diff --git a/4coder_API.html b/4coder_API.html index b0d75b5a..2769ca27 100644 --- a/4coder_API.html +++ b/4coder_API.html @@ -298,7 +298,7 @@ It should point at the String in the first element of the array.
count
The count parameter specifies the number of elements in the str_set array.
str
The str parameter specifies the string to match against the str_set.
match_index
If this call succeeds match_index is filled with the index into str_set where the match occurred.
Description
This call tries to see if str matches any of the strings in str_set. If there is a match the call succeeds and returns non-zero. The matching rule is equivalent to the matching rule for match.

See Also
match

§4.3.116: string_set_match

fstr_bool string_set_match(
String *str_set,
int32_t count,
String str,
int32_t *match_index
)
Parameters
str_set
The str_set parameter is an array of String structs specifying matchable strings.
count
The count parameter specifies the number of String structs in the str_set array.
str
The str parameter specifies the string to match against the str_set.
match_index
If this call succeeds match_index is filled with the index into str_set where the match occurred.
Description
This call tries to see if str matches any of the strings in str_set. If there is a match the call succeeds and returns non-zero. The matching rule is equivalent to the matching rule for match.

See Also
match

-

§5 Lexer Library

§5.1 Lexer Intro

The 4cpp lexer system provides a polished, fast, flexible system that takes in C/C++ and outputs a tokenization of the text data. There are two API levels. One level is setup to let you easily get a tokenization of the file. This level manages memory for you with malloc to make it as fast as possible to start getting your tokens. The second level enables deep integration by allowing control over allocation, data chunking, and output rate control.

To use the quick setup API you simply include 4cpp_lexer.h and read the documentation at cpp_lex_file.

To use the the fancier API include 4cpp_lexer.h and read the documentation at cpp_lex_step. If you want to be absolutely sure you are not including malloc into your program you can define FCPP_FORBID_MALLOC before the include and the "step" API will continue to work.

There are a few more features in 4cpp that are not documented yet. You are free to try to use these, but I am not totally sure they are ready yet, and when they are they will be documented.

§5.2 Lexer Function List

§5.3 Lexer Types List

§5.4 Lexer Function Descriptions

§5.4.1: cpp_get_token

Cpp_Get_Token_Result cpp_get_token(
Cpp_Token_Array *token_array_in,
int32_t pos
)
Parameters
token_array
The array of tokens from which to get a token.
pos
The position, measured in bytes, to get the token for.
Return
A Cpp_Get_Token_Result struct is returned containing the index +

§5 Lexer Library

§5.1 Lexer Intro

The 4cpp lexer system provides a polished, fast, flexible system that takes in C/C++ and outputs a tokenization of the text data. There are two API levels. One level is setup to let you easily get a tokenization of the file. This level manages memory for you with malloc to make it as fast as possible to start getting your tokens. The second level enables deep integration by allowing control over allocation, data chunking, and output rate control.

To use the quick setup API you simply include 4cpp_lexer.h and read the documentation at cpp_lex_file.

To use the the fancier API include 4cpp_lexer.h and read the documentation at cpp_lex_step. If you want to be absolutely sure you are not including malloc into your program you can define FCPP_FORBID_MALLOC before the include and the "step" API will continue to work.

There are a few more features in 4cpp that are not documented yet. You are free to try to use these, but I am not totally sure they are ready yet, and when they are they will be documented.

§5.2 Lexer Function List

§5.3 Lexer Types List

§5.4 Lexer Function Descriptions

§5.4.1: cpp_get_token

Cpp_Get_Token_Result cpp_get_token(
Cpp_Token_Array array,
int32_t pos
)
Parameters
array
The array of tokens from which to get a token.
pos
The position, measured in bytes, to get the token for.
Return
A Cpp_Get_Token_Result struct is returned containing the index of a token and a flag indicating whether the pos is contained in the token or in whitespace after the token.
Description
This call performs a binary search over all of the tokens looking for the token that contains the specified position. If the position @@ -419,9 +419,11 @@ It is the primary output of the lexing system.

Fields
tokens
The tokens field points to the memory used to store the array of tokens.

count
The count field counts how many tokens in the array are currently used.

max_count
The max_count field specifies the maximum size the count field may grow to before - the tokens array is out of space.


