This module provides scope highlighting by drawing colored lines or blocks aligned to the scope indentation of the scopes surrounding the cursor.
Line mode on the left, block mode on the right.
This was tested with 4coder 4.1.7.
Make sure that use_scope_highlight
is set to true in config.4coder
.
You need to #include this file in your custom layer (4coder_default_bindings.cpp
by default) below the line:
1 | #include "4coder_default_include.cpp" |
You need to call the function scope_highlight_draw
from default_render_buffer
in 4coder_default_hooks.cpp
instead of draw_scope_highlight
. The function has a slightly different signature: it doesn't take colors
and color_count
as arguments, instead it takes the view id and a boolean to choose between line and block mode.
The call should look like this:
1 | scope_highlight_draw( app, buffer, text_layout_id, cursor_pos, view_id, false ); |
You'll need to insert the following function prototype above the declaration of default_render_buffer
:
1 | function void scope_highlight_draw( Application_Links *app, Buffer_ID buffer, Text_Layout_ID text_layout_id, i64 pos, View_ID view, b32 block_mode ); |
The line highlight, by default will be drawn on top of the scope highlight. To change that you can move the code that draws the line highlight above the code that draws the scope highlight in default_render_buffer
. Note that this works great in line mode
, but in block mode
it will make the line highlight invisible, since the blocks will be drawn on top of it.
Add those lines in your theme file to change the colors.
1 2 | scope_highlight_line_cycle = { 0xfff048be, 0xfff07a48, 0xffbef048, 0xff48f07a, 0xff48bef0, 0xff7a48f0 }; scope_highlight_block_cycle = { 0x3ff048be, 0x3ff07a48, 0x3fbef048, 0x3f48f07a, 0x3f48bef0, 0x3f7a48f0 }; |
If all scopes are colored colored purple, make sure the theme file is loaded. The full theme file name needs to be set in config.4coder
, which by default isn't the case. Use :
1 | default_theme_name = "theme-4coder"; |
instead of
1 | default_theme_name = "4coder"; |
This module uses scope_highlight
as a prefix for its types and functions.
This module declares the following managed ids:
In the colors
group:
scope_highlight_line_cycle
;scope_highlight_block_cycle
;This module needs modifications in the following files to work:
4coder_default_bindings.h
or your custom layer file;4coder_default_hooks.h
;This module doesn't use any global variables.
This module doesn't declare any types.
This module declare the following function:
scope_highlight_draw
;This module doesn't declare any scope attachment.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | /* # Description This module provides scope highlighting by drawing colored lines or blocks aligned to the scope indentation of the scopes surrounding the cursor. # Version This was tested with 4coder 4.1.7. # Setup Make sure that 'use_scope_highlight' is set to true in 'config.4coder'. You need to #include this file in your custom layer ('4coder_default_bindings.cpp' by default) below the line: '''c #include "4coder_default_include.cpp" ''' You need to call the function 'scope_highlight_draw' from 'default_render_buffer' in '4coder_default_hooks.cpp' instead of 'draw_scope_highlight'. The function has a slightly different signature: it doesn't take 'colors' and 'color_count' as arguments, instead it takes the view id and a boolean to choose between line and block mode. The call should look like this: '''c scope_highlight_draw( app, buffer, text_layout_id, cursor_pos, view_id, false ); ''' You'll need to insert the following function prototype above the declaration of 'default_render_buffer': '''c function void scope_highlight_draw( Application_Links *app, Buffer_ID buffer, Text_Layout_ID text_layout_id, i64 pos, View_ID view, b32 block_mode ); ''' The line highlight, by default will be drawn on top of the scope highlight. To change that you can move the code that draws the line highlight above the code that draws the scope highlight in 'default_render_buffer'. Note that this works great in 'line mode', but in 'block mode' it will make the line highlight invisible, since the blocks will be drawn on top of it. Add those lines in your theme file to change the colors. '''c scope_highlight_line_cycle = { 0xfff048be, 0xfff07a48, 0xffbef048, 0xff48f07a, 0xff48bef0, 0xff7a48f0 }; scope_highlight_block_cycle = { 0x3ff048be, 0x3ff07a48, 0x3fbef048, 0x3f48f07a, 0x3f48bef0, 0x3f7a48f0 }; ''' # Issues If all scopes are colored colored purple, make sure the theme file is loaded. The full theme file name needs to be set in 'config.4coder', which by default isn't the case. Use : '''c default_theme_name = "theme-4coder"; ''' instead of '''c default_theme_name = "4coder"; ''' # Details ## Prefix This module uses 'scope_highlight' as a prefix for its types and functions. ## Ids This module declares the following managed ids: In the 'colors' group: - 'scope_highlight_line_cycle'; - 'scope_highlight_block_cycle'; ## Modified files This module needs modifications in the following files to work: - '4coder_default_bindings.h' or your custom layer file; - '4coder_default_hooks.h'; ## Global variables This module doesn't use any global variables. ## Types This module doesn't declare any types. ## Functions This module declare the following function: - 'scope_highlight_draw'; ## Scope attachment This module doesn't declare any scope attachment. */ CUSTOM_ID( colors, scope_highlight_line_cycle ); CUSTOM_ID( colors, scope_highlight_block_cycle ); function void scope_highlight_draw( Application_Links *app, Buffer_ID buffer, Text_Layout_ID text_layout_id, i64 pos, View_ID view, b32 block_mode ) { ProfileScope( app, "scope_highlight" ); Scratch_Block scratch( app ); ProfileBlockNamed( app, "get enclosure ranges", scope_highlight_get_enclosure_range ); Range_i64_Array ranges = get_enclosure_ranges( app, scratch, buffer, pos, FindNest_Scope ); ProfileCloseNow( scope_highlight_get_enclosure_range ); if ( ranges.count ) { Face_ID face_id = get_face_id( app, buffer ); Face_Metrics metrics = get_face_metrics( app, face_id ); Rect_f32 region = text_layout_region( app, text_layout_id ); Range_i64 visible_range = text_layout_get_visible_range( app, text_layout_id ); i64 indent_space_count = def_get_config_u64( app, vars_save_string_lit( "indent_width" ) ); if ( def_get_config_b32( vars_save_string_lit( "enable_virtual_whitespace" ) ) ) { indent_space_count = def_get_config_u64( app, vars_save_string_lit( "virtual_whitespace_regular_indent" ) ); } Buffer_Scroll scroll = view_get_buffer_scroll( app, view ); f32 x_start = region.x0 - scroll.position.pixel_shift.x; Color_Array colors = finalize_color_array( scope_highlight_line_cycle ); i32 color_index = 0; if ( block_mode ) { colors = finalize_color_array( scope_highlight_block_cycle ); } ProfileScope( app, "Ranges loop" ); for ( i32 i = ranges.count - 1; i >= 0; i -= 1 ) { Range_i64 range = ranges.ranges[ i ]; i64 start = range.min; i64 end = range.max - 1; i64 start_line = get_line_number_from_pos( app, buffer, start ); i64 end_line = get_line_number_from_pos( app, buffer, end ); Rect_f32 rect = { 0 }; if ( start_line == end_line ) { Rect_f32 min_rect = text_layout_character_on_screen( app, text_layout_id, start ); Rect_f32 max_rect = text_layout_character_on_screen( app, text_layout_id, end ); rect = Rf32( min_rect.x1, min_rect.y1 + 1, max_rect.x0, min_rect.y1 + 2 ); } else { i64 space_count = indent_space_count * ( ranges.count - 1 - i ); /* +1 to avoid having the first line against the panel border. */ rect.x0 = x_start + 1 + space_count * metrics.space_advance; if ( block_mode ) { rect.x1 = region.x1; } else { rect.x1 = rect.x0 + 1; } if ( range.max - 1 > visible_range.min && range.min < visible_range.max ) { // i64 unwrapped_start = get_start_of_textual_line_pos_from_pos( app, view, buffer, range.min ); /* Get the start position of the textual line. */ i64 new_pos = get_line_side_pos_from_pos( app, buffer, range.min, Side_Min ); Buffer_Cursor cursor = view_compute_cursor( app, view, seek_pos( new_pos ) ); Vec2_f32 p = view_relative_xy_of_pos( app, view, cursor.line, cursor.pos ); i64 unwrapped_start = view_pos_at_relative_xy( app, view, cursor.line, p ); if ( unwrapped_start < visible_range.min ) { unwrapped_start = range.min; } if ( unwrapped_start < visible_range.min ) { rect.y0 = region.y0; } else { rect.y0 = text_layout_character_on_screen( app, text_layout_id, unwrapped_start ).y0 + metrics.line_height; } if ( range.max - 1 > visible_range.max ) { rect.y1 = region.y1; } else { rect.y1 = text_layout_character_on_screen( app, text_layout_id, range.max - 1 ).y1 - metrics.line_height; } } } if ( rect.x0 < rect.x1 && rect.y0 < rect.y1 ) { draw_rectangle( app, rect, 0, colors.vals[ color_index % colors.count ] ); } color_index += 1; } } } |