diff --git a/4coder_base_types.cpp b/4coder_base_types.cpp index b63c5236..26ff6747 100644 --- a/4coder_base_types.cpp +++ b/4coder_base_types.cpp @@ -1799,6 +1799,59 @@ range_side(Interval_f32 a, Side side){ return(side == Side_Min?a.min:a.max); } +internal i32 +range_distance(Interval_i32 a, Interval_i32 b){ + i32 result = 0; + if (!range_overlap(a, b)){ + if (a.max < b.min){ + result = b.min - a.max; + } + else{ + result = a.min - b.max; + } + } + return(result); +} +internal i64 +range_distance(Interval_i64 a, Interval_i64 b){ + i64 result = 0; + if (!range_overlap(a, b)){ + if (a.max < b.min){ + result = b.min - a.max; + } + else{ + result = a.min - b.max; + } + } + return(result); +} +internal u64 +range_distance(Interval_u64 a, Interval_u64 b){ + u64 result = 0; + if (!range_overlap(a, b)){ + if (a.max < b.min){ + result = b.min - a.max; + } + else{ + result = a.min - b.max; + } + } + return(result); +} +internal f32 +range_distance(Interval_f32 a, Interval_f32 b){ + f32 result = 0; + if (!range_overlap(a, b)){ + if (a.max < b.min){ + result = b.min - a.max; + } + else{ + result = a.min - b.max; + } + } + return(result); +} + //////////////////////////////// internal i32 diff --git a/4coder_generated/command_metadata.h b/4coder_generated/command_metadata.h index 3d73493f..d3f78605 100644 --- a/4coder_generated/command_metadata.h +++ b/4coder_generated/command_metadata.h @@ -412,7 +412,7 @@ static Command_Metadata fcoder_metacmd_table[236] = { { PROC_LINKS(list_all_locations_of_selection_case_insensitive, 0), "list_all_locations_of_selection_case_insensitive", 48, "Reads the string in the selected range and lists all exact case-insensitive mathces in all open buffers.", 104, "c:\\4ed\\code\\4coder_search.cpp", 29, 745 }, { PROC_LINKS(list_all_locations_of_type_definition, 0), "list_all_locations_of_type_definition", 37, "Queries user for string, lists all locations of strings that appear to define a type whose name matches the input string.", 121, "c:\\4ed\\code\\4coder_search.cpp", 29, 752 }, { PROC_LINKS(list_all_locations_of_type_definition_of_identifier, 0), "list_all_locations_of_type_definition_of_identifier", 51, "Reads a token or word under the cursor and lists all locations of strings that appear to define a type whose name matches it.", 125, "c:\\4ed\\code\\4coder_search.cpp", 29, 763 }, -{ PROC_LINKS(word_complete, 0), "word_complete", 13, "Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.", 130, "c:\\4ed\\code\\4coder_search.cpp", 29, 784 }, +{ PROC_LINKS(word_complete, 0), "word_complete", 13, "Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.", 130, "c:\\4ed\\code\\4coder_search.cpp", 29, 836 }, { PROC_LINKS(goto_jump_at_cursor_direct, 0), "goto_jump_at_cursor_direct", 26, "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.", 187, "c:\\4ed\\code\\4coder_jump_direct.cpp", 34, 8 }, { PROC_LINKS(goto_jump_at_cursor_same_panel_direct, 0), "goto_jump_at_cursor_same_panel_direct", 37, "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..", 168, "c:\\4ed\\code\\4coder_jump_direct.cpp", 34, 31 }, { PROC_LINKS(goto_next_jump_direct, 0), "goto_next_jump_direct", 21, "If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, skipping sub jump locations.", 123, "c:\\4ed\\code\\4coder_jump_direct.cpp", 34, 52 }, diff --git a/4coder_helper.cpp b/4coder_helper.cpp index e600e4f0..f2b87c8c 100644 --- a/4coder_helper.cpp +++ b/4coder_helper.cpp @@ -715,6 +715,11 @@ boundary_alpha_numeric_underscore(Application_Links *app, Buffer_ID buffer, Side return(boundary_predicate(app, buffer, side, direction, pos, &character_predicate_alpha_numeric_underscore)); } +static i64 +boundary_alpha_numeric_underscore_utf8(Application_Links *app, Buffer_ID buffer, Side side, Scan_Direction direction, i64 pos){ + return(boundary_predicate(app, buffer, side, direction, pos, &character_predicate_alpha_numeric_underscore_utf8)); +} + static i64 boundary_alpha_numeric_camel(Application_Links *app, Buffer_ID buffer, Side side, Scan_Direction direction, i64 pos){ i64 an_pos = boundary_alpha_numeric(app, buffer, side, direction, pos); diff --git a/4coder_scope_commands.cpp b/4coder_scope_commands.cpp index 0457f7b4..868c0b12 100644 --- a/4coder_scope_commands.cpp +++ b/4coder_scope_commands.cpp @@ -704,8 +704,8 @@ CUSTOM_DOC("If a scope is currently selected, and a statement or block statement Buffer_Edit edits[2]; edits[0].str_start = 0; edits[0].len = (i32)edit_str.size; - edits[0].start = (i32)(range.max - 1); - edits[0].end = (i32)(range.max - 1); + edits[0].start = (i32)(range.min - 1); + edits[0].end = (i32)(range.min - 1); edits[1].str_start = 0; edits[1].len = 0; edits[1].start = (i32)(range.start); diff --git a/4coder_search.cpp b/4coder_search.cpp index be62b1bf..971f184e 100644 --- a/4coder_search.cpp +++ b/4coder_search.cpp @@ -779,6 +779,69 @@ CUSTOM_DOC("Reads a token or word under the cursor and lists all locations of st // Word Complete Command // +#if 0 + +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.") +{ + View_ID view = get_active_view(app, AccessOpen); + Buffer_ID buffer = view_get_buffer(app, view, AccessOpen); + if (buffer != 0){ + Managed_Scope scope = view_get_managed_scope(app, view); + + local_persist b32 completion_state_initialized = false; + local_persist Data_Table completion_table = {}; + + b32 reset_completion_state = false; + u64 rewrite = 0; + managed_variable_get(app, scope, view_rewrite_loc, &rewrite); + if (rewrite != RewriteWordComplete){ + reset_completion_state = true; + } + managed_variable_set(app, scope, view_next_rewrite_loc, RewriteWordComplete); + + if (!completion_state_initialized || reset_completion_state){ + table_clear(&completion_table); + completion_table = make_Data_table_app_links(app); + + Scratch_Block scratch(app); + + i64 pos = view_get_cursor_pos(app, view); + i64 start_pos = scan(app, boundary_alpha_numeric_underscore_utf8, buffer, Scan_Backward, pos); + if (start_pos < pos){ + i64 check = scan(app, boundary_alpha_numeric_underscore_utf8, buffer, Scan_Forward, start_pos); + if (pos <= check){ + Range_i64 range = Ii64(start_pos, pos); + String_Const_u8 match_prefix = push_buffer_range(app, scratch, buffer, range); + + String_Match_Flag has_flags = StringMatch_CaseSensitive|StringMatch_RightSideSloppy; + String_Match_List not_flags = StringMatch_LeftSideSloppy; + + i64 size = buffer_get_size(app, buffer); + String_Match_List forward = buffer_find_all_matches(app, scratch, buffer, 0, Ii64(pos, size), match_prefix, + &character_predicate_alpha_numeric_underscore_utf8, Scan_Forward); + String_Match_List backward = buffer_find_all_matches(app, scratch, buffer, 0, Ii64(0, start_pos), match_prefix, + &character_predicate_alpha_numeric_underscore_utf8, Scan_Backward); + + string_match_list_filter_flags(&forward , has_flags, not_flags); + string_match_list_filter_flags(&backward, has_flags, not_flags); + + String_Match_List list = string_match_list_merge_nearest(&forward, &backward, range); + + for (String_Match *node = list.first; + node != 0; + node = node->next){ + node->range.end = scan(app, boundary_alpha_numeric_underscore_utf8, node->buffer, Scan_Forward, node->range.end); + } + + } + } + } + } +} + +#else + static Word_Complete_State complete_state = {}; CUSTOM_COMMAND_SIG(word_complete) @@ -787,10 +850,9 @@ CUSTOM_DOC("Iteratively tries completing the word to the left of the cursor with View_ID view = get_active_view(app, AccessOpen); Buffer_ID buffer = view_get_buffer(app, view, AccessOpen); if (buffer != 0){ - i32 do_init = false; - Managed_Scope scope = view_get_managed_scope(app, view); + i32 do_init = false; u64 rewrite = 0; managed_variable_get(app, scope, view_rewrite_loc, &rewrite); if (rewrite != RewriteWordComplete){ @@ -931,6 +993,7 @@ CUSTOM_DOC("Iteratively tries completing the word to the left of the cursor with } } } +#endif // BOTTOM diff --git a/4coder_search.h b/4coder_search.h index 0d725a8c..86d114c0 100644 --- a/4coder_search.h +++ b/4coder_search.h @@ -10,16 +10,23 @@ /* TODO(allen): Time to rewrite _ALL_ of this s***f. -1. String matching optimization study -2. Redesign and reimplement find_all_in_range -3. Filtering and reversing string lists -4. Clean prefix match iterator -5. Reimplement commands in 4coder_search.cpp -6. Ditch all the old s***f we don't want anymore -7. Reorganize, rename, etc. +[x] 1. String matching optimization study +[x] 2. Redesign and reimplement find_all_in_range +[x] 3. Filtering and reversing string lists +[ ] 4. Clean prefix match iterator +[ ] 5. Reimplement commands in 4coder_search.cpp +[ ] 6. Ditch all the old s***f we don't want anymore +[ ] 7. Reorganize, rename, etc. */ +//////////////////////////////// + + + +//////////////////////////////// + +// TODO(allen): deprecate all this typedef i32 Seek_Potential_Match_Direction; enum{ SeekPotentialMatch_Forward = 0, diff --git a/4coder_string_match.cpp b/4coder_string_match.cpp index 4edc0db7..8cf09737 100644 --- a/4coder_string_match.cpp +++ b/4coder_string_match.cpp @@ -40,4 +40,63 @@ string_match_list_join(String_Match_List *dst, String_Match_List *src){ block_zero_struct(src); } -// BOTTOM \ No newline at end of file +internal void +string_match_list_filter_flags(String_Match_List *list, String_Match_Flag must_have_flags, String_Match_Flag must_not_have_flags){ + String_Match_List new_list = {}; + if ((must_have_flags & must_not_have_flags) == 0){ + for (String_Match *node = list->first, *next = 0; + node != 0; + node = next){ + next = node->next; + if ((node->flags & must_have_flags) == must_have_flags && (node->flags & must_not_have_flags) == 0){ + sll_queue_push(new_list.first, new_list.last, node); + new_list.count += 1; + } + } + } + *list = new_list; +} + +internal String_Match_List +string_match_list_merge_nearest(String_Match_List *a, String_Match_List *b, Range_i64 range){ + String_Match_List list = {}; + String_Match *node_a = a->first; + String_Match *node_b = b->first; + for (String_Match *next_a = node_a, *next_b = node_b; + node_a != 0 && node_b != 0; + node_a = next_a, node_b = next_b){ + i64 dist_a = range_distance(node_a->range, range); + i64 dist_b = range_distance(node_b->range, range); + if (dist_a <= dist_b){ + next_a = next_a->next; + sll_queue_push(list.first, list.last, node_a); + list.count += 1; + } + else{ + next_b = next_b->next; + sll_queue_push(list.first, list.last, node_b); + list.count += 1; + } + } + Assert(node_a == 0 || node_b == 0); + String_Match *node = 0; + if (node_a != 0){ + node = node_a; + } + else if (node_b != 0){ + node = node_b; + } + for (String_Match *next = 0; + node != 0; + node = next){ + next = node->next; + sll_queue_push(list.first, list.last, node); + list.count += 1; + } + block_zero_struct(a); + block_zero_struct(b); + return(list); +} + +// BOTTOM + diff --git a/4ed_edit.cpp b/4ed_edit.cpp index 2e227fa8..27826c99 100644 --- a/4ed_edit.cpp +++ b/4ed_edit.cpp @@ -472,7 +472,7 @@ edit_batch(System_Functions *system, Models *models, Editing_File *file, char *s if (edit_count > 0){ History_Record_Index start_index = 0; if (history_is_activated(&file->state.history)){ - start_index = history_get_record_count(&file->state.history); + start_index = file->state.current_record_index; } Buffer_Edit *edit_in = edits; @@ -495,7 +495,7 @@ edit_batch(System_Functions *system, Models *models, Editing_File *file, char *s } if (history_is_activated(&file->state.history)){ - History_Record_Index last_index = history_get_record_count(&file->state.history); + History_Record_Index last_index = file->state.current_record_index; if (start_index + 1 < last_index){ edit_merge_history_range(models, file, start_index + 1, last_index, RecordMergeFlag_StateInRange_ErrorOut); }