Fix horizontal chunk movement

The current horizontal chunk motion (ctrl + left/right arrow by default) does not work like most other editors, subverting the users expectation. The behaviour of most editors from my experience is as follows:
1. Skip any leading whitespace in the motion
2. If the next char is:
    - Alphanumeric or `_`, move up until the next symbol that isn't one of those
    - not one of the above move either up until: the next whitespace character or the same rules as above if an alphanumeric or `_` is encountered before whitespace.

e.g. Assume the current cursor position and string `... |mystruct.member ...`
The current code will move to the end of the whole struct accessor: `... mystruct.member| ...`
Most other editors would move to the end of the struct name: `... mystruct|.member ...`
In this case the current behaviour may not seem _that_ agregious, but in other cases its much more annoying
especially if you're looking to copy into a watch window or something as in this case:
`|ui_nav_scanned_column_from_column(String8 string, ...)`
the cursor will move to: `ui_nav_scanned_column_from_column(String8| string, ...)`
which is almost certainly not what the user wanted.

This behaviour means that if you want to copy a symbol, you can consistantly achieve this by chunk moving to one end, pressing shift, then chunk moving to the other end without ever getting extra symbols/whitespace. This is currently not possible with existing chunk motions.
This commit is contained in:
Jack Punter
2024-01-13 23:29:09 +00:00
committed by Ryan Fleury
parent c0322437d6
commit 3917218a4e
+18 -13
View File
@@ -115,11 +115,10 @@ ui_nav_eat_action_node(UI_NavActionList *list, UI_NavActionNode *node)
////////////////////////////////
//~ rjf: High Level Navigation Action => Text Operations
internal B32
ui_nav_char_is_scan_boundary(U8 c)
ui_nav_char_is_code_symbol(U8 c)
{
return char_is_space(c) || char_is_slash(c);
return (char_is_alpha(c) || char_is_digit(c, 10) || c == '_');
}
internal S64
@@ -127,20 +126,26 @@ ui_nav_scanned_column_from_column(String8 string, S64 start_column, Side side)
{
S64 new_column = start_column;
S64 delta = (!!side)*2 - 1;
B32 found_boundary = 0;
for(S64 col = start_column+delta; 1 <= col && col <= string.size+1; col += delta)
B32 found_text = 0;
B32 found_non_space = 0;
S64 start_off = delta < 0 ? delta : 0;
for(S64 col = start_column+start_off; 1 <= col && col <= string.size+1; col += delta)
{
U8 byte = (col <= string.size) ? string.str[col-1] : 0;
B32 is_boundary = (ui_nav_char_is_scan_boundary(byte) ^ !(side == Side_Max));
if((found_boundary && !is_boundary) ||
(col == 1 || col == string.size+1))
B32 is_non_space = !char_is_space(byte);
B32 is_name = ui_nav_char_is_code_symbol(byte);
if (((side == Side_Min) && (col == 1)) ||
((side == Side_Max) && (col == string.size+1)) ||
(found_non_space && !is_non_space) ||
(found_text && !is_name))
{
new_column = col + (!side && col != 1);
new_column = col + (!side && col != 1);
break;
}
else if(!found_boundary && is_boundary)
{
found_boundary = 1;
} else if (!found_text && is_name) {
found_text = 1;
} else if (!found_non_space && is_non_space ) {
found_non_space = 1;
}
}
return new_column;