Compare commits

...

5 Commits

9 changed files with 436 additions and 324 deletions

View File

@ -11,12 +11,12 @@ write_text(Application_Links *app, String_Const_u8 insert){
if (insert.str != 0 && insert.size > 0){
View_ID view = get_active_view(app, Access_ReadWriteVisible);
if_view_has_highlighted_range_delete_range(app, view);
i64 pos = view_get_cursor_pos(app, view);
pos = view_get_character_legal_pos_from_pos(app, view, pos);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible);
// NOTE(allen): consecutive inserts merge logic
History_Record_Index first_index = buffer_history_get_current_state_index(app, buffer);
b32 do_merge = false;
@ -39,16 +39,16 @@ write_text(Application_Links *app, String_Const_u8 insert){
}
}
}
// NOTE(allen): perform the edit
b32 edit_success = buffer_replace_range(app, buffer, Ii64(pos), insert);
// NOTE(allen): finish merging records if necessary
if (do_merge){
History_Record_Index last_index = buffer_history_get_current_state_index(app, buffer);
buffer_history_merge_record_range(app, buffer, first_index, last_index, RecordMergeFlag_StateInRange_MoveStateForward);
}
// NOTE(allen): finish updating the cursor
if (edit_success){
view_set_cursor_and_preferred_x(app, view, seek_pos(pos + insert.size));
@ -160,7 +160,7 @@ CUSTOM_DOC("Delete characters between the cursor position and the first alphanum
}
function i64
get_boundary_token_or_whitespace(Application_Links *app, Buffer_ID buffer,
get_boundary_token_or_whitespace(Application_Links *app, Buffer_ID buffer,
Side side, Scan_Direction direction, i64 pos)
{
// NOTE(PS): originally this was F4_Boundary_TokenAndWhitespace
@ -176,12 +176,12 @@ get_boundary_token_or_whitespace(Application_Links *app, Buffer_ID buffer,
{
Token_Iterator_Array it = token_iterator_pos(0, &tokens, pos);
Token *token = token_it_read(&it);
if(token == 0)
{
break;
}
// NOTE(rjf): Comments/Strings
if(token->kind == TokenBaseKind_Comment ||
token->kind == TokenBaseKind_LiteralString)
@ -189,7 +189,7 @@ get_boundary_token_or_whitespace(Application_Links *app, Buffer_ID buffer,
result = boundary_non_whitespace(app, buffer, side, direction, pos);
break;
}
// NOTE(rjf): All other cases.
else
{
@ -198,10 +198,10 @@ get_boundary_token_or_whitespace(Application_Links *app, Buffer_ID buffer,
// token_it_inc_non_whitespace(&it);
// token = token_it_read(&it);
}
if (side == Side_Max){
result = token->pos + token->size;
token_it_inc_all(&it);
Token *ws = token_it_read(&it);
if(ws != 0 && ws->kind == TokenBaseKind_Whitespace &&
@ -221,32 +221,32 @@ get_boundary_token_or_whitespace(Application_Links *app, Buffer_ID buffer,
}
}
}
}
}break;
case Scan_Backward:
{
result = 0;
if (tokens.count > 0){
Token_Iterator_Array it = token_iterator_pos(0, &tokens, pos);
Token *token = token_it_read(&it);
Token_Iterator_Array it2 = it;
token_it_dec_non_whitespace(&it2);
Token *token2 = token_it_read(&it2);
// NOTE(rjf): Comments/Strings
if(token->kind == TokenBaseKind_Comment ||
token->kind == TokenBaseKind_LiteralString ||
(token2 &&
(token2 &&
token2->kind == TokenBaseKind_Comment ||
token2->kind == TokenBaseKind_LiteralString))
{
result = boundary_non_whitespace(app, buffer, side, direction, pos);
break;
}
if (token->kind == TokenBaseKind_Whitespace){
token_it_dec_non_whitespace(&it);
token = token_it_read(&it);
@ -724,7 +724,7 @@ clean_all_lines_buffer(Application_Links *app, Buffer_ID buffer, Clean_All_Lines
Scratch_Block scratch(app);
Batch_Edit *batch_first = 0;
Batch_Edit *batch_last = 0;
i64 line_count = buffer_get_line_count(app, buffer);
for (i64 line_number = 1; line_number <= line_count; line_number += 1){
i64 line_start = get_line_side_pos(app, buffer, line_number, Side_Min);
@ -759,11 +759,11 @@ clean_all_lines_buffer(Application_Links *app, Buffer_ID buffer, Clean_All_Lines
break;
}
}
if (mode == CleanAllLinesMode_RemoveBlankLines || start_offset > 0){
i64 start = start_offset + line_start;
i64 end = end_offset + line_start;
Batch_Edit *batch = push_array(scratch, Batch_Edit, 1);
sll_queue_push(batch_first, batch_last, batch);
batch->edit.text = SCu8();
@ -772,7 +772,7 @@ clean_all_lines_buffer(Application_Links *app, Buffer_ID buffer, Clean_All_Lines
}
}
}
if (batch_first != 0){
buffer_batch_edit(app, buffer, batch_first);
}
@ -865,7 +865,7 @@ CUSTOM_DOC("Set face size of the face used by the current buffer.")
Buffer_ID buffer = view_get_buffer(app, view, Access_Always);
Face_ID face_id = get_face_id(app, buffer);
Face_Description description = get_face_description(app, face_id);
Query_Bar_Group group(app);
u8 string_space[256];
Query_Bar bar = {};
@ -906,7 +906,7 @@ CUSTOM_DOC("Set face size of the face used by the current buffer; if any other b
View_ID view = get_active_view(app, Access_Always);
Buffer_ID buffer = view_get_buffer(app, view, Access_Always);
Face_ID face_id = get_face_id(app, buffer);
b32 is_shared = false;
for (Buffer_ID buf_it = get_buffer_next(app, 0, Access_Always);
buf_it != 0;
@ -919,7 +919,7 @@ CUSTOM_DOC("Set face size of the face used by the current buffer; if any other b
is_shared = true;
}
}
if (is_shared){
Face_Description description = get_face_description(app, face_id);
face_id = try_create_new_face(app, &description);
@ -927,7 +927,7 @@ CUSTOM_DOC("Set face size of the face used by the current buffer; if any other b
buffer_set_face(app, buffer, face_id);
}
}
set_face_size(app);
}
@ -1019,35 +1019,35 @@ isearch(Application_Links *app, Scan_Direction start_scan, i64 first_pos,
if (!buffer_exists(app, buffer)){
return;
}
i64 buffer_size = buffer_get_size(app, buffer);
Query_Bar_Group group(app);
Query_Bar bar = {};
if (start_query_bar(app, &bar, 0) == 0){
return;
}
Vec2_f32 old_margin = {};
Vec2_f32 old_push_in = {};
view_get_camera_bounds(app, view, &old_margin, &old_push_in);
Vec2_f32 margin = old_margin;
margin.y = clamp_bot(200.f, margin.y);
view_set_camera_bounds(app, view, margin, old_push_in);
Scan_Direction scan = start_scan;
i64 pos = first_pos;
u8 bar_string_space[256];
bar.string = SCu8(bar_string_space, query_init.size);
block_copy(bar.string.str, query_init.str, query_init.size);
String_Const_u8 isearch_str = string_u8_litexpr("I-Search: ");
String_Const_u8 rsearch_str = string_u8_litexpr("Reverse-I-Search: ");
u64 match_size = bar.string.size;
User_Input in = {};
for (;;){
switch (scan){
@ -1061,14 +1061,14 @@ isearch(Application_Links *app, Scan_Direction start_scan, i64 first_pos,
}break;
}
isearch__update_highlight(app, view, Ii64_size(pos, match_size));
in = get_next_input(app, EventPropertyGroup_Any, EventProperty_Escape);
if (in.abort){
break;
}
String_Const_u8 string = to_writable(&in);
b32 string_change = false;
if (match_key_code(&in, KeyCode_Return) ||
match_key_code(&in, KeyCode_Tab)){
@ -1104,7 +1104,7 @@ isearch(Application_Links *app, Scan_Direction start_scan, i64 first_pos,
}
}
}
b32 do_scan_action = false;
b32 do_scroll_wheel = false;
Scan_Direction change_scan = scan;
@ -1150,7 +1150,7 @@ isearch(Application_Links *app, Scan_Direction start_scan, i64 first_pos,
}
}
}
if (string_change){
switch (scan){
case Scan_Forward:
@ -1162,7 +1162,7 @@ isearch(Application_Links *app, Scan_Direction start_scan, i64 first_pos,
match_size = bar.string.size;
}
}break;
case Scan_Backward:
{
i64 new_pos = 0;
@ -1186,7 +1186,7 @@ isearch(Application_Links *app, Scan_Direction start_scan, i64 first_pos,
match_size = bar.string.size;
}
}break;
case Scan_Backward:
{
i64 new_pos = 0;
@ -1202,9 +1202,9 @@ isearch(Application_Links *app, Scan_Direction start_scan, i64 first_pos,
mouse_wheel_scroll(app);
}
}
view_disable_highlight_range(app, view);
if (in.abort){
u64 size = bar.string.size;
size = clamp_top(size, sizeof(previous_isearch_query) - 1);
@ -1212,7 +1212,7 @@ isearch(Application_Links *app, Scan_Direction start_scan, i64 first_pos,
previous_isearch_query[size] = 0;
view_set_cursor_and_preferred_x(app, view, seek_pos(first_pos));
}
view_set_camera_bounds(app, view, old_margin, old_push_in);
}
@ -1278,13 +1278,13 @@ query_user_replace_pair(Application_Links *app, Arena *arena){
replace->prompt = string_u8_litexpr("Replace: ");
replace->string = SCu8(replace_space, (u64)0);
replace->string_capacity = KB(1);
Query_Bar *with = push_array(arena, Query_Bar, 1);
u8 *with_space = push_array(arena, u8, KB(1));
with->prompt = string_u8_litexpr("With: ");
with->string = SCu8(with_space, (u64)0);
with->string_capacity = KB(1);
String_Pair result = {};
if (query_user_string(app, replace) && replace->string.size != 0 && query_user_string(app, with)){
result.valid = true;
@ -1328,7 +1328,7 @@ CUSTOM_COMMAND_SIG(replace_in_all_buffers)
CUSTOM_DOC("Queries the user for a needle and string. Replaces all occurences of needle with string in all editable buffers.")
{
global_history_edit_group_begin(app);
Scratch_Block scratch(app);
Query_Bar_Group group(app);
String_Pair pair = query_user_replace_pair(app, scratch);
@ -1338,7 +1338,7 @@ CUSTOM_DOC("Queries the user for a needle and string. Replaces all occurences of
Range_i64 range = buffer_range(app, buffer);
replace_in_range(app, buffer, range, pair.a, pair.b);
}
global_history_edit_group_end(app);
}
@ -1346,17 +1346,17 @@ function void
query_replace_base(Application_Links *app, View_ID view, Buffer_ID buffer_id, i64 pos, String_Const_u8 r, String_Const_u8 w){
i64 new_pos = 0;
seek_string_forward(app, buffer_id, pos - 1, 0, r, &new_pos);
User_Input in = {};
for (;;){
Range_i64 match = Ii64(new_pos, new_pos + r.size);
isearch__update_highlight(app, view, match);
in = get_next_input(app, EventProperty_AnyKey, EventProperty_MouseButton);
if (in.abort || match_key_code(&in, KeyCode_Escape) || !is_unmodified_key(&in.event)){
break;
}
i64 size = buffer_get_size(app, buffer_id);
if (match.max <= size &&
(match_key_code(&in, KeyCode_Y) ||
@ -1368,16 +1368,16 @@ query_replace_base(Application_Links *app, View_ID view, Buffer_ID buffer_id, i6
else{
pos = match.max;
}
seek_string_forward(app, buffer_id, pos, 0, r, &new_pos);
}
view_disable_highlight_range(app, view);
if (in.abort){
return;
}
view_set_cursor_and_preferred_x(app, view, seek_pos(pos));
}
@ -1387,29 +1387,29 @@ query_replace_parameter(Application_Links *app, String_Const_u8 replace_str, i64
Query_Bar replace = {};
replace.prompt = string_u8_litexpr("Replace: ");
replace.string = replace_str;
if (add_replace_query_bar){
start_query_bar(app, &replace, 0);
}
Query_Bar with = {};
u8 with_space[1024];
with.prompt = string_u8_litexpr("With: ");
with.string = SCu8(with_space, (u64)0);
with.string_capacity = sizeof(with_space);
if (query_user_string(app, &with)){
String_Const_u8 r = replace.string;
String_Const_u8 w = with.string;
View_ID view = get_active_view(app, Access_ReadVisible);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible);
i64 pos = start_pos;
Query_Bar bar = {};
bar.prompt = string_u8_litexpr("Replace? (y)es, (n)ext, (esc)\n");
start_query_bar(app, &bar, 0);
query_replace_base(app, view, buffer, pos, r, w);
}
}
@ -1475,7 +1475,7 @@ CUSTOM_DOC("Read from the top of the point stack and jump there; if already ther
if (view != 0){
Buffer_ID buffer = view_get_buffer(app, view, Access_Always);
i64 pos = view_get_cursor_pos(app, view);
for (;;){
Buffer_ID stack_buffer = 0;
i64 stack_pos = 0;
@ -1540,14 +1540,14 @@ CUSTOM_DOC("Deletes the file of the current buffer if 4coder has the appropriate
delete_file_base(app, file_name, buffer);
cancelled = true;
}break;
case KeyCode_Shift:
case KeyCode_Control:
case KeyCode_Alt:
case KeyCode_Command:
case KeyCode_CapsLock:
{}break;
default:
{
cancelled = true;
@ -1564,11 +1564,11 @@ CUSTOM_DOC("Queries the user for a file name and saves the contents of the curre
{
View_ID view = get_active_view(app, Access_Always);
Buffer_ID buffer = view_get_buffer(app, view, Access_Always);
Scratch_Block scratch(app);
Query_Bar_Group group(app);
String_Const_u8 buffer_name = push_buffer_unique_name(app, scratch, buffer);
// Query the user
u8 name_space[4096];
Query_Bar bar = {};
@ -1597,9 +1597,9 @@ CUSTOM_DOC("Queries the user for a new name and renames the file of the current
{
View_ID view = get_active_view(app, Access_Always);
Buffer_ID buffer = view_get_buffer(app, view, Access_Always);
Scratch_Block scratch(app);
String_Const_u8 file_name = push_buffer_file_name(app, scratch, buffer);
if (file_name.size > 0){
// Query the user
@ -1631,9 +1631,9 @@ CUSTOM_COMMAND_SIG(make_directory_query)
CUSTOM_DOC("Queries the user for a name and creates a new directory with the given name.")
{
Scratch_Block scratch(app);
String_Const_u8 hot = push_hot_directory(app, scratch);
// Query the user
Query_Bar_Group group(app);
u8 name_space[4096];
@ -1641,10 +1641,10 @@ CUSTOM_DOC("Queries the user for a name and creates a new directory with the giv
bar.prompt = push_u8_stringf(scratch, "Make directory at '%.*s': ", string_expand(hot));
bar.string = SCu8(name_space, (u64)0);
bar.string_capacity = sizeof(name_space);
if (!query_user_string(app, &bar)) return;
if (bar.string.size == 0) return;
String_Const_u8 cmd = push_u8_stringf(scratch, "mkdir %.*s", string_expand(bar.string));
exec_system_command(app, 0, buffer_identifier(0), hot, cmd, 0);
}
@ -1715,19 +1715,19 @@ CUSTOM_DOC("Deletes all text from the cursor to the end of the line")
i64 line_number = get_line_number_from_pos(app, buffer, pos);
Range_Cursor line_range = get_line_range(app, buffer, line_number);
Range_i64 delete_range = {};
if (line_range.start.line != 0 && line_range.end.line != 0)
{
delete_range = Ii64(pos, line_range.end.pos);
}
if (range_size(delete_range) == 0)
{
delete_range.end += 1;
i32 buffer_size = (i32)buffer_get_size(app, buffer);
delete_range.end = clamp_top(delete_range.end, buffer_size);
}
buffer_replace_range(app, buffer, delete_range, string_u8_litexpr(""));
}
@ -1740,22 +1740,22 @@ CUSTOM_DOC("Reads a filename from surrounding '\"' characters and attempts to op
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible);
if (buffer_exists(app, buffer)){
Scratch_Block scratch(app);
i64 pos = view_get_cursor_pos(app, view);
Range_i64 range = enclose_pos_inside_quotes(app, buffer, pos);
String_Const_u8 quoted_name = push_buffer_range(app, scratch, buffer, range);
String_Const_u8 file_name = push_buffer_file_name(app, scratch, buffer);
String_Const_u8 path = string_remove_last_folder(file_name);
if (character_is_slash(string_get_character(path, path.size - 1))){
path = string_chop(path, 1);
}
String_Const_u8 new_file_name = push_u8_stringf(scratch, "%.*s/%.*s", string_expand(path), string_expand(quoted_name));
view = get_next_view_looped_primary_panels(app, view, Access_Always);
if (view != 0){
if (view_open_file(app, view, new_file_name, true)){
@ -1792,7 +1792,7 @@ get_cpp_matching_file(Application_Links *app, Buffer_ID buffer, Buffer_ID *buffe
new_extensions[0] = string_u8_litexpr("cpp");
new_extensions_count = 1;
}
String_Const_u8 file_without_extension = string_file_without_extension(file_name);
for (i32 i = 0; i < new_extensions_count; i += 1){
Temp_Memory temp = begin_temp(scratch);
@ -1804,7 +1804,7 @@ get_cpp_matching_file(Application_Links *app, Buffer_ID buffer, Buffer_ID *buffe
}
end_temp(temp);
}
if (!result && new_extensions_count > 0){
String_Const_u8 new_file_name = push_u8_stringf(scratch, "%.*s.%.*s", string_expand(file_without_extension), string_expand(new_extensions[0]));
if (open_file(app, buffer_out, new_file_name, false, false)){
@ -1812,7 +1812,7 @@ get_cpp_matching_file(Application_Links *app, Buffer_ID buffer, Buffer_ID *buffe
}
}
}
return(result);
}
@ -1850,15 +1850,15 @@ CUSTOM_DOC("Swaps the active panel with it's sibling.")
for (;parent != 0;){
Panel_ID child_1 = panel_get_child(app, parent, Side_Min);
Panel_ID child_2 = panel_get_child(app, parent, Side_Max);
View_ID view_1 = panel_get_view(app, child_1, Access_Always);
View_ID view_2 = panel_get_view(app, child_2, Access_Always);
if (!view_get_is_passive(app, view_1) && !view_get_is_passive(app, view_2)){
panel_swap_children(app, parent);
break;
}
parent = panel_get_parent(app, parent);
}
}
@ -1997,12 +1997,12 @@ CUSTOM_DOC("Advances backwards through the undo history of the current buffer.")
View_ID view = get_active_view(app, Access_ReadWriteVisible);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible);
undo__flush_fades(app, buffer);
History_Record_Index current = buffer_history_get_current_state_index(app, buffer);
if (current > 0){
Record_Info record = buffer_history_get_record_info(app, buffer, current);
i64 new_position = record_get_new_cursor_position_undo(app, buffer, current, record);
b32 do_immedite_undo = true;
f32 undo_fade_time = 0.33f;
b32 enable_undo_fade_out = def_get_config_b32(vars_save_string_lit("enable_undo_fade_out"));
@ -2029,7 +2029,7 @@ CUSTOM_DOC("Advances backwards through the undo history of the current buffer.")
}
}
}
if (do_immedite_undo){
buffer_history_set_current_state_index(app, buffer, current - 1);
if (record.single_string_backward.size > 0){
@ -2038,7 +2038,7 @@ CUSTOM_DOC("Advances backwards through the undo history of the current buffer.")
buffer_post_fade(app, buffer, undo_fade_time, range, color);
}
}
view_set_cursor_and_preferred_x(app, view, seek_pos(new_position));
}
}
@ -2049,22 +2049,22 @@ CUSTOM_DOC("Advances forwards through the undo history of the current buffer.")
View_ID view = get_active_view(app, Access_ReadWriteVisible);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible);
undo__flush_fades(app, buffer);
History_Record_Index current = buffer_history_get_current_state_index(app, buffer);
History_Record_Index max_index = buffer_history_get_max_record_index(app, buffer);
if (current < max_index){
Record_Info record = buffer_history_get_record_info(app, buffer, current);
Record_Info record = buffer_history_get_record_info(app, buffer, current+1);
i64 new_position = record_get_new_cursor_position_redo(app, buffer, current + 1, record);
buffer_history_set_current_state_index(app, buffer, current + 1);
if (record.single_string_forward.size > 0){
Range_i64 range = Ii64_size(record.single_first, record.single_string_forward.size);
ARGB_Color color = fcolor_resolve(fcolor_id(defcolor_undo));
f32 undo_fade_time = 0.33f;
buffer_post_fade(app, buffer, undo_fade_time, range, color);
}
view_set_cursor_and_preferred_x(app, view, seek_pos(new_position));
}
}
@ -2077,7 +2077,7 @@ CUSTOM_DOC("Advances backward through the undo history in the buffer containing
Buffer_ID first_buffer_match = 0;
Buffer_ID last_buffer_match = 0;
i32 match_count = 0;
{
for (Buffer_ID buffer = get_buffer_next(app, 0, Access_Always);
buffer != 0;
@ -2098,11 +2098,11 @@ CUSTOM_DOC("Advances backward through the undo history in the buffer containing
}
}
}
Buffer_ID *match_buffers = push_array(scratch, Buffer_ID, match_count);
i64 *new_positions = push_array(scratch, i64, match_count);
match_count = 0;
if (highest_edit_number != -1){
for (Buffer_ID buffer = first_buffer_match;
buffer != 0;
@ -2136,7 +2136,7 @@ CUSTOM_DOC("Advances backward through the undo history in the buffer containing
}
}
}
view_buffer_set(app, match_buffers, new_positions, match_count);
}
@ -2144,12 +2144,12 @@ CUSTOM_COMMAND_SIG(redo_all_buffers)
CUSTOM_DOC("Advances forward through the undo history in the buffer containing the most recent regular edit.")
{
Scratch_Block scratch(app);
i32 lowest_edit_number = 0x7FFFFFFF;
Buffer_ID first_buffer_match = 0;
Buffer_ID last_buffer_match = 0;
i32 match_count = 0;
{
for (Buffer_ID buffer = get_buffer_next(app, 0, Access_Always);
buffer != 0;
@ -2171,11 +2171,11 @@ CUSTOM_DOC("Advances forward through the undo history in the buffer containing t
}
}
}
Buffer_ID *match_buffers = push_array(scratch, Buffer_ID, match_count);
i64 *new_positions = push_array(scratch, i64, match_count);
match_count = 0;
if (lowest_edit_number != -1){
for (Buffer_ID buffer = first_buffer_match;
buffer != 0;
@ -2210,7 +2210,7 @@ CUSTOM_DOC("Advances forward through the undo history in the buffer containing t
}
}
}
view_buffer_set(app, match_buffers, new_positions, match_count);
}
@ -2259,10 +2259,10 @@ reindent_line(Application_Links *app, Buffer_ID buffer, i64 line, i64 indent_del
{
Scratch_Block scratch(app);
View_ID view = get_active_view(app, Access_ReadWriteVisible);
String_Const_u8 line_string = push_buffer_line(app, scratch, buffer, line);
i64 line_start_pos = get_line_start_pos(app, buffer, line);
Range_i64 line_indent_range = Ii64(0, 0);
i64 tabs_at_beginning = 0;
i64 spaces_at_beginning = 0;
@ -2282,7 +2282,7 @@ reindent_line(Application_Links *app, Buffer_ID buffer, i64 line, i64 indent_del
break;
}
}
// NOTE(PS): This is in the event that we are unindenting a line that
// is JUST tabs or spaces - rather than unindenting nothing
// and then reindenting the proper amount, this should cause
@ -2294,7 +2294,7 @@ reindent_line(Application_Links *app, Buffer_ID buffer, i64 line, i64 indent_del
line_indent_range.max = line_string.size;
place_cursor_at_end = true;
}
// NOTE(rjf): Indent lines.
{
Range_i64 indent_range =
@ -2302,13 +2302,13 @@ reindent_line(Application_Links *app, Buffer_ID buffer, i64 line, i64 indent_del
line_indent_range.min + line_start_pos,
line_indent_range.max + line_start_pos,
};
i64 indent_width = (i64)def_get_config_u64(app, vars_save_string_lit("indent_width"));
b32 indent_with_tabs = def_get_config_b32(vars_save_string_lit("indent_with_tabs"));
i64 spaces_per_indent_level = indent_width;
i64 indent_level = spaces_at_beginning / spaces_per_indent_level + tabs_at_beginning;
i64 new_indent_level = indent_level + indent_delta;
String_Const_u8 indent_string;
if (indent_with_tabs) {
indent_string = str8_lit("\t");
@ -2320,18 +2320,18 @@ reindent_line(Application_Links *app, Buffer_ID buffer, i64 line, i64 indent_del
{
buffer_replace_range(app, buffer, Ii64(line_start_pos), indent_string);
}
if (place_cursor_at_end)
{
// update line_string now that we've edited the line
line_string = push_buffer_line(app, scratch, buffer, line);
line_start_pos = get_line_start_pos(app, buffer, line);
i64 line_end_pos = line_start_pos + line_string.size;
view_set_cursor(app, view, seek_pos(line_end_pos));
}
}
}
internal void
@ -2405,7 +2405,7 @@ adjust_cursor_and_mark_for_indentation(Application_Links *app, View_ID view, i64
break;
}
}
view_set_cursor(app, view, seek_pos(new_pos));
view_set_mark(app, view, seek_pos(new_pos));
}
@ -2447,7 +2447,7 @@ CUSTOM_COMMAND_SIG(unindent_range)
CUSTOM_COMMAND_SIG(indent_or_autocomplete)
{
Scratch_Block scratch(app);
View_ID view = get_active_view(app, Access_ReadVisible);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible);
if (buffer != 0)
@ -2492,7 +2492,7 @@ CUSTOM_COMMAND_SIG(input_enter_behavior)
}
else
{
leave_current_input_unhandled(app);
}
}

View File

@ -123,6 +123,85 @@ CUSTOM_COMMAND_SIG(cmd_alt_enter_behavior)
}
}
function i64
qol_seek_char(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 start_pos, u8 target_char){
Scratch_Block scratch(app);
i64 line = get_line_number_from_pos(app, buffer, start_pos);
Range_i64 range = get_line_pos_range(app, buffer, line);
range.max += 1;
String_Const_u8 string = push_buffer_range(app, scratch, buffer, range);
i64 pos = start_pos;
while(range_contains(range, pos)){
pos += direction;
u8 current_char = string.str[pos - range.min];
if (current_char == target_char){ return pos; }
}
return start_pos;
}
CUSTOM_COMMAND_SIG(qol_char_forward)
CUSTOM_DOC("[QOL] Seeks forward in current line to the selected char")
{
View_ID view = get_active_view(app, Access_ReadVisible);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible);
i64 cursor_pos = view_get_cursor_pos(app, view);
i64 pos = qol_seek_char(app, buffer, Scan_Forward, cursor_pos, qol_target_char);
view_set_cursor_and_preferred_x(app, view, seek_pos(pos));
}
CUSTOM_COMMAND_SIG(qol_char_backward)
CUSTOM_DOC("[QOL] Seeks back in current line to the selected char")
{
View_ID view = get_active_view(app, Access_ReadVisible);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible);
i64 cursor_pos = view_get_cursor_pos(app, view);
i64 pos = qol_seek_char(app, buffer, Scan_Backward, cursor_pos, qol_target_char);
view_set_cursor_and_preferred_x(app, view, seek_pos(pos));
}
CUSTOM_COMMAND_SIG(qol_column_toggle)
CUSTOM_DOC("[QOL] Toggles the column for bumping and selects hovered char")
{
View_ID view = get_active_view(app, Access_ReadVisible);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible);
if (qol_col_cursor.pos < 0){
i64 pos = view_get_cursor_pos(app, view);
qol_target_char = buffer_get_char(app, buffer, pos);
qol_col_cursor = buffer_compute_cursor(app, buffer, seek_pos(pos));
}
else{
qol_col_cursor.pos = -1;
}
}
CUSTOM_COMMAND_SIG(qol_write_space)
CUSTOM_DOC("[QOL] Writes as many spaces needed for bumping to column")
{
Scratch_Block scratch(app);
if (qol_col_cursor.pos > 0){
View_ID view = get_active_view(app, Access_ReadVisible);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible);
qol_col_cursor = buffer_compute_cursor(app, buffer, seek_line_col(qol_col_cursor.line, qol_col_cursor.col));
i64 pos = view_get_cursor_pos(app, view);
i64 line = get_line_number_from_pos(app, buffer, pos);
f32 col_x = view_relative_xy_of_pos(app, view, line, qol_col_cursor.pos).x;
f32 cur_x = view_relative_xy_of_pos(app, view, line, pos).x;
Face_ID face = get_face_id(app, buffer);
f32 space_advance = get_face_metrics(app, face).space_advance;
i64 N = i64((col_x - cur_x) / space_advance);
if (N < 0){ N = 1; }
String_Const_u8 spaces = string_const_u8_push(scratch, N);
block_fill_u8(spaces.str, N, ' ');
write_text(app, spaces);
}
else{
write_space(app);
}
}
function void
bindings_cmd_misc(Mapping* m, Command_Map* map)
@ -231,6 +310,11 @@ custom_keyboard_bindings()
Bind(unindent_range, KeyCode_Tab, KeyCode_Shift);
Bind(indent_range, KeyCode_Tab);
Bind(qol_column_toggle, KeyCode_BackwardSlash, key_alt);
Bind(qol_write_space, KeyCode_Space, key_alt, KeyCode_Shift);
Bind(qol_char_forward, KeyCode_L, key_alt);
Bind(qol_char_backward, KeyCode_J, key_alt);
// Macros
Bind(keyboard_macro_start_recording, KeyCode_1, key_alt);
Bind(keyboard_macro_finish_recording, KeyCode_2, key_alt);

View File

@ -326,50 +326,50 @@ default_render_buffer(Application_Links *app, View_ID view_id, Face_ID face_id,
// NOTE(allen): Token colorizing
ARGB_Color color_default = fcolor_resolve(fcolor_id(defcolor_text_default));
ARGB_Color color_function = fcolor_resolve(fcolor_id(defcolor_function));
ARGB_Color color_operator = fcolor_resolve(fcolor_id(defcolor_operator));
ARGB_Color color_type = fcolor_resolve(fcolor_id(defcolor_type));
ARGB_Color color_macro = fcolor_resolve(fcolor_id(defcolor_macro));
ARGB_Color color_default = fcolor_resolve(fcolor_id(defcolor_text_default));
ARGB_Color color_function = fcolor_resolve(fcolor_id(defcolor_function));
ARGB_Color color_operator = fcolor_resolve(fcolor_id(defcolor_operator));
ARGB_Color color_type = fcolor_resolve(fcolor_id(defcolor_type));
ARGB_Color color_macro = fcolor_resolve(fcolor_id(defcolor_macro));
Token_Array token_array = get_token_array_from_buffer(app, buffer);
if (token_array.tokens != 0){
draw_cpp_token_colors(app, text_layout_id, &token_array);
draw_cpp_token_colors(app, text_layout_id, &token_array);
// NOTE(allen): Scan for TODOs and NOTEs
b32 use_comment_keyword = def_get_config_b32(vars_save_string_lit("use_comment_keyword"));
if (use_comment_keyword){
Comment_Highlight_Pair pairs[] = {
{string_u8_litexpr("NOTE"), finalize_color(defcolor_comment_pop, 0)},
{string_u8_litexpr("TODO"), finalize_color(defcolor_comment_pop, 1)},
};
draw_comment_highlights(app, buffer, text_layout_id, &token_array, pairs, ArrayCount(pairs));
// NOTE(allen): Scan for TODOs and NOTEs
b32 use_comment_keyword = def_get_config_b32(vars_save_string_lit("use_comment_keyword"));
if (use_comment_keyword){
Comment_Highlight_Pair pairs[] = {
{string_u8_litexpr("NOTE"), finalize_color(defcolor_comment_pop, 0)},
{string_u8_litexpr("TODO"), finalize_color(defcolor_comment_pop, 1)},
};
draw_comment_highlights(app, buffer, text_layout_id, &token_array, pairs, ArrayCount(pairs));
}
// NOTE(allen): Color functions
Scratch_Block scratch(app);
Token_Iterator_Array it = token_iterator_pos(0, &token_array, visible_range.first);
it.count = Min(it.count, visible_range.one_past_last - visible_range.first);
for (;;){
if (!token_it_inc_non_whitespace(&it)){
break;
}
// NOTE(allen): Color functions
Scratch_Block scratch(app);
Token_Iterator_Array it = token_iterator_pos(0, &token_array, visible_range.first);
it.count = Min(it.count, visible_range.one_past_last - visible_range.first);
for (;;){
if (!token_it_inc_non_whitespace(&it)){
break;
}
ARGB_Color token_color = color_default;
Token *token = token_it_read(&it);
if (token->kind == TokenBaseKind_Operator ||
token->kind == TokenBaseKind_ScopeOpen ||
token->kind == TokenBaseKind_ScopeClose ||
token->kind == TokenBaseKind_ParentheticalOpen ||
token->kind == TokenBaseKind_ParentheticalClose ||
token->kind == TokenBaseKind_StatementClose)
{
token_color = color_operator;
}
else
{
String_Const_u8 lexeme = push_token_lexeme(app, scratch, buffer, token);
ARGB_Color token_color = color_default;
Token *token = token_it_read(&it);
if (token->kind == TokenBaseKind_Operator ||
token->kind == TokenBaseKind_ScopeOpen ||
token->kind == TokenBaseKind_ScopeClose ||
token->kind == TokenBaseKind_ParentheticalOpen ||
token->kind == TokenBaseKind_ParentheticalClose ||
token->kind == TokenBaseKind_StatementClose)
{
token_color = color_operator;
}
else
{
String_Const_u8 lexeme = push_token_lexeme(app, scratch, buffer, token);
Code_Index_Note *note = code_index_note_from_string(lexeme);
if (note != 0)
{
@ -381,14 +381,14 @@ String_Const_u8 lexeme = push_token_lexeme(app, scratch, buffer, token);
default: {} break;
}
}
}
paint_text_color(app, text_layout_id, Ii64_size(token->pos, token->size), token_color);
}
}
else
{
paint_text_color(app, text_layout_id, visible_range, color_default);
}
}
paint_text_color(app, text_layout_id, Ii64_size(token->pos, token->size), token_color);
}
}
else
{
paint_text_color(app, text_layout_id, visible_range, color_default);
}
i64 cursor_pos = view_correct_cursor(app, view_id);
view_correct_mark(app, view_id);
@ -400,6 +400,18 @@ String_Const_u8 lexeme = push_token_lexeme(app, scratch, buffer, token);
draw_scope_highlight(app, buffer, text_layout_id, cursor_pos, colors.vals, colors.count);
}
// NOTE(PS): QOL Column
if (qol_col_cursor.pos >= 0){
Buffer_Seek seek = seek_line_col(qol_col_cursor.line, qol_col_cursor.col);
Buffer_Cursor cursor = buffer_compute_cursor(app, buffer, seek);
Rect_f32 col_rect = text_layout_character_on_screen(app, text_layout_id, cursor.pos);
if (col_rect.x1 > 0.f){
col_rect.y0 = rect.y0;
col_rect.y1 = rect.y1;
draw_rectangle_fcolor(app, col_rect, 0.f, fcolor_id(defcolor_highlight_cursor_line));
}
}
b32 use_error_highlight = def_get_config_b32(vars_save_string_lit("use_error_highlight"));
b32 use_jump_highlight = def_get_config_b32(vars_save_string_lit("use_jump_highlight"));
if (use_error_highlight || use_jump_highlight){

View File

@ -64,6 +64,7 @@
#include "4coder_tutorial.h"
#include "4coder_search_list.h"
#include "4coder_modal.h"
#include "4coder_qol.h"
////////////////////////////////
@ -147,6 +148,8 @@
#include "4coder_default_hooks.cpp"
#include "4coder_qol.cpp"
#endif
// BOTTOM

View File

@ -1,5 +1,5 @@
/*
4coder_jump_sticky.cpp - Commands and helpers for parsing jump locations from
4coder_jump_sticky.cpp - Commands and helpers for parsing jump locations from
compiler errors, sticking markers on jump locations, and jumping to them.
*/
@ -43,14 +43,14 @@ parse_buffer_to_jump_array(Application_Links *app, Arena *arena, Buffer_ID buffe
Sticky_Jump_Node *jump_first = 0;;
Sticky_Jump_Node *jump_last = 0;
i32 jump_count = 0;
for (i32 line = 1;; line += 1){
b32 output_jump = false;
i32 colon_index = 0;
b32 is_sub_error = false;
Buffer_ID out_buffer_id = 0;
i64 out_pos = 0;
{
Temp_Memory_Block line_auto_closer(arena);
if (is_valid_line(app, buffer, line)){
@ -74,7 +74,7 @@ parse_buffer_to_jump_array(Application_Links *app, Arena *arena, Buffer_ID buffe
break;
}
}
if (output_jump){
Sticky_Jump_Node *jump = push_array(arena, Sticky_Jump_Node, 1);
sll_queue_push(jump_first, jump_last, jump);
@ -86,7 +86,7 @@ parse_buffer_to_jump_array(Application_Links *app, Arena *arena, Buffer_ID buffe
jump->jump.jump_pos = out_pos;
}
}
Sticky_Jump_Array result = {};
result.count = jump_count;
result.jumps = push_array(arena, Sticky_Jump, result.count);
@ -97,14 +97,14 @@ parse_buffer_to_jump_array(Application_Links *app, Arena *arena, Buffer_ID buffe
result.jumps[index] = node->jump;
index += 1;
}
return(result);
}
internal void
init_marker_list(Application_Links *app, Heap *heap, Buffer_ID buffer, Marker_List *list){
Scratch_Block scratch(app);
Sticky_Jump_Array jumps = parse_buffer_to_jump_array(app, scratch, buffer);
Range_i32_Array buffer_ranges = get_ranges_of_duplicate_keys(scratch, &jumps.jumps->jump_buffer_id, sizeof(*jumps.jumps), jumps.count);
Sort_Pair_i32 *range_index_buffer_id_pairs = push_array(scratch, Sort_Pair_i32, buffer_ranges.count);
@ -117,15 +117,15 @@ init_marker_list(Application_Links *app, Heap *heap, Buffer_ID buffer, Marker_Li
&range_index_buffer_id_pairs->key,
sizeof(*range_index_buffer_id_pairs),
buffer_ranges.count);
Sticky_Jump_Stored *stored = push_array(scratch, Sticky_Jump_Stored, jumps.count);
Managed_Scope scope_array[2] = {};
scope_array[0] = buffer_get_managed_scope(app, buffer);
for (i32 i = 0; i < scoped_buffer_ranges.count; i += 1){
Range_i32 buffer_range_indices = scoped_buffer_ranges.ranges[i];
u32 total_jump_count = 0;
for (i32 j = buffer_range_indices.first;
j < buffer_range_indices.one_past_last;
@ -134,7 +134,7 @@ init_marker_list(Application_Links *app, Heap *heap, Buffer_ID buffer, Marker_Li
Range_i32 range = buffer_ranges.ranges[range_index];
total_jump_count += range_size(range);
}
Temp_Memory marker_temp = begin_temp(scratch);
Marker *markers = push_array(scratch, Marker, total_jump_count);
Buffer_ID target_buffer_id = 0;
@ -158,27 +158,27 @@ init_marker_list(Application_Links *app, Heap *heap, Buffer_ID buffer, Marker_Li
marker_index += 1;
}
}
scope_array[1] = buffer_get_managed_scope(app, target_buffer_id);
Managed_Scope scope = get_managed_scope_with_multiple_dependencies(app, scope_array, ArrayCount(scope_array));
Managed_Object marker_handle = alloc_buffer_markers_on_buffer(app, target_buffer_id, total_jump_count, &scope);
managed_object_store_data(app, marker_handle, 0, total_jump_count, markers);
end_temp(marker_temp);
Assert(managed_object_get_item_size(app, marker_handle) == sizeof(Marker));
Assert(managed_object_get_item_count(app, marker_handle) == total_jump_count);
Assert(managed_object_get_type(app, marker_handle) == ManagedObjectType_Markers);
Managed_Object *marker_handle_ptr = scope_attachment(app, scope, sticky_jump_marker_handle, Managed_Object);
if (marker_handle_ptr != 0){
*marker_handle_ptr = marker_handle;
}
}
Managed_Object stored_jump_array = alloc_managed_memory_in_scope(app, scope_array[0], sizeof(Sticky_Jump_Stored), jumps.count);
managed_object_store_data(app, stored_jump_array, 0, jumps.count, stored);
list->jump_array = stored_jump_array;
list->jump_count = jumps.count;
list->previous_size = (i32)buffer_get_size(app, buffer);
@ -274,12 +274,12 @@ get_jump_from_list(Application_Links *app, Marker_List *list, i32 index, ID_Pos_
Sticky_Jump_Stored stored = {};
if (get_stored_jump_from_list(app, list, index, &stored)){
Buffer_ID target_buffer_id = stored.jump_buffer_id;
Managed_Scope scope_array[2] = {};
scope_array[0] = buffer_get_managed_scope(app, list->buffer_id);
scope_array[1] = buffer_get_managed_scope(app, target_buffer_id);
Managed_Scope scope = get_managed_scope_with_multiple_dependencies(app, scope_array, ArrayCount(scope_array));
Managed_Object *marker_array = scope_attachment(app, scope, sticky_jump_marker_handle, Managed_Object);
if (marker_array != 0 && *marker_array != 0){
Marker marker = {};
@ -349,16 +349,16 @@ CUSTOM_COMMAND_SIG(goto_jump_at_cursor)
CUSTOM_DOC("If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in another view and changes the active panel to the view containing the jump.")
{
Heap *heap = &global_heap;
View_ID view = get_active_view(app, Access_ReadVisible);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible);
Marker_List *list = get_or_make_list_for_buffer(app, heap, buffer);
i64 pos = view_get_cursor_pos(app, view);
Buffer_Cursor cursor = buffer_compute_cursor(app, buffer, seek_pos(pos));
i32 list_index = get_index_exact_from_list(app, list, cursor.line);
if (list_index >= 0){
ID_Pos_Jump_Location location = {};
if (get_jump_from_list(app, list, list_index, &location)){
@ -376,17 +376,17 @@ CUSTOM_COMMAND_SIG(goto_jump_at_cursor_same_panel)
CUSTOM_DOC("If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in this view, losing the compilation output or jump list.")
{
Heap *heap = &global_heap;
View_ID view = get_active_view(app, Access_ReadVisible);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible);
Marker_List *list = get_or_make_list_for_buffer(app, heap, buffer);
i64 pos = view_get_cursor_pos(app, view);
Buffer_Cursor cursor = buffer_compute_cursor(app, buffer, seek_pos(pos));
i32 list_index = get_index_exact_from_list(app, list, cursor.line);
if (list_index >= 0){
ID_Pos_Jump_Location location = {};
if (get_jump_from_list(app, list, list_index, &location)){
@ -420,7 +420,7 @@ jump_is_repeat(ID_Pos_Jump_Location prev, ID_Pos_Jump_Location location){
internal void
goto_next_filtered_jump(Application_Links *app, Marker_List *list, View_ID jump_view, i32 list_index, i32 direction, b32 skip_repeats, b32 skip_sub_errors){
Assert(direction == 1 || direction == -1);
if (list != 0){
for (;list_index >= 0 && list_index < list->jump_count;){
ID_Pos_Jump_Location location = {};
@ -432,7 +432,7 @@ goto_next_filtered_jump(Application_Links *app, Marker_List *list, View_ID jump_
else if (skip_sub_errors && get_is_sub_error_from_list(app, list, list_index)){
skip_this = true;
}
if (!skip_this){
goto_jump_in_order(app, list, jump_view, location);
i64 updated_line = get_line_from_list(app, list, list_index);
@ -440,7 +440,7 @@ goto_next_filtered_jump(Application_Links *app, Marker_List *list, View_ID jump_
break;
}
}
list_index += direction;
}
}
@ -453,8 +453,9 @@ get_locked_jump_state(Application_Links *app, Heap *heap){
if (result.view != 0){
Buffer_ID buffer = view_get_buffer(app, result.view, Access_Always);
result.list = get_or_make_list_for_buffer(app, heap, buffer);
i64 cursor_position = view_get_cursor_pos(app, result.view);
i64 size = buffer_get_size(app, buffer);
i64 cursor_position = size == 0 ? 0 : view_get_cursor_pos(app, result.view) % size;
Buffer_Cursor cursor = buffer_compute_cursor(app, buffer, seek_pos(cursor_position));
result.list_index = get_index_nearest_from_list(app, result.list, cursor.line);
}
@ -465,10 +466,11 @@ CUSTOM_COMMAND_SIG(goto_next_jump)
CUSTOM_DOC("If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, skipping sub jump locations.")
{
Heap *heap = &global_heap;
Locked_Jump_State jump_state = get_locked_jump_state(app, heap);
if (jump_state.view != 0){
i64 cursor_position = view_get_cursor_pos(app, jump_state.view);
i64 size = buffer_get_size(app, view_get_buffer(app, jump_state.view, Access_Always));
i64 cursor_position = size == 0 ? 0 : view_get_cursor_pos(app, jump_state.view) % size;
Buffer_Cursor cursor = view_compute_cursor(app, jump_state.view, seek_pos(cursor_position));
i64 line = get_line_from_list(app, jump_state.list, jump_state.list_index);
if (line <= cursor.line){
@ -481,7 +483,7 @@ CUSTOM_DOC("If a buffer containing jump locations has been locked in, goes to th
CUSTOM_COMMAND_SIG(goto_prev_jump)
CUSTOM_DOC("If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, skipping sub jump locations."){
Heap *heap = &global_heap;
Locked_Jump_State jump_state = get_locked_jump_state(app, heap);
if (jump_state.view != 0){
if (jump_state.list_index > 0){
@ -495,7 +497,7 @@ CUSTOM_COMMAND_SIG(goto_next_jump_no_skips)
CUSTOM_DOC("If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, and does not skip sub jump locations.")
{
Heap *heap = &global_heap;
Locked_Jump_State jump_state = get_locked_jump_state(app, heap);
if (jump_state.view != 0){
i64 cursor_position = view_get_cursor_pos(app, jump_state.view);
@ -512,7 +514,7 @@ CUSTOM_COMMAND_SIG(goto_prev_jump_no_skips)
CUSTOM_DOC("If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, and does not skip sub jump locations.")
{
Heap *heap = &global_heap;
Locked_Jump_State jump_state = get_locked_jump_state(app, heap);
if (jump_state.view != 0){
if (jump_state.list_index > 0){
@ -526,7 +528,7 @@ CUSTOM_COMMAND_SIG(goto_first_jump)
CUSTOM_DOC("If a buffer containing jump locations has been locked in, goes to the first jump in the buffer.")
{
Heap *heap = &global_heap;
Locked_Jump_State jump_state = get_locked_jump_state(app, heap);
if (jump_state.view != 0){
i32 list_index = 0;
@ -543,7 +545,7 @@ CUSTOM_COMMAND_SIG(goto_first_jump_same_panel_sticky)
CUSTOM_DOC("If a buffer containing jump locations has been locked in, goes to the first jump in the buffer and views the buffer in the panel where the jump list was.")
{
Heap *heap = &global_heap;
Locked_Jump_State jump_state = get_locked_jump_state(app, heap);
if (jump_state.view != 0){
i32 list_index = 0;

View File

@ -178,21 +178,21 @@ lister_zero_scroll(Lister *lister){
function void
lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){
Scratch_Block scratch(app);
Lister *lister = view_get_lister(app, view);
if (lister == 0){
return;
}
Rect_f32 region = draw_background_and_margin(app, view);
Rect_f32 prev_clip = draw_set_clip(app, region);
Face_ID face_id = get_face_id(app, 0);
Face_Metrics metrics = get_face_metrics(app, face_id);
f32 line_height = metrics.line_height;
f32 block_height = lister_get_block_height(line_height);
f32 text_field_height = lister_get_text_field_height(line_height);
// NOTE(allen): file bar
// TODO(allen): What's going on with 'showing_file_bar'? I found it like this.
b64 showing_file_bar = false;
@ -204,13 +204,13 @@ lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){
draw_file_bar(app, view, buffer, face_id, pair.min);
region = pair.max;
}
Mouse_State mouse = get_mouse_state(app);
Vec2_f32 m_p = V2f32(mouse.p);
lister->visible_count = (i32)((rect_height(region)/block_height)) - 3;
lister->visible_count = clamp_bot(1, lister->visible_count);
Rect_f32 text_field_rect = {};
Rect_f32 list_rect = {};
{
@ -218,7 +218,7 @@ lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){
text_field_rect = pair.min;
list_rect = pair.max;
}
{
Vec2_f32 p = V2f32(text_field_rect.x0 + 3.f, text_field_rect.y0);
Fancy_Line text_field = {};
@ -226,7 +226,7 @@ lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){
lister->query.string);
push_fancy_stringf(scratch, &text_field, " ");
p = draw_fancy_line(app, face_id, fcolor_zero(), &text_field, p);
// TODO(allen): This is a bit of a hack. Maybe an upgrade to fancy to focus
// more on being good at this and less on overriding everything 10 ways to sunday
// would be good.
@ -245,14 +245,14 @@ lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){
draw_fancy_line(app, face_id, fcolor_zero(), &text_field, p);
}
}
Range_f32 x = rect_range_x(list_rect);
draw_set_clip(app, list_rect);
// NOTE(allen): auto scroll to the item if the flag is set.
f32 scroll_y = lister->scroll.position.y;
if (lister->set_vertical_focus_to_item){
lister->set_vertical_focus_to_item = false;
Range_f32 item_y = If32_size(lister->item_index*block_height, block_height);
@ -272,39 +272,40 @@ lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){
}
}
}
// NOTE(allen): clamp scroll target and position; smooth scroll rule
i32 count = lister->filtered.count;
Range_f32 scroll_range = If32(0.f, clamp_bot(0.f, count*block_height - block_height));
lister->scroll.target.y = clamp_range(scroll_range, lister->scroll.target.y);
lister->scroll.target.x = 0.f;
Vec2_f32_Delta_Result delta = delta_apply(app, view,
frame_info.animation_dt, lister->scroll);
lister->scroll.position = delta.p;
if (delta.still_animating){
animate_in_n_milliseconds(app, 0);
}
lister->scroll.position.y = clamp_range(scroll_range, lister->scroll.position.y);
lister->scroll.position.x = 0.f;
scroll_y = lister->scroll.position.y;
f32 y_pos = list_rect.y0 - scroll_y;
i32 first_index = (i32)(scroll_y/block_height);
y_pos += first_index*block_height;
for (i32 i = first_index; i < count; i += 1){
Lister_Node *node = lister->filtered.node_ptrs[i];
if (y_pos >= region.y1) break;
Range_f32 y = If32(y_pos, y_pos + block_height);
y_pos = y.max;
Rect_f32 item_rect = Rf32(x, y);
if (item_rect.y0 > region.y1) { break; }
Rect_f32 item_inner = rect_inner(item_rect, 3.f);
b32 hovered = rect_contains_point(item_rect, m_p);
UI_Highlight_Level highlight = UIHighlight_None;
if (node == lister->highlighted_node){
@ -321,21 +322,21 @@ lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){
else if (hovered){
highlight = UIHighlight_Hover;
}
u64 lister_roundness_100 = def_get_config_u64(app, vars_save_string_lit("lister_roundness"));
f32 roundness = block_height*lister_roundness_100*0.01f;
draw_rectangle_fcolor(app, item_rect, roundness, get_item_margin_color(highlight));
draw_rectangle_fcolor(app, item_inner, roundness, get_item_margin_color(highlight, 1));
Fancy_Line line = {};
push_fancy_string(scratch, &line, fcolor_id(defcolor_text_default), node->string);
push_fancy_stringf(scratch, &line, " ");
push_fancy_string(scratch, &line, fcolor_id(defcolor_pop2), node->status);
Vec2_f32 p = item_inner.p0 + V2f32(3.f, (block_height - line_height)*0.5f);
draw_fancy_line(app, face_id, fcolor_zero(), &line, p);
}
draw_set_clip(app, prev_clip);
}
@ -359,26 +360,26 @@ lister_get_user_data(Lister *lister, i32 index){
function Lister_Filtered
lister_get_filtered(Arena *arena, Lister *lister){
i32 node_count = lister->options.count;
Lister_Filtered filtered = {};
filtered.exact_matches.node_ptrs = push_array(arena, Lister_Node*, 1);
filtered.before_extension_matches.node_ptrs = push_array(arena, Lister_Node*, node_count);
filtered.substring_matches.node_ptrs = push_array(arena, Lister_Node*, node_count);
Temp_Memory_Block temp(arena);
String_Const_u8 key = lister->key_string.string;
key = push_string_copy(arena, key);
string_mod_replace_character(key, '_', '*');
string_mod_replace_character(key, ' ', '*');
List_String_Const_u8 absolutes = {};
string_list_push(arena, &absolutes, string_u8_litexpr(""));
List_String_Const_u8 splits = string_split(arena, key, (u8*)"*", 1);
b32 has_wildcard = (splits.node_count > 1);
string_list_push(&absolutes, &splits);
string_list_push(arena, &absolutes, string_u8_litexpr(""));
for (Lister_Node *node = lister->options.first;
node != 0;
node = node->next){
@ -399,7 +400,7 @@ lister_get_filtered(Arena *arena, Lister *lister){
}
}
}
return(filtered);
}
@ -421,23 +422,23 @@ function void
lister_update_filtered_list(Application_Links *app, Lister *lister){
Arena *arena = lister->arena;
Scratch_Block scratch(app, arena);
Lister_Filtered filtered = lister_get_filtered(scratch, lister);
Lister_Node_Ptr_Array node_ptr_arrays[] = {
filtered.exact_matches,
filtered.before_extension_matches,
filtered.substring_matches,
};
end_temp(lister->filter_restore_point);
i32 total_count = 0;
for (i32 array_index = 0; array_index < ArrayCount(node_ptr_arrays); array_index += 1){
Lister_Node_Ptr_Array node_ptr_array = node_ptr_arrays[array_index];
total_count += node_ptr_array.count;
}
Lister_Node **node_ptrs = push_array(arena, Lister_Node*, total_count);
lister->filtered.node_ptrs = node_ptrs;
lister->filtered.count = total_count;
@ -450,7 +451,7 @@ lister_update_filtered_list(Application_Links *app, Lister *lister){
counter += 1;
}
}
lister_update_selection_values(lister);
}
@ -475,13 +476,13 @@ lister_user_data_at_p(Application_Links *app, View_ID view, Lister *lister, Vec2
Rect_f32 region = view_get_screen_rect(app, view);
// TODO(allen): eliminate this. bad bad bad bad :(
region = rect_inner(region, 3.f);
Face_ID face_id = get_face_id(app, 0);
Face_Metrics metrics = get_face_metrics(app, face_id);
f32 line_height = metrics.line_height;
f32 block_height = lister_get_block_height(line_height);
f32 text_field_height = lister_get_text_field_height(line_height);
b64 showing_file_bar = false;
b32 hide_file_bar_in_ui = def_get_config_b32(vars_save_string_lit("hide_file_bar_in_ui"));
if (view_get_setting(app, view, ViewSetting_ShowFileBar, &showing_file_bar) &&
@ -489,10 +490,10 @@ lister_user_data_at_p(Application_Links *app, View_ID view, Lister *lister, Vec2
Rect_f32_Pair pair = layout_file_bar_on_top(region, line_height);
region = pair.max;
}
Rect_f32_Pair pair = lister_get_top_level_layout(region, text_field_height);
Rect_f32 list_rect = pair.max;
void *result = 0;
if (rect_contains_point(list_rect, m_p)){
f32 y = m_p.y - list_rect.y0 + lister->scroll.position.y;
@ -502,7 +503,7 @@ lister_user_data_at_p(Application_Links *app, View_ID view, Lister *lister, Vec2
result = node->user_data;
}
}
return(result);
}
@ -510,13 +511,13 @@ function Lister_Result
run_lister(Application_Links *app, Lister *lister){
lister->filter_restore_point = begin_temp(lister->arena);
lister_update_filtered_list(app, lister);
View_ID view = get_this_ctx_view(app, Access_Always);
View_Context ctx = view_current_context(app, view);
ctx.render_caller = lister_render;
ctx.hides_buffer = true;
View_Context_Block ctx_block(app, view, &ctx);
for (;;){
User_Input in = get_next_input(app, EventPropertyGroup_Any, EventProperty_Escape);
if (in.abort){
@ -524,7 +525,7 @@ run_lister(Application_Links *app, Lister *lister){
lister->out.canceled = true;
break;
}
Lister_Activation_Code result = ListerActivation_Continue;
b32 handled = true;
switch (in.event.kind){
@ -534,7 +535,7 @@ run_lister(Application_Links *app, Lister *lister){
result = lister->handlers.write_character(app);
}
}break;
case InputEventKind_KeyStroke:
{
switch (in.event.key.code){
@ -549,7 +550,7 @@ run_lister(Application_Links *app, Lister *lister){
lister_activate(app, lister, user_data, false);
result = ListerActivation_Finished;
}break;
case KeyCode_Backspace:
{
if (lister->handlers.backspace != 0){
@ -562,7 +563,7 @@ run_lister(Application_Links *app, Lister *lister){
handled = false;
}
}break;
case KeyCode_Up:
{
if (lister->handlers.navigate != 0){
@ -575,7 +576,7 @@ run_lister(Application_Links *app, Lister *lister){
handled = false;
}
}break;
case KeyCode_Down:
{
if (lister->handlers.navigate != 0){
@ -588,7 +589,7 @@ run_lister(Application_Links *app, Lister *lister){
handled = false;
}
}break;
case KeyCode_PageUp:
{
if (lister->handlers.navigate != 0){
@ -602,7 +603,7 @@ run_lister(Application_Links *app, Lister *lister){
handled = false;
}
}break;
case KeyCode_PageDown:
{
if (lister->handlers.navigate != 0){
@ -616,7 +617,7 @@ run_lister(Application_Links *app, Lister *lister){
handled = false;
}
}break;
default:
{
if (lister->handlers.key_stroke != 0){
@ -628,7 +629,7 @@ run_lister(Application_Links *app, Lister *lister){
}break;
}
}break;
case InputEventKind_MouseButton:
{
switch (in.event.mouse.code){
@ -638,14 +639,14 @@ run_lister(Application_Links *app, Lister *lister){
void *clicked = lister_user_data_at_p(app, view, lister, p);
lister->hot_user_data = clicked;
}break;
default:
{
handled = false;
}break;
}
}break;
case InputEventKind_MouseButtonRelease:
{
switch (in.event.mouse.code){
@ -661,26 +662,26 @@ run_lister(Application_Links *app, Lister *lister){
}
lister->hot_user_data = 0;
}break;
default:
{
handled = false;
}break;
}
}break;
case InputEventKind_MouseWheel:
{
Mouse_State mouse = get_mouse_state(app);
lister->scroll.target.y += mouse.wheel;
lister_update_filtered_list(app, lister);
}break;
case InputEventKind_MouseMove:
{
lister_update_filtered_list(app, lister);
}break;
case InputEventKind_Core:
{
switch (in.event.core.code){
@ -688,28 +689,28 @@ run_lister(Application_Links *app, Lister *lister){
{
lister_update_filtered_list(app, lister);
}break;
default:
{
handled = false;
}break;
}
}break;
default:
{
handled = false;
}break;
}
if (result == ListerActivation_Finished){
break;
}
if (!handled){
Mapping *mapping = lister->mapping;
Command_Map *map = lister->map;
Fallback_Dispatch_Result disp_result =
fallback_command_dispatch(app, mapping, map, &in);
if (disp_result.code == FallbackDispatch_DelayedUICall){
@ -724,7 +725,7 @@ run_lister(Application_Links *app, Lister *lister){
}
}
}
return(lister->out);
}
@ -972,7 +973,7 @@ get_choice_from_user(Application_Links *app, String_Const_u8 query,
handlers.navigate = lister__navigate__default;
handlers.key_stroke = lister__key_stroke__choice_list;
lister_set_handlers(lister, &handlers);
Lister_Result l_result = run_lister(app, lister);
Lister_Choice *result = 0;
if (!l_result.canceled){

View File

9
code/custom/4coder_qol.h Normal file
View File

@ -0,0 +1,9 @@
/* date = July 7th 2025 2:22 pm */
#ifndef FCODER_QOL_H
#define FCODER_QOL_H
global u8 qol_target_char;
global Buffer_Cursor qol_col_cursor = {-1};
#endif //FCODER_QOL_H

View File

@ -14,11 +14,11 @@ print_string_match_list_to_buffer(Application_Links *app, Buffer_ID out_buffer_i
Buffer_Insertion out = begin_buffer_insertion_at_buffered(app, out_buffer_id, 0, scratch, KB(64));
buffer_set_setting(app, out_buffer_id, BufferSetting_ReadOnly, true);
buffer_set_setting(app, out_buffer_id, BufferSetting_RecordsHistory, false);
Temp_Memory buffer_name_restore_point = begin_temp(scratch);
String_Const_u8 current_file_name = {};
Buffer_ID current_buffer = 0;
if (matches.first != 0){
for (String_Match *node = matches.first;
node != 0;
@ -35,7 +35,7 @@ print_string_match_list_to_buffer(Application_Links *app, Buffer_ID out_buffer_i
current_file_name = push_buffer_unique_name(app, scratch, current_buffer);
}
}
Buffer_Cursor cursor = buffer_compute_cursor(app, current_buffer, seek_pos(node->range.first));
Temp_Memory line_temp = begin_temp(scratch);
String_Const_u8 full_line_str = push_buffer_line(app, scratch, current_buffer, cursor.line);
@ -50,8 +50,9 @@ print_string_match_list_to_buffer(Application_Links *app, Buffer_ID out_buffer_i
else{
insertf(&out, "no matches");
}
end_buffer_insertion(&out);
lock_jump_buffer(app, out_buffer_id);
}
internal void
@ -261,7 +262,7 @@ get_complete_list_raw(Application_Links *app, Arena *arena, Buffer_ID buffer,
Range_i64 needle_range, String_Const_u8 needle){
local_persist Character_Predicate *pred =
&character_predicate_alpha_numeric_underscore_utf8;
String_Match_List result = {};
i64 size = buffer_get_size(app, buffer);
if (range_size(needle_range) > 0){
@ -280,7 +281,7 @@ get_complete_list_raw(Application_Links *app, Arena *arena, Buffer_ID buffer,
Ii64(0, size), needle, pred, Scan_Forward);
string_match_list_filter_flags(&result, complete_must, complete_must_not);
}
string_match_list_enclose_all(app, result,
right_enclose_alpha_numeric_underscore_utf8);
return(result);
@ -307,28 +308,28 @@ function void
word_complete_iter_init__inner(Buffer_ID buffer, String_Const_u8 needle, Range_i64 range, Word_Complete_Iterator *iter){
Application_Links *app = iter->app;
Arena *arena = iter->arena;
Base_Allocator *allocator = get_base_allocator_system();
if (iter->already_used_table.allocator != 0){
end_temp(iter->arena_restore);
table_clear(&iter->already_used_table);
}
block_zero_struct(iter);
iter->app = app;
iter->arena = arena;
iter->arena_restore = begin_temp(arena);
iter->needle = push_string_copy(arena, needle);
iter->first_buffer = buffer;
iter->current_buffer = buffer;
Scratch_Block scratch(app, arena);
String_Match_List list = get_complete_list_raw(app, scratch, buffer, range, needle);
iter->already_used_table = make_table_Data_u64(allocator, 100);
word_complete_list_extend_from_raw(app, arena, &list, &iter->list, &iter->already_used_table);
iter->scan_all_buffers = true;
}
@ -339,7 +340,7 @@ word_complete_iter_init(Buffer_ID buffer, Range_i64 range, Word_Complete_Iterato
Arena *arena = iter->arena;
Scratch_Block scratch(app, arena);
String_Const_u8 needle = push_buffer_range(app, scratch, buffer, range);
word_complete_iter_init__inner(buffer, needle, range, iter);
word_complete_iter_init__inner(buffer, needle, range, iter);
}
}
@ -373,21 +374,21 @@ word_complete_iter_next(Word_Complete_Iterator *it){
else{
it->node = it->node->next;
}
if (it->node != 0){
break;
}
if (!it->scan_all_buffers){
break;
}
Application_Links *app = it->app;
Buffer_ID next = get_buffer_next_looped(app, it->current_buffer, Access_Read);
if (next == it->first_buffer){
break;
}
it->node = it->list.last;
it->current_buffer = next;
Scratch_Block scratch(app);
@ -434,24 +435,24 @@ CUSTOM_COMMAND_SIG(word_complete)
CUSTOM_DOC("Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.")
{
ProfileScope(app, "word complete");
View_ID view = get_active_view(app, Access_ReadWriteVisible);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible);
if (buffer != 0){
Managed_Scope scope = view_get_managed_scope(app, view);
b32 first_completion = false;
Rewrite_Type *rewrite = scope_attachment(app, scope, view_rewrite_loc, Rewrite_Type);
if (*rewrite != Rewrite_WordComplete){
first_completion = true;
}
set_next_rewrite(app, view, Rewrite_WordComplete);
Word_Complete_Iterator *it = word_complete_get_shared_iter(app);
local_persist b32 initialized = false;
local_persist Range_i64 range = {};
if (first_completion || !initialized){
ProfileBlock(app, "word complete state init");
initialized = false;
@ -463,15 +464,15 @@ CUSTOM_DOC("Iteratively tries completing the word to the left of the cursor with
word_complete_iter_init(buffer, needle_range, it);
}
}
if (initialized){
ProfileBlock(app, "word complete apply");
word_complete_iter_next(it);
String_Const_u8 str = word_complete_iter_read(it);
buffer_replace_range(app, buffer, range, str);
range.max = range.min + str.size;
view_set_cursor_and_preferred_x(app, view, seek_pos(range.max));
}
@ -507,15 +508,15 @@ word_complete_menu_render(Application_Links *app, Frame_Info frame_info, View_ID
Managed_Scope scope = view_get_managed_scope(app, view);
Word_Complete_Menu **menu_ptr = scope_attachment(app, scope, view_word_complete_menu, Word_Complete_Menu*);
Word_Complete_Menu *menu = *menu_ptr;
if (menu != 0){
menu->prev_render_caller(app, frame_info, view);
Buffer_ID buffer = view_get_buffer(app, view, Access_Always);
Face_ID face = get_face_id(app, buffer);
Scratch_Block scratch(app);
Fancy_Block block = {};
for (i32 i = 0; i < menu->count; i += 1){
if (menu->options[i].size > 0){
@ -524,20 +525,20 @@ word_complete_menu_render(Application_Links *app, Frame_Info frame_info, View_ID
push_fancy_string(scratch, line, fcolor_id(defcolor_text_default), menu->options[i]);
}
}
Rect_f32 region = view_get_buffer_region(app, view);
Buffer_Scroll scroll = view_get_buffer_scroll(app, view);
Buffer_Point buffer_point = scroll.position;
i64 pos = view_get_cursor_pos(app, view);
Vec2_f32 cursor_p = view_relative_xy_of_pos(app, view, buffer_point.line_number, pos);
cursor_p -= buffer_point.pixel_shift;
cursor_p += region.p0;
Face_Metrics metrics = get_face_metrics(app, face);
f32 x_padding = metrics.normal_advance;
f32 x_half_padding = x_padding*0.5f;
draw_drop_down(app, face, &block, cursor_p, region, x_padding, x_half_padding,
fcolor_id(defcolor_margin_hover), fcolor_id(defcolor_back));
}
@ -548,11 +549,11 @@ get_word_complete_from_user_drop_down(Application_Links *app){
View_ID view = get_this_ctx_view(app, Access_Always);
View_Context ctx = view_current_context(app, view);
Render_Caller_Function *prev_render_caller = ctx.render_caller;
Edit result = {};
Word_Complete_Iterator *it = word_complete_get_shared_iter(app);
i64 pos = view_get_cursor_pos(app, view);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible);
Range_i64 range = get_word_complete_needle_range(app, buffer, pos);
@ -560,14 +561,14 @@ get_word_complete_from_user_drop_down(Application_Links *app){
word_complete_iter_init(buffer, range, it);
Word_Complete_Menu menu = make_word_complete_menu(prev_render_caller, it);
word_complete_menu_next(&menu);
ctx.render_caller = word_complete_menu_render;
View_Context_Block ctx_block(app, view, &ctx);
Managed_Scope scope = view_get_managed_scope(app, view);
Word_Complete_Menu **menu_ptr = scope_attachment(app, scope, view_word_complete_menu, Word_Complete_Menu*);
*menu_ptr = &menu;
b32 keep_looping_menu = true;
for (;keep_looping_menu;){
User_Input in = get_next_input(app, EventPropertyGroup_Any,
@ -575,7 +576,7 @@ get_word_complete_from_user_drop_down(Application_Links *app){
if (in.abort){
break;
}
b32 handled = true;
switch (in.event.kind){
case InputEventKind_TextInsert:
@ -595,7 +596,7 @@ get_word_complete_from_user_drop_down(Application_Links *app){
}
}
}break;
case InputEventKind_KeyStroke:
{
switch (in.event.key.code){
@ -605,12 +606,12 @@ get_word_complete_from_user_drop_down(Application_Links *app){
result.range = range;
keep_looping_menu = false;
}break;
case KeyCode_Tab:
{
word_complete_menu_next(&menu);
}break;
case KeyCode_F1:
case KeyCode_F2:
case KeyCode_F3:
@ -625,7 +626,7 @@ get_word_complete_from_user_drop_down(Application_Links *app){
result.range = range;
keep_looping_menu = false;
}break;
case KeyCode_Backspace:
{
backspace_char(app);
@ -643,36 +644,36 @@ get_word_complete_from_user_drop_down(Application_Links *app){
}
}
}break;
default:
{
leave_current_input_unhandled(app);
}break;
}
}break;
case InputEventKind_MouseButton:
{
leave_current_input_unhandled(app);
keep_looping_menu = false;
}break;
default:
{
handled = false;
}break;
}
if (!handled){
leave_current_input_unhandled(app);
}
}
scope = view_get_managed_scope(app, view);
menu_ptr = scope_attachment(app, scope, view_word_complete_menu, Word_Complete_Menu*);
*menu_ptr = 0;
}
return(result);
}