§5.5.5: Cpp_Get_Token_Result

struct Cpp_Get_Token_Result {
int32_t token_index;
int32_t in_whitespace;
};
Description
Cpp_Get_Token_Result is the return result of the cpp_get_token call.

Fields
token_index
The token_index field indicates which token answers the query. To get the token from + the tokens array is out of space.


§5.5.5: Cpp_Get_Token_Result

struct Cpp_Get_Token_Result {
int32_t token_index;
int32_t in_whitespace;
int32_t token_start;
int32_t token_end;
};
Description
Cpp_Get_Token_Result is the return result of the cpp_get_token call.

Fields
token_index
The token_index field indicates which token answers the query. To get the token from the source array

array.tokens[result.token_index]
in_whitespace
The in_whitespace field is true when the query position was actually in whitespace - after the result token.

See Also
cpp_get_token

§5.5.6: Cpp_Relex_Range

struct Cpp_Relex_Range {
int32_t start_token_index;
int32_t end_token_index;
};
Description
Cpp_Relex_Range is the return result of the cpp_get_relex_range call.

Fields
start_token_index
The index of the first token in the unedited array that needs to be relexed.

end_token_index
The index of the first token in the unedited array after the edited range + after the result token.

token_start
If the token_index refers to an actual token, this is the start value of the token. + Otherwise this is zero.

token_end
If the token_index refers to an actual token, this is the start+size value of the token. + Otherwise this is zero.

See Also
cpp_get_token

§5.5.6: Cpp_Relex_Range

struct Cpp_Relex_Range {
int32_t start_token_index;
int32_t end_token_index;
};
Description
Cpp_Relex_Range is the return result of the cpp_get_relex_range call.

Fields
start_token_index
The index of the first token in the unedited array that needs to be relexed.

end_token_index
The index of the first token in the unedited array after the edited range that may not need to be relexed. Sometimes a relex operation has to lex past this position to find a token that is not effected by the edit.

See Also
cpp_get_relex_range

§5.5.7: Cpp_Lex_Data

struct Cpp_Lex_Data { /* non-public internals */ } ;
Description
Cpp_Lex_Data represents the state of the lexer so that the system may be resumable and the user can manage the lexer state and decide when to resume lexing with it. To create diff --git a/4coder_default_bindings.cpp b/4coder_default_bindings.cpp index 02b988b2..12b57f0d 100644 --- a/4coder_default_bindings.cpp +++ b/4coder_default_bindings.cpp @@ -390,6 +390,7 @@ default_keys(Bind_Helper *context){ bind(context, 'q', MDFR_CTRL, query_replace); bind(context, 'r', MDFR_CTRL, reverse_search); bind(context, 's', MDFR_CTRL, cmdid_save); + bind(context, 'T', MDFR_CTRL, list_all_locations_of_identifier); bind(context, 'u', MDFR_CTRL, to_uppercase); bind(context, 'U', MDFR_CTRL, rewrite_as_single_caps); bind(context, 'v', MDFR_CTRL, paste_and_indent); diff --git a/4coder_default_include.cpp b/4coder_default_include.cpp index 5251e10a..e9f5f1d1 100644 --- a/4coder_default_include.cpp +++ b/4coder_default_include.cpp @@ -677,7 +677,7 @@ static Cpp_Token* get_first_token_at_line(Application_Links *app, Buffer_Summary *buffer, Cpp_Token_Array tokens, int32_t line, int32_t *line_start_out = 0){ int32_t line_start = buffer_get_line_start(app, buffer, line); - Cpp_Get_Token_Result get_token = cpp_get_token(&tokens, line_start); + Cpp_Get_Token_Result get_token = cpp_get_token(tokens, line_start); if (get_token.in_whitespace){ get_token.token_index += 1; @@ -1769,7 +1769,7 @@ buffer_seek_alphanumeric_or_camel_left(Application_Links *app, Buffer_Summary *b static int32_t seek_token_left(Cpp_Token_Array *tokens, int32_t pos){ - Cpp_Get_Token_Result get = cpp_get_token(tokens, pos); + Cpp_Get_Token_Result get = cpp_get_token(*tokens, pos); if (get.token_index == -1){ get.token_index = 0; } @@ -1784,7 +1784,7 @@ seek_token_left(Cpp_Token_Array *tokens, int32_t pos){ static int32_t seek_token_right(Cpp_Token_Array *tokens, int32_t pos){ - Cpp_Get_Token_Result get = cpp_get_token(tokens, pos); + Cpp_Get_Token_Result get = cpp_get_token(*tokens, pos); if (get.in_whitespace){ ++get.token_index; } @@ -2705,22 +2705,24 @@ CUSTOM_COMMAND_SIG(exit_4coder){ #include "4coder_jump_parsing.cpp" static void -generic_search_all_buffers(Application_Links *app, General_Memory *general, Partition *part, - uint32_t match_flags){ - - Query_Bar string; +get_search_all_string(Application_Links *app, Query_Bar *bar){ char string_space[1024]; - string.prompt = make_lit_string("List Locations For: "); - string.string = make_fixed_width_string(string_space); - - if (!query_user_string(app, &string)) return; - if (string.string.size == 0) return; + bar->prompt = make_lit_string("List Locations For: "); + bar->string = make_fixed_width_string(string_space); + if (!query_user_string(app, bar)){ + bar->string.size = 0; + } +} + +static void +generic_search_all_buffers(Application_Links *app, General_Memory *general, Partition *part, + String string, uint32_t match_flags){ Search_Set set = {0}; Search_Iter iter = {0}; - search_iter_init(general, &iter, string.string.size); - copy_ss(&iter.word, string.string); + search_iter_init(general, &iter, string.size); + copy_ss(&iter.word, string); int32_t buffer_count = get_buffer_count(app); search_set_init(general, &set, buffer_count); @@ -2730,7 +2732,7 @@ generic_search_all_buffers(Application_Links *app, General_Memory *general, Part String search_name = make_lit_string("*search*"); Buffer_Summary search_buffer = get_buffer_by_name(app, search_name.str, search_name.size, - AccessAll); + AccessAll); if (!search_buffer.exists){ search_buffer = create_buffer(app, search_name.str, search_name.size, BufferCreate_AlwaysNew); buffer_set_setting(app, &search_buffer, BufferSetting_Unimportant, true); @@ -2799,7 +2801,7 @@ generic_search_all_buffers(Application_Links *app, General_Memory *general, Part if (spare == 0){ buffer_replace_range(app, &search_buffer, - size, size, str, part_size); + size, size, str, part_size); size += part_size; end_temp_memory(temp); @@ -2841,19 +2843,59 @@ generic_search_all_buffers(Application_Links *app, General_Memory *general, Part } CUSTOM_COMMAND_SIG(list_all_locations){ - generic_search_all_buffers(app, &global_general, &global_part, SearchFlag_MatchWholeWord); + Query_Bar bar; + get_search_all_string(app, &bar); + if (bar.string.size == 0) return; + generic_search_all_buffers(app, &global_general, &global_part, + bar.string, SearchFlag_MatchWholeWord); } CUSTOM_COMMAND_SIG(list_all_substring_locations){ - generic_search_all_buffers(app, &global_general, &global_part, SearchFlag_MatchSubstring); + Query_Bar bar; + get_search_all_string(app, &bar); + if (bar.string.size == 0) return; + generic_search_all_buffers(app, &global_general, &global_part, + bar.string, SearchFlag_MatchSubstring); } CUSTOM_COMMAND_SIG(list_all_locations_case_insensitive){ - generic_search_all_buffers(app, &global_general, &global_part, SearchFlag_CaseInsensitive | SearchFlag_MatchWholeWord); + Query_Bar bar; + get_search_all_string(app, &bar); + if (bar.string.size == 0) return; + generic_search_all_buffers(app, &global_general, &global_part, + bar.string, SearchFlag_CaseInsensitive | SearchFlag_MatchWholeWord); } CUSTOM_COMMAND_SIG(list_all_substring_locations_case_insensitive){ - generic_search_all_buffers(app, &global_general, &global_part, SearchFlag_CaseInsensitive | SearchFlag_MatchSubstring); + Query_Bar bar; + get_search_all_string(app, &bar); + if (bar.string.size == 0) return; + generic_search_all_buffers(app, &global_general, &global_part, + bar.string, SearchFlag_CaseInsensitive | SearchFlag_MatchSubstring); +} + +CUSTOM_COMMAND_SIG(list_all_locations_of_identifier){ + View_Summary view = get_active_view(app, AccessProtected); + Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected); + + Cpp_Get_Token_Result get_result = {0}; + bool32 success = buffer_get_token_index(app, &buffer, view.cursor.pos, &get_result); + + if (success && !get_result.in_whitespace){ + char space[128]; + int32_t size = get_result.token_end - get_result.token_start; + + if (size > 0 && size <= sizeof(space)){ + success = buffer_read_range(app, &buffer, get_result.token_start, + get_result.token_end, space); + if (success){ + String str = make_string(space, size); + exec_command(app, change_active_panel); + generic_search_all_buffers(app, &global_general, &global_part, + str, SearchFlag_MatchWholeWord); + } + } + } } struct Word_Complete_State{ diff --git a/4cpp_lexer.h b/4cpp_lexer.h index f5c1d879..27cac35b 100644 --- a/4cpp_lexer.h +++ b/4cpp_lexer.h @@ -151,8 +151,8 @@ static String_And_Flag keywords[] = { FCPP_LINK Cpp_Get_Token_Result -cpp_get_token(Cpp_Token_Array *token_array_in, int32_t pos)/* -DOC_PARAM(token_array, The array of tokens from which to get a token.) +cpp_get_token(Cpp_Token_Array array, int32_t pos)/* +DOC_PARAM(array, The array of tokens from which to get a token.) DOC_PARAM(pos, The position, measured in bytes, to get the token for.) DOC_RETURN(A Cpp_Get_Token_Result struct is returned containing the index of a token and a flag indicating whether the pos is contained in the token @@ -167,10 +167,10 @@ index can be -1 if the position is before the first token.) DOC_SEE(Cpp_Get_Token_Result) */{ Cpp_Get_Token_Result result = {}; - Cpp_Token *token_array = token_array_in->tokens; + Cpp_Token *token_array = array.tokens; Cpp_Token *token = 0; int32_t first = 0; - int32_t count = token_array_in->count; + int32_t count = array.count; int32_t last = count; int32_t this_start = 0, next_start = 0; @@ -217,6 +217,12 @@ DOC_SEE(Cpp_Get_Token_Result) result.in_whitespace = 1; } + if (result.token_index >= 0 && result.token_index < count){ + token = array.tokens + result.token_index; + result.token_start = token->start; + result.token_end = token->start + token->size; + } + return(result); } @@ -1133,13 +1139,13 @@ The start and end points are based on the edited region of the file before the e Cpp_Relex_Range range = {0}; Cpp_Get_Token_Result get_result = {0}; - get_result = cpp_get_token(array, start_pos); + get_result = cpp_get_token(*array, start_pos); range.start_token_index = get_result.token_index-1; if (range.start_token_index < 0){ range.start_token_index = 0; } - get_result = cpp_get_token(array, end_pos); + get_result = cpp_get_token(*array, end_pos); range.end_token_index = get_result.token_index; if (end_pos > array->tokens[range.end_token_index].start){ ++range.end_token_index; diff --git a/4cpp_lexer_types.h b/4cpp_lexer_types.h index e5632174..c307c932 100644 --- a/4cpp_lexer_types.h +++ b/4cpp_lexer_types.h @@ -303,6 +303,14 @@ struct Cpp_Get_Token_Result{ /* DOC(The in_whitespace field is true when the query position was actually in whitespace after the result token.) */ int32_t in_whitespace; + + /* DOC(If the token_index refers to an actual token, this is the start value of the token. + Otherwise this is zero.) */ + int32_t token_start; + + /* DOC(If the token_index refers to an actual token, this is the start+size value of the token. + Otherwise this is zero.) */ + int32_t token_end; }; /* DOC(Cpp_Relex_Range is the return result of the cpp_get_relex_range call.) diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 896f2894..e2082f17 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -865,7 +865,7 @@ DOC_SEE(cpp_get_token) if (file && token_array.tokens && file->state.tokens_complete){ result = 1; Cpp_Get_Token_Result get = {0}; - get = cpp_get_token(&token_array, pos); + get = cpp_get_token(token_array, pos); *get_result = get; } diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index e2ef56a8..1f542999 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -1371,7 +1371,7 @@ file_relex_parallel(System_Functions *system, if (!inline_lex){ Cpp_Token_Array *array = &file->state.token_array; - Cpp_Get_Token_Result get_token_result = cpp_get_token(array, end_i); + Cpp_Get_Token_Result get_token_result = cpp_get_token(*array, end_i); i32 end_token_i = get_token_result.token_index; if (end_token_i < 0){ @@ -4955,8 +4955,6 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target advance_data, (f32)line_height); } - Assert(count > 0); - i32 cursor_begin = 0, cursor_end = 0; u32 cursor_color = 0, at_cursor_color = 0; if (view->file_data.show_temp_highlight){ @@ -4976,7 +4974,7 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target u32 main_color = style->main.default_color; u32 special_color = style->main.special_character_color; if (tokens_use){ - Cpp_Get_Token_Result result = cpp_get_token(&token_array, items->index); + Cpp_Get_Token_Result result = cpp_get_token(token_array, items->index); main_color = *style_get_color(style, token_array.tokens[result.token_index]); token_i = result.token_index + 1; } diff --git a/TODO.txt b/TODO.txt index 15f90bb8..9295bf97 100644 --- a/TODO.txt +++ b/TODO.txt @@ -143,6 +143,7 @@ ; ; [X] eliminate the need for the lexer state's spare array. ; [X] fix buffer render item capacity issue +; [X] tab to complete folder names in the new file dialogue ; Arbitrary wrap positions ; [X] allow for arbitrary wrap positions independent of view width @@ -150,12 +151,13 @@ ; [X] get horizontal scrolling to work in line wrap mode ; [] command for setting wrap positions in views directly ; [] ability to see the wrap position as a number/line and adjust graphically +; [] word level wrapping +; [] code level wrapping ; [] miblo's various number editors ; [] user file bar string ; [] API docs as text file ; [] read only files -; [] tab to complete folder names in the new file dialogue ; [] option to hide hidden files ; [] control over how mouse effects panel focus ; [] option to not open *messages* every startup @@ -164,18 +166,25 @@ ; [] option to break buffer name ties by adding parent directories instead of <#> ; [] undo groups ; [] cursor/scroll groups -; [] word level wrapping ~ temporary measure really want to have totally formatted code presentation ; [] double binding warnings ; ; ; [] the "main_4coder" experiment ; [] real multi-line editing ; [] multi-cursor editing +; [] matching brace/paren/#if#endif highlighting +; [] word repetition highlighting + +; [] simple text based project file +; [] system commands bound to in project file +; [] find matches for current identifier +; [] ability to save and reopen the window state ; [] API docs have duplicate ids? ; [] introduce custom command line arguments ; [] control the file opening/start hook relationship better ; [] get keyboard state on launch +; [] never launch two 4coders unless special -R flag is used ; buffer behavior cleanup ; [X] show all characters as \# if they can't be rendered @@ -219,8 +228,8 @@ ; control schemes ; [] emacs style sub-maps ; [] vim style modes +; [] sublime style editing ; [] "tap typing" -; [] "thin cursor" ; [] command meta data ; [] macros ; @@ -228,7 +237,7 @@ ; code engine ; [X] lexer with multiple chunk input ; [X] more correct auto-indentation -; [] switch over to gap buffer +; [X] switch over to gap buffer ; [] preprocessor ; [] AST generator ; @@ -252,7 +261,6 @@ ; ; [] tutorials ; [] 4edT thing -; [] unicode/UTF support ; [] console emulator ; @@ -275,13 +283,11 @@ ; HARD BUGS ; [X] reduce cpu consumption ; [X] repainting too slow for resize looks really dumb -; [] fyoucon's segfaults with malloc on win10 +; [X] fill screen right away +; [X] minimize and reopen problem (fixed by microsoft patch aparently) ; [] handling cursor in non-client part of window so it doesn't spaz -; [] fill screen right away -; [] history breaks when heavily used? (disk swaping?) ; ; [] a triangle rendered for a few frames? color of the dirty markers (not reproduced by me yet) -; [] minimize and reopen problem (not reproduced by me yet) ; ;