From 706370b553588eb789c7eb2d2278e477a1661443 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Fri, 12 Jul 2019 20:19:24 -0700 Subject: [PATCH] New string matching lists based system for search buffer filling --- 4coder_api_transition_30_31_helpers.cpp | 2 +- 4coder_base_commands.cpp | 28 ++-- 4coder_generated/command_metadata.h | 76 +++++----- 4coder_helper.cpp | 60 ++++++-- 4coder_insertion.cpp | 7 + 4coder_search.cpp | 178 ++++++++++++++++++++++-- 4coder_search.h | 6 +- 4coder_string_match.cpp | 44 ++++-- 8 files changed, 317 insertions(+), 84 deletions(-) diff --git a/4coder_api_transition_30_31_helpers.cpp b/4coder_api_transition_30_31_helpers.cpp index fdffed00..305e993c 100644 --- a/4coder_api_transition_30_31_helpers.cpp +++ b/4coder_api_transition_30_31_helpers.cpp @@ -241,7 +241,7 @@ get_token_or_word_under_pos(Application_Links *app, Buffer_Summary *buffer, i32 String result = {}; if (buffer != 0){ Scratch_Block scratch(app); - String_Const_u8 string = get_token_or_word_under_pos(app, scratch, buffer->buffer_id, pos); + String_Const_u8 string = push_token_or_word_under_pos(app, scratch, buffer->buffer_id, pos); i32 size = (i32)string.size; size = clamp_top(size, capacity); block_copy(space, string.str, size); diff --git a/4coder_base_commands.cpp b/4coder_base_commands.cpp index 132de112..c6f4d447 100644 --- a/4coder_base_commands.cpp +++ b/4coder_base_commands.cpp @@ -1117,27 +1117,29 @@ struct String_Pair{ internal String_Pair query_user_replace_pair(Application_Links *app, Arena *arena){ - Query_Bar replace = {}; - u8 replace_space[1024]; - replace.prompt = string_u8_litexpr("Replace: "); - replace.string = SCu8(replace_space, (umem)0); - replace.string_capacity = sizeof(replace_space); + Query_Bar *replace = push_array(arena, Query_Bar, 1); + u8 *replace_space = push_array(arena, u8, KB(1)); + replace->prompt = string_u8_litexpr("Replace: "); + replace->string = SCu8(replace_space, (umem)0); + replace->string_capacity = KB(1); - Query_Bar with = {}; - u8 with_space[1024]; - with.prompt = string_u8_litexpr("With: "); - with.string = SCu8(with_space, (umem)0); - with.string_capacity = sizeof(with_space); + 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, (umem)0); + with->string_capacity = KB(1); String_Pair result = {}; - if (query_user_string(app, &replace) && replace.string.size != 0 && query_user_string(app, &with)){ + if (query_user_string(app, replace) && replace->string.size != 0 && query_user_string(app, with)){ result.valid = true; - result.a = push_string_copy(arena, replace.string); - result.b = push_string_copy(arena, with.string); + result.a = replace->string; + result.b = with->string; } return(result); } +// NOTE(allen): This is a bit of a hacky setup because of Query_Bar lifetimes. This must be +// called as the last operation of a command. internal void replace_in_range_query_user(Application_Links *app, Buffer_ID buffer, Range_i64 range){ Scratch_Block scratch(app); diff --git a/4coder_generated/command_metadata.h b/4coder_generated/command_metadata.h index 97c6bbee..b2325c2c 100644 --- a/4coder_generated/command_metadata.h +++ b/4coder_generated/command_metadata.h @@ -351,33 +351,33 @@ static Command_Metadata fcoder_metacmd_table[237] = { { PROC_LINKS(reverse_search, 0), "reverse_search", 14, "Begins an incremental search up through the current buffer for a user specified string.", 87, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1084 }, { PROC_LINKS(search_identifier, 0), "search_identifier", 17, "Begins an incremental search down through the current buffer for the word or token under the cursor.", 100, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1090 }, { PROC_LINKS(reverse_search_identifier, 0), "reverse_search_identifier", 25, "Begins an incremental search up through the current buffer for the word or token under the cursor.", 98, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1101 }, -{ PROC_LINKS(replace_in_range, 0), "replace_in_range", 16, "Queries the user for a needle and string. Replaces all occurences of needle with string in the range between cursor and the mark in the active buffer.", 150, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1150 }, -{ PROC_LINKS(replace_in_buffer, 0), "replace_in_buffer", 17, "Queries the user for a needle and string. Replaces all occurences of needle with string in the active buffer.", 109, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1159 }, -{ PROC_LINKS(replace_in_all_buffers, 0), "replace_in_all_buffers", 22, "Queries the user for a needle and string. Replaces all occurences of needle with string in all editable buffers.", 112, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1168 }, -{ PROC_LINKS(query_replace, 0), "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1261 }, -{ PROC_LINKS(query_replace_identifier, 0), "query_replace_identifier", 24, "Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string.", 140, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1281 }, -{ PROC_LINKS(query_replace_selection, 0), "query_replace_selection", 23, "Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string.", 141, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1297 }, -{ PROC_LINKS(save_all_dirty_buffers, 0), "save_all_dirty_buffers", 22, "Saves all buffers marked dirty (showing the '*' indicator).", 59, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1332 }, -{ PROC_LINKS(delete_file_query, 0), "delete_file_query", 17, "Deletes the file of the current buffer if 4coder has the appropriate access rights. Will ask the user for confirmation first.", 125, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1357 }, -{ PROC_LINKS(save_to_query, 0), "save_to_query", 13, "Queries the user for a file name and saves the contents of the current buffer, altering the buffer's name too.", 110, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1395 }, -{ PROC_LINKS(rename_file_query, 0), "rename_file_query", 17, "Queries the user for a new name and renames the file of the current buffer, altering the buffer's name too.", 107, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1430 }, -{ PROC_LINKS(make_directory_query, 0), "make_directory_query", 20, "Queries the user for a name and creates a new directory with the given name.", 76, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1470 }, -{ PROC_LINKS(move_line_up, 0), "move_line_up", 12, "Swaps the line under the cursor with the line above it, and moves the cursor up with it.", 88, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1503 }, -{ PROC_LINKS(move_line_down, 0), "move_line_down", 14, "Swaps the line under the cursor with the line below it, and moves the cursor down with it.", 90, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1509 }, -{ PROC_LINKS(duplicate_line, 0), "duplicate_line", 14, "Create a copy of the line on which the cursor sits.", 51, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1515 }, -{ PROC_LINKS(delete_line, 0), "delete_line", 11, "Delete the line the on which the cursor sits.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1529 }, -{ PROC_LINKS(open_file_in_quotes, 0), "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1594 }, -{ PROC_LINKS(open_matching_file_cpp, 0), "open_matching_file_cpp", 22, "If the current file is a *.cpp or *.h, attempts to open the corresponding *.h or *.cpp file in the other view.", 110, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1626 }, -{ PROC_LINKS(view_buffer_other_panel, 0), "view_buffer_other_panel", 23, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1639 }, -{ PROC_LINKS(swap_buffers_between_panels, 0), "swap_buffers_between_panels", 27, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1651 }, -{ PROC_LINKS(kill_buffer, 0), "kill_buffer", 11, "Kills the current buffer.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1685 }, -{ PROC_LINKS(save, 0), "save", 4, "Saves the current buffer.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1693 }, -{ PROC_LINKS(reopen, 0), "reopen", 6, "Reopen the current buffer from the hard drive.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1705 }, -{ PROC_LINKS(undo, 0), "undo", 4, "Advances backwards through the undo history of the current buffer.", 66, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1763 }, -{ PROC_LINKS(redo, 0), "redo", 4, "Advances forwards through the undo history of the current buffer.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1776 }, -{ PROC_LINKS(undo_all_buffers, 0), "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1790 }, -{ PROC_LINKS(redo_all_buffers, 0), "redo_all_buffers", 16, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1864 }, -{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1967 }, +{ PROC_LINKS(replace_in_range, 0), "replace_in_range", 16, "Queries the user for a needle and string. Replaces all occurences of needle with string in the range between cursor and the mark in the active buffer.", 150, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1152 }, +{ PROC_LINKS(replace_in_buffer, 0), "replace_in_buffer", 17, "Queries the user for a needle and string. Replaces all occurences of needle with string in the active buffer.", 109, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1161 }, +{ PROC_LINKS(replace_in_all_buffers, 0), "replace_in_all_buffers", 22, "Queries the user for a needle and string. Replaces all occurences of needle with string in all editable buffers.", 112, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1170 }, +{ PROC_LINKS(query_replace, 0), "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1263 }, +{ PROC_LINKS(query_replace_identifier, 0), "query_replace_identifier", 24, "Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string.", 140, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1283 }, +{ PROC_LINKS(query_replace_selection, 0), "query_replace_selection", 23, "Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string.", 141, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1299 }, +{ PROC_LINKS(save_all_dirty_buffers, 0), "save_all_dirty_buffers", 22, "Saves all buffers marked dirty (showing the '*' indicator).", 59, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1334 }, +{ PROC_LINKS(delete_file_query, 0), "delete_file_query", 17, "Deletes the file of the current buffer if 4coder has the appropriate access rights. Will ask the user for confirmation first.", 125, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1359 }, +{ PROC_LINKS(save_to_query, 0), "save_to_query", 13, "Queries the user for a file name and saves the contents of the current buffer, altering the buffer's name too.", 110, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1397 }, +{ PROC_LINKS(rename_file_query, 0), "rename_file_query", 17, "Queries the user for a new name and renames the file of the current buffer, altering the buffer's name too.", 107, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1432 }, +{ PROC_LINKS(make_directory_query, 0), "make_directory_query", 20, "Queries the user for a name and creates a new directory with the given name.", 76, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1472 }, +{ PROC_LINKS(move_line_up, 0), "move_line_up", 12, "Swaps the line under the cursor with the line above it, and moves the cursor up with it.", 88, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1505 }, +{ PROC_LINKS(move_line_down, 0), "move_line_down", 14, "Swaps the line under the cursor with the line below it, and moves the cursor down with it.", 90, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1511 }, +{ PROC_LINKS(duplicate_line, 0), "duplicate_line", 14, "Create a copy of the line on which the cursor sits.", 51, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1517 }, +{ PROC_LINKS(delete_line, 0), "delete_line", 11, "Delete the line the on which the cursor sits.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1531 }, +{ PROC_LINKS(open_file_in_quotes, 0), "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1596 }, +{ PROC_LINKS(open_matching_file_cpp, 0), "open_matching_file_cpp", 22, "If the current file is a *.cpp or *.h, attempts to open the corresponding *.h or *.cpp file in the other view.", 110, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1628 }, +{ PROC_LINKS(view_buffer_other_panel, 0), "view_buffer_other_panel", 23, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1641 }, +{ PROC_LINKS(swap_buffers_between_panels, 0), "swap_buffers_between_panels", 27, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1653 }, +{ PROC_LINKS(kill_buffer, 0), "kill_buffer", 11, "Kills the current buffer.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1687 }, +{ PROC_LINKS(save, 0), "save", 4, "Saves the current buffer.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1695 }, +{ PROC_LINKS(reopen, 0), "reopen", 6, "Reopen the current buffer from the hard drive.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1707 }, +{ PROC_LINKS(undo, 0), "undo", 4, "Advances backwards through the undo history of the current buffer.", 66, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1765 }, +{ PROC_LINKS(redo, 0), "redo", 4, "Advances forwards through the undo history of the current buffer.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1778 }, +{ PROC_LINKS(undo_all_buffers, 0), "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1792 }, +{ PROC_LINKS(redo_all_buffers, 0), "redo_all_buffers", 16, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1866 }, +{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1969 }, { PROC_LINKS(lister__quit, 0), "lister__quit", 12, "A lister mode command that quits the list without executing any actions.", 72, "w:\\4ed\\code\\4coder_lists.cpp", 28, 8 }, { PROC_LINKS(lister__activate, 0), "lister__activate", 16, "A lister mode command that activates the list's action on the highlighted item.", 79, "w:\\4ed\\code\\4coder_lists.cpp", 28, 15 }, { PROC_LINKS(lister__write_character, 0), "lister__write_character", 23, "A lister mode command that dispatches to the lister's write character handler.", 78, "w:\\4ed\\code\\4coder_lists.cpp", 28, 30 }, @@ -405,17 +405,17 @@ static Command_Metadata fcoder_metacmd_table[237] = { { PROC_LINKS(auto_tab_line_at_cursor, 0), "auto_tab_line_at_cursor", 23, "Auto-indents the line on which the cursor sits.", 47, "w:\\4ed\\code\\4coder_auto_indent.cpp", 34, 555 }, { PROC_LINKS(auto_tab_range, 0), "auto_tab_range", 14, "Auto-indents the range between the cursor and the mark.", 55, "w:\\4ed\\code\\4coder_auto_indent.cpp", 34, 565 }, { PROC_LINKS(write_and_auto_tab, 0), "write_and_auto_tab", 18, "Inserts a character and auto-indents the line on which the cursor sits.", 71, "w:\\4ed\\code\\4coder_auto_indent.cpp", 34, 575 }, -{ PROC_LINKS(list_all_locations, 0), "list_all_locations", 18, "Queries the user for a string and lists all exact case-sensitive matches found in all open buffers.", 99, "w:\\4ed\\code\\4coder_search.cpp", 29, 15 }, -{ PROC_LINKS(list_all_substring_locations, 0), "list_all_substring_locations", 28, "Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.", 103, "w:\\4ed\\code\\4coder_search.cpp", 29, 21 }, -{ PROC_LINKS(list_all_locations_case_insensitive, 0), "list_all_locations_case_insensitive", 35, "Queries the user for a string and lists all exact case-insensitive matches found in all open buffers.", 101, "w:\\4ed\\code\\4coder_search.cpp", 29, 27 }, -{ PROC_LINKS(list_all_substring_locations_case_insensitive, 0), "list_all_substring_locations_case_insensitive", 45, "Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.", 105, "w:\\4ed\\code\\4coder_search.cpp", 29, 33 }, -{ PROC_LINKS(list_all_locations_of_identifier, 0), "list_all_locations_of_identifier", 32, "Reads a token or word under the cursor and lists all exact case-sensitive mathces in all open buffers.", 102, "w:\\4ed\\code\\4coder_search.cpp", 29, 39 }, -{ PROC_LINKS(list_all_locations_of_identifier_case_insensitive, 0), "list_all_locations_of_identifier_case_insensitive", 49, "Reads a token or word under the cursor and lists all exact case-insensitive mathces in all open buffers.", 104, "w:\\4ed\\code\\4coder_search.cpp", 29, 45 }, -{ PROC_LINKS(list_all_locations_of_selection, 0), "list_all_locations_of_selection", 31, "Reads the string in the selected range and lists all exact case-sensitive mathces in all open buffers.", 102, "w:\\4ed\\code\\4coder_search.cpp", 29, 51 }, -{ 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, "w:\\4ed\\code\\4coder_search.cpp", 29, 57 }, -{ 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, "w:\\4ed\\code\\4coder_search.cpp", 29, 63 }, -{ 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, "w:\\4ed\\code\\4coder_search.cpp", 29, 69 }, -{ 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, "w:\\4ed\\code\\4coder_search.cpp", 29, 75 }, +{ PROC_LINKS(list_all_locations, 0), "list_all_locations", 18, "Queries the user for a string and lists all exact case-sensitive matches found in all open buffers.", 99, "w:\\4ed\\code\\4coder_search.cpp", 29, 164 }, +{ PROC_LINKS(list_all_substring_locations, 0), "list_all_substring_locations", 28, "Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.", 103, "w:\\4ed\\code\\4coder_search.cpp", 29, 170 }, +{ PROC_LINKS(list_all_locations_case_insensitive, 0), "list_all_locations_case_insensitive", 35, "Queries the user for a string and lists all exact case-insensitive matches found in all open buffers.", 101, "w:\\4ed\\code\\4coder_search.cpp", 29, 176 }, +{ PROC_LINKS(list_all_substring_locations_case_insensitive, 0), "list_all_substring_locations_case_insensitive", 45, "Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.", 105, "w:\\4ed\\code\\4coder_search.cpp", 29, 182 }, +{ PROC_LINKS(list_all_locations_of_identifier, 0), "list_all_locations_of_identifier", 32, "Reads a token or word under the cursor and lists all exact case-sensitive mathces in all open buffers.", 102, "w:\\4ed\\code\\4coder_search.cpp", 29, 188 }, +{ PROC_LINKS(list_all_locations_of_identifier_case_insensitive, 0), "list_all_locations_of_identifier_case_insensitive", 49, "Reads a token or word under the cursor and lists all exact case-insensitive mathces in all open buffers.", 104, "w:\\4ed\\code\\4coder_search.cpp", 29, 194 }, +{ PROC_LINKS(list_all_locations_of_selection, 0), "list_all_locations_of_selection", 31, "Reads the string in the selected range and lists all exact case-sensitive mathces in all open buffers.", 102, "w:\\4ed\\code\\4coder_search.cpp", 29, 200 }, +{ 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, "w:\\4ed\\code\\4coder_search.cpp", 29, 206 }, +{ 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, "w:\\4ed\\code\\4coder_search.cpp", 29, 212 }, +{ 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, "w:\\4ed\\code\\4coder_search.cpp", 29, 220 }, +{ 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, "w:\\4ed\\code\\4coder_search.cpp", 29, 229 }, { 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, "w:\\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, "w:\\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, "w:\\4ed\\code\\4coder_jump_direct.cpp", 34, 52 }, diff --git a/4coder_helper.cpp b/4coder_helper.cpp index 24407dca..d37fc1a0 100644 --- a/4coder_helper.cpp +++ b/4coder_helper.cpp @@ -1166,6 +1166,12 @@ push_view_range_string(Application_Links *app, Arena *arena, View_ID view){ return(push_buffer_range(app, arena, buffer, get_view_range(app, view))); } +internal String_Const_u8 +push_view_range_string(Application_Links *app, Arena *arena){ + View_ID view = get_active_view(app, AccessAll); + return(push_view_range_string(app, arena, view)); +} + static String_Const_u8 push_enclose_range_at_pos(Application_Links *app, Arena *arena, Buffer_ID buffer, i64 pos, Enclose_Function *enclose){ Range_i64 range = enclose(app, buffer, Ii64(pos)); @@ -1446,6 +1452,39 @@ move_line(Application_Links *app, Buffer_ID buffer, i64 line_number, Scan_Direct return(result); } +static void +clear_buffer(Application_Links *app, Buffer_ID buffer){ + buffer_replace_range(app, buffer, buffer_range(app, buffer), string_u8_litexpr("")); +} + +//////////////////////////////// + +internal String_Match_List +find_all_matches_all_buffers(Application_Links *app, Arena *arena, String_Const_u8_Array match_patterns, String_Match_Flag must_have_flags, String_Match_Flag must_not_have_flags){ + String_Match_List all_matches = {}; + for (Buffer_ID buffer = get_buffer_next(app, 0, AccessAll); + buffer != 0; + buffer = get_buffer_next(app, buffer, AccessAll)){ + String_Match_List buffer_matches = {}; + for (i32 i = 0; i < match_patterns.count; i += 1){ + Range_i64 range = buffer_range(app, buffer); + String_Match_List pattern_matches = buffer_find_all_matches(app, arena, buffer, i, range, match_patterns.vals[i], + &character_predicate_alpha_numeric_underscore_utf8, Scan_Forward); + string_match_list_filter_flags(&pattern_matches, must_have_flags, must_not_have_flags); + if (pattern_matches.count > 0){ + if (buffer_matches.count == 0){ + buffer_matches = pattern_matches; + } + else{ + buffer_matches = string_match_list_merge_front_to_back(&buffer_matches, &pattern_matches); + } + } + } + all_matches = string_match_list_join(&all_matches, &buffer_matches); + } + return(all_matches); +} + //////////////////////////////// static void @@ -1758,13 +1797,6 @@ try_buffer_kill(Application_Links *app, Buffer_ID buffer, View_ID gui_view_id, B //////////////////////////////// -static void -clear_buffer(Application_Links *app, Buffer_ID buffer){ - buffer_replace_range(app, buffer, buffer_range(app, buffer), string_u8_litexpr("")); -} - -//////////////////////////////// - static b32 init_stream_chunk(Stream_Chunk *chunk, Application_Links *app, Buffer_ID buffer_id, i32 pos, char *data, u32 size){ @@ -1976,10 +2008,10 @@ token_iterator_goto_prev_raw(Token_Iterator *iterator){ //////////////////////////////// static String_Const_u8 -get_query_string(Application_Links *app, char *query_str, char *string_space, i32 space_size){ +get_query_string(Application_Links *app, char *query_str, u8 *string_space, i32 space_size){ Query_Bar bar; bar.prompt = SCu8((u8*)query_str); - bar.string = SCu8((u8*)string_space, (umem)0); + bar.string = SCu8(string_space, (umem)0); bar.string_capacity = space_size; if (!query_user_string(app, &bar)){ bar.string.size = 0; @@ -1999,7 +2031,7 @@ get_token_from_pos(Application_Links *app, Buffer_ID buffer, u64 pos, Cpp_Get_To } static String_Const_u8 -get_token_or_word_under_pos(Application_Links *app, Arena *arena, Buffer_ID buffer, u64 pos){ +push_token_or_word_under_pos(Application_Links *app, Arena *arena, Buffer_ID buffer, u64 pos){ String_Const_u8 result = {}; Cpp_Get_Token_Result get_result = {}; b32 success = get_token_from_pos(app, buffer, (i32)pos, &get_result); @@ -2012,6 +2044,14 @@ get_token_or_word_under_pos(Application_Links *app, Arena *arena, Buffer_ID buff return(result); } +internal String_Const_u8 +push_token_or_word_under_active_cursor(Application_Links *app, Arena *arena){ + View_ID view = get_active_view(app, AccessAll); + Buffer_ID buffer = view_get_buffer(app, view, AccessAll); + i64 pos = view_get_cursor_pos(app, view); + return(push_token_or_word_under_pos(app, arena, buffer, pos)); +} + static b32 lexer_keywords_default_init(Arena *arena, Cpp_Keyword_Table *kw_out, Cpp_Keyword_Table *pp_out){ b32 success = false; diff --git a/4coder_insertion.cpp b/4coder_insertion.cpp index e26e169a..cd3dec4d 100644 --- a/4coder_insertion.cpp +++ b/4coder_insertion.cpp @@ -22,6 +22,13 @@ begin_buffer_insertion_at_buffered(Application_Links *app, Buffer_ID buffer_id, return(result); } +internal Buffer_Insertion +begin_buffer_insertion_at_buffered(Application_Links *app, Buffer_ID buffer_id, i64 at, Arena *buffer_memory, umem buffer_memory_size){ + Cursor *cursor = push_array(buffer_memory, Cursor, 1); + *cursor = make_cursor(push_array(buffer_memory, u8, buffer_memory_size), buffer_memory_size); + return(begin_buffer_insertion_at_buffered(app, buffer_id, at, cursor)); +} + static Buffer_Insertion begin_buffer_insertion(Application_Links *app){ View_ID view = get_active_view(app, AccessAll); diff --git a/4coder_search.cpp b/4coder_search.cpp index a0804fbb..258531ff 100644 --- a/4coder_search.cpp +++ b/4coder_search.cpp @@ -9,67 +9,221 @@ and list all locations. // Search Iteration Systems // -#if Migrate__Match_Iterator +global String_Const_u8 search_name = string_u8_litexpr("*search*"); +internal void +print_string_match_list_to_buffer(Application_Links *app, Buffer_ID out_buffer_id, String_Match_List matches){ + Scratch_Block scratch(app); + clear_buffer(app, out_buffer_id); + 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; + + for (String_Match *node = matches.first; + node != 0; + node = node->next){ + if (node->buffer != out_buffer_id){ + if (current_buffer != 0 && current_buffer != node->buffer){ + insertc(&out, '\n'); + } + if (current_buffer != node->buffer){ + end_temp(buffer_name_restore_point); + current_buffer = node->buffer; + current_file_name = push_buffer_file_name(app, scratch, current_buffer); + if (current_file_name.size == 0){ + current_file_name = push_buffer_unique_name(app, scratch, current_buffer); + } + } + + Partial_Cursor partial_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, partial_cursor.line); + String_Const_u8 line_str = string_skip_chop_whitespace(full_line_str); + insertf(&out, "%.*s:%d:%d: %.*s\n", string_expand(current_file_name), partial_cursor.line, partial_cursor.character, string_expand(line_str)); + end_temp(line_temp); + } + } + + end_buffer_insertion(&out); +} + +internal void +print_all_matches_all_buffers(Application_Links *app, String_Const_u8_Array match_patterns, String_Match_Flag must_have_flags, String_Match_Flag must_not_have_flags, Buffer_ID out_buffer_id){ + Scratch_Block scratch(app); + String_Match_List matches = find_all_matches_all_buffers(app, scratch, match_patterns, must_have_flags, must_not_have_flags); + Buffer_ID messages_buffer = get_buffer_by_name(app, string_u8_litexpr("*messages*"), AccessAll); + string_match_list_filter_remove_buffer(&matches, out_buffer_id); + if (out_buffer_id != messages_buffer){ + string_match_list_filter_remove_buffer(&matches, messages_buffer); + } + print_string_match_list_to_buffer(app, out_buffer_id, matches); +} + +internal void +print_all_matches_all_buffers(Application_Links *app, String_Const_u8 pattern, String_Match_Flag must_have_flags, String_Match_Flag must_not_have_flags, Buffer_ID out_buffer_id){ + String_Const_u8_Array array = {&pattern, 1}; + print_all_matches_all_buffers(app, array, must_have_flags, must_not_have_flags, out_buffer_id); +} + +internal void +print_all_matches_all_buffers_to_search(Application_Links *app, String_Const_u8_Array match_patterns, String_Match_Flag must_have_flags, String_Match_Flag must_not_have_flags, View_ID default_target_view){ + Buffer_ID search_buffer = create_or_switch_to_buffer_and_clear_by_name(app, search_name, default_target_view); + print_all_matches_all_buffers(app, match_patterns, must_have_flags, must_not_have_flags, search_buffer); +} + +internal void +print_all_matches_all_buffers_to_search(Application_Links *app, String_Const_u8 pattern, String_Match_Flag must_have_flags, String_Match_Flag must_not_have_flags, View_ID default_target_view){ + String_Const_u8_Array array = {&pattern, 1}; + print_all_matches_all_buffers_to_search(app, array, must_have_flags, must_not_have_flags, default_target_view); +} + +internal String_Const_u8 +query_user_list_needle(Application_Links *app, Arena *arena){ + u8 *space = push_array(arena, u8, KB(1)); + return(get_query_string(app, "List Locations For: ", space, KB(1))); +} + +internal String_Const_u8_Array +user_list_definition_array(Application_Links *app, Arena *arena, String_Const_u8 base_needle){ + String_Const_u8_Array result = {}; + if (base_needle.size > 0){ + result.count = 9; + result.vals = push_array(arena, String_Const_u8, result.count); + i32 i = 0; + result.vals[i++] = (push_u8_stringf(arena, "struct %.*s{" , string_expand(base_needle))); + result.vals[i++] = (push_u8_stringf(arena, "struct %.*s\n{", string_expand(base_needle))); + result.vals[i++] = (push_u8_stringf(arena, "struct %.*s {" , string_expand(base_needle))); + result.vals[i++] = (push_u8_stringf(arena, "union %.*s{" , string_expand(base_needle))); + result.vals[i++] = (push_u8_stringf(arena, "union %.*s\n{" , string_expand(base_needle))); + result.vals[i++] = (push_u8_stringf(arena, "union %.*s {" , string_expand(base_needle))); + result.vals[i++] = (push_u8_stringf(arena, "enum %.*s{" , string_expand(base_needle))); + result.vals[i++] = (push_u8_stringf(arena, "enum %.*s\n{" , string_expand(base_needle))); + result.vals[i++] = (push_u8_stringf(arena, "enum %.*s {" , string_expand(base_needle))); + Assert(i == result.count); + } + return(result); +} + +internal String_Const_u8_Array +query_user_list_definition_needle(Application_Links *app, Arena *arena){ + u8 *space = push_array(arena, u8, KB(1)); + String_Const_u8 base_needle = get_query_string(app, "List Definitions For: ", space, KB(1)); + return(user_list_definition_array(app, arena, base_needle)); +} + +internal void +list_all_locations__generic(Application_Links *app, String_Const_u8_Array needle, List_All_Locations_Flag flags){ + if (needle.count > 0){ + View_ID target_view = get_next_view_after_active(app, AccessAll); + String_Match_Flag must_have_flags = 0; + String_Match_Flag must_not_have_flags = 0; + if (HasFlag(flags, ListAllLocationsFlag_CaseSensitive)){ + AddFlag(must_have_flags, StringMatch_CaseSensitive); + } + if (!HasFlag(flags, ListAllLocationsFlag_MatchSubstring)){ + AddFlag(must_not_have_flags, StringMatch_LeftSideSloppy); + AddFlag(must_not_have_flags, StringMatch_RightSideSloppy); + } + print_all_matches_all_buffers_to_search(app, needle, must_have_flags, must_not_have_flags, target_view); + } +} + +internal void +list_all_locations__generic(Application_Links *app, String_Const_u8 needle, List_All_Locations_Flag flags){ + String_Const_u8_Array array = {&needle, 1}; + list_all_locations__generic(app, array, flags); +} + +internal void +list_all_locations__generic_query(Application_Links *app, List_All_Locations_Flag flags){ + Scratch_Block scratch(app); + String_Const_u8 needle = query_user_list_needle(app, scratch); + list_all_locations__generic(app, needle, flags); +} + +internal void +list_all_locations__generic_identifier(Application_Links *app, List_All_Locations_Flag flags){ + Scratch_Block scratch(app); + String_Const_u8 needle = push_token_or_word_under_active_cursor(app, scratch); + list_all_locations__generic(app, needle, flags); +} + +internal void +list_all_locations__generic_view_range(Application_Links *app, List_All_Locations_Flag flags){ + Scratch_Block scratch(app); + String_Const_u8 needle = push_view_range_string(app, scratch); + list_all_locations__generic(app, needle, flags); +} + +#if Migrate__Match_Iterator CUSTOM_COMMAND_SIG(list_all_locations) CUSTOM_DOC("Queries the user for a string and lists all exact case-sensitive matches found in all open buffers.") { - NotImplemented; + list_all_locations__generic_query(app, ListAllLocationsFlag_CaseSensitive); } CUSTOM_COMMAND_SIG(list_all_substring_locations) CUSTOM_DOC("Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.") { - NotImplemented; + list_all_locations__generic_query(app, ListAllLocationsFlag_CaseSensitive|ListAllLocationsFlag_MatchSubstring); } CUSTOM_COMMAND_SIG(list_all_locations_case_insensitive) CUSTOM_DOC("Queries the user for a string and lists all exact case-insensitive matches found in all open buffers.") { - NotImplemented; + list_all_locations__generic_query(app, 0); } CUSTOM_COMMAND_SIG(list_all_substring_locations_case_insensitive) CUSTOM_DOC("Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.") { - NotImplemented; + list_all_locations__generic_query(app, ListAllLocationsFlag_MatchSubstring); } CUSTOM_COMMAND_SIG(list_all_locations_of_identifier) CUSTOM_DOC("Reads a token or word under the cursor and lists all exact case-sensitive mathces in all open buffers.") { - NotImplemented; + list_all_locations__generic_identifier(app, ListAllLocationsFlag_CaseSensitive); } CUSTOM_COMMAND_SIG(list_all_locations_of_identifier_case_insensitive) CUSTOM_DOC("Reads a token or word under the cursor and lists all exact case-insensitive mathces in all open buffers.") { - NotImplemented; + list_all_locations__generic_identifier(app, ListAllLocationsFlag_CaseSensitive|ListAllLocationsFlag_MatchSubstring); } CUSTOM_COMMAND_SIG(list_all_locations_of_selection) CUSTOM_DOC("Reads the string in the selected range and lists all exact case-sensitive mathces in all open buffers.") { - NotImplemented; + list_all_locations__generic_view_range(app, ListAllLocationsFlag_CaseSensitive); } CUSTOM_COMMAND_SIG(list_all_locations_of_selection_case_insensitive) CUSTOM_DOC("Reads the string in the selected range and lists all exact case-insensitive mathces in all open buffers.") { - NotImplemented; + list_all_locations__generic_view_range(app, 0); } CUSTOM_COMMAND_SIG(list_all_locations_of_type_definition) CUSTOM_DOC("Queries user for string, lists all locations of strings that appear to define a type whose name matches the input string.") { - NotImplemented; + Scratch_Block scratch(app); + String_Const_u8_Array array = query_user_list_definition_needle(app, scratch); + list_all_locations__generic(app, array, ListAllLocationsFlag_CaseSensitive|ListAllLocationsFlag_MatchSubstring); } CUSTOM_COMMAND_SIG(list_all_locations_of_type_definition_of_identifier) CUSTOM_DOC("Reads a token or word under the cursor and lists all locations of strings that appear to define a type whose name matches it.") { - NotImplemented; + Scratch_Block scratch(app); + String_Const_u8 base_needle = push_token_or_word_under_active_cursor(app, scratch); + String_Const_u8_Array array = user_list_definition_array(app, scratch, base_needle); + list_all_locations__generic(app, array, ListAllLocationsFlag_CaseSensitive|ListAllLocationsFlag_MatchSubstring); } CUSTOM_COMMAND_SIG(word_complete) @@ -616,8 +770,6 @@ initialize_generic_search_all_buffers(Application_Links *app, Heap *heap, String //////////////////////////////// -static String_Const_u8 search_name = string_u8_litexpr("*search*"); - static void list__parameters_buffer(Application_Links *app, Heap *heap, String_Const_u8 *strings, i32 count, Search_Range_Flag match_flags, diff --git a/4coder_search.h b/4coder_search.h index d3ed38e7..01b00821 100644 --- a/4coder_search.h +++ b/4coder_search.h @@ -24,7 +24,11 @@ Time to rewrite _ALL_ of this s***f. //////////////////////////////// - +typedef u32 List_All_Locations_Flag; +enum{ + ListAllLocationsFlag_CaseSensitive = 1, + ListAllLocationsFlag_MatchSubstring = 2, +}; //////////////////////////////// diff --git a/4coder_string_match.cpp b/4coder_string_match.cpp index 8cf09737..4c8b4f6d 100644 --- a/4coder_string_match.cpp +++ b/4coder_string_match.cpp @@ -28,16 +28,23 @@ string_match_list_push(Arena *arena, String_Match_List *list, make_range_i64(start, start + length)); } -internal void -string_match_list_join(String_Match_List *dst, String_Match_List *src){ - if (dst->last != 0){ - dst->last->next = src->first; +internal String_Match_List +string_match_list_join(String_Match_List *a, String_Match_List *b){ + String_Match_List list = *a; + block_zero_struct(a); + if (list.last != 0){ + list.last->next = b->first; + if (b->last != 0){ + list.last = b->last; + } } - if (src->last != 0){ - dst->last = src->last; + else{ + list.first = b->first; + list.last = b->last; } - dst->count += src->count; - block_zero_struct(src); + list.count += b->count; + block_zero_struct(b); + return(list); } internal void @@ -57,6 +64,21 @@ string_match_list_filter_flags(String_Match_List *list, String_Match_Flag must_h *list = new_list; } +internal void +string_match_list_filter_remove_buffer(String_Match_List *list, Buffer_ID buffer){ + String_Match_List new_list = {}; + for (String_Match *node = list->first, *next = 0; + node != 0; + node = next){ + next = node->next; + if (node->buffer != buffer){ + 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 = {}; @@ -79,6 +101,7 @@ string_match_list_merge_nearest(String_Match_List *a, String_Match_List *b, Rang } } Assert(node_a == 0 || node_b == 0); + // TODO(allen): this is dumb O(n) work that could be O(1) String_Match *node = 0; if (node_a != 0){ node = node_a; @@ -98,5 +121,10 @@ string_match_list_merge_nearest(String_Match_List *a, String_Match_List *b, Rang return(list); } +internal String_Match_List +string_match_list_merge_front_to_back(String_Match_List *a, String_Match_List *b){ + return(string_match_list_merge_nearest(a, b, make_range_i64(0))); +} + // BOTTOM