From 8915bcceba075082f7396d7887138787d2a837ab Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Thu, 22 Oct 2020 14:57:28 -0700 Subject: [PATCH] [variables] added new 4coder variables system --- custom/4coder_casey_index.cpp | 708 ---------------------------- custom/4coder_casey_index.h | 100 ---- custom/4coder_default_framework.cpp | 4 +- custom/4coder_default_framework.h | 14 + custom/4coder_default_hooks.cpp | 30 +- custom/4coder_default_include.cpp | 2 + custom/4coder_variables.cpp | 237 ++++++++++ custom/4coder_variables.h | 51 ++ custom/generated/command_metadata.h | 2 +- ship_files/changes.txt | 7 + 10 files changed, 339 insertions(+), 816 deletions(-) delete mode 100644 custom/4coder_casey_index.cpp delete mode 100644 custom/4coder_casey_index.h create mode 100644 custom/4coder_variables.cpp create mode 100644 custom/4coder_variables.h diff --git a/custom/4coder_casey_index.cpp b/custom/4coder_casey_index.cpp deleted file mode 100644 index d4d333d3..00000000 --- a/custom/4coder_casey_index.cpp +++ /dev/null @@ -1,708 +0,0 @@ -static Content_Index *global_content_index = 0; - -internal String get_name_of_index_type(Indexed_Content_Element_Type content_type) -{ - String result = {}; - - switch(content_type) - { - case ContentType_Unspecified: {result = make_lit_string("Unspecified");} break; - - case ContentType_Function: {result = make_lit_string("Function");} break; - case ContentType_Type: {result = make_lit_string("Type");} break; - case ContentType_Macro: {result = make_lit_string("Macro");} break; - case ContentType_EnumValue: {result = make_lit_string("Enum Value");} break; - case ContentType_ForwardDeclaration: {result = make_lit_string("Forward Declaration");} break; - - case ContentType_TODO: {result = make_lit_string("TODO");} break; - case ContentType_NOTE: {result = make_lit_string("Note");} break; - case ContentType_IMPORTANT: {result = make_lit_string("Important");} break; - case ContentType_STUDY: {result = make_lit_string("Study");} break; - } - - return(result); -} - -static Content_Index * -create_content_index(Application_Links *app) -{ - // TODO(casey): I really just want this to be its own allocating arena, but I can't find anything like that in 4coder? - // All arenas seem to be fixed size and they can't get more memory if they run out :( - Content_Index *index = (Content_Index *)malloc(sizeof(Content_Index)); - - memset(index, 0, sizeof(*index)); - - return(index); -} - -static Indexed_Content_Element ** -get_element_slot_for_name(Content_Index *index, String name) -{ - Indexed_Content_Element **slot = &index->name_hash[table_hash_u8((uint8_t *)name.str, name.size) % ArrayCount(index->name_hash)]; - return(slot); -} - -static Indexed_Buffer * -get_or_create_indexed_buffer(Content_Index *index, Buffer_ID buffer_id) -{ - Indexed_Buffer *result = 0; - - Indexed_Buffer **slot = &index->buffer_hash[buffer_id % ArrayCount(index->buffer_hash)]; - for(Indexed_Buffer *search = *slot; - search; - search = search->next_in_hash) - { - if(search->buffer_id == buffer_id) - { - result = search; - break; - } - } - - if(!result) - { - result = (Indexed_Buffer *)malloc(sizeof(Indexed_Buffer)); - result->buffer_id = buffer_id; - result->first_tag = 0; - result->next_in_hash = *slot; - *slot = result; - } - - return(result); -} - -static color_pair -get_color_pair_for(Indexed_Content_Element_Type type) -{ - color_pair result = {}; - - switch(type) - { - case ContentType_Function: - { - result.fore = CC_Function; - } break; - - case ContentType_Type: - { - result.fore = CC_Type; - } break; - - case ContentType_Macro: - { - result.fore = CC_Macro; - } break; - - case ContentType_EnumValue: - { - result.fore = CC_EnumValue; - } break; - - case ContentType_ForwardDeclaration: - { - result.fore = CC_ForwardDeclaration; - } break; - - case ContentType_TODO: - { - result.fore = CC_TODO; - } break; - - case ContentType_NOTE: - { - result.fore = CC_NOTE; - } break; - - case ContentType_IMPORTANT: - { - result.fore = CC_IMPORTANT; - } break; - - case ContentType_STUDY: - { - result.fore = CC_STUDY; - } break; - } - - return(result); -} - -static Indexed_Content_Element * -begin_element_in_index(Content_Index *index, Indexed_Content_Element_Type type, Buffer_ID buffer_id, int32_t location, - int32_t name_size, int32_t content_size) -{ - Indexed_Content_Element *elem = 0; - - // TODO(casey): I really just want this to be its own allocating arena, but I can't find anything like that in 4coder? - // All arenas seem to be fixed size and they can't get more memory if they run out :( - uint8_t *mem = (uint8_t *)malloc(sizeof(Indexed_Content_Element) + name_size + content_size); - if(mem) - { - elem = (Indexed_Content_Element *)mem; - - elem->next_in_hash = 0; - elem->type = type; - elem->name.memory_size = elem->name.size = name_size; - elem->name.str = (char *)(elem + 1); - elem->content.memory_size = elem->content.size = content_size; - elem->content.str = elem->name.str + name_size; - - elem->color = get_color_pair_for(type); - - elem->buffer_id = buffer_id; - elem->last_known_location = location; - - index->total_string_space += name_size + content_size; - ++index->element_count; - } - - return(elem); -} - -static void -end_element_in_index(Content_Index *index, Indexed_Content_Element *elem, u32 flags) -{ - if(elem) - { - // NOTE(casey): By convention, we make content into a single line, and remove leading/trailing whitespace - condense_whitespace(&elem->name); - condense_whitespace(&elem->content); - - Indexed_Content_Element **slot = &index->unhashed; - if(!(flags & IndexFlag_NoNameLookup)) - { - slot = get_element_slot_for_name(index, elem->name); - } - elem->next_in_hash = *slot; - *slot = elem; - - Indexed_Buffer *buffer = get_or_create_indexed_buffer(index, elem->buffer_id); - ++buffer->element_type_counts[elem->type]; - ++index->element_type_counts[elem->type]; - } -} - -static Indexed_Content_Element * -add_element_to_index(Application_Links *app, Content_Index *index, Indexed_Content_Element_Type type, Buffer_Summary *buffer, int32_t location, - int32_t name_start, int32_t name_end, - int32_t content_start, int32_t content_end, - u32 flags = 0) -{ - Indexed_Content_Element *elem = 0; - if((name_start <= name_end) && - (content_start <= content_end)) - { - elem = begin_element_in_index(index, type, buffer->buffer_id, location, name_end - name_start, content_end - content_start); - if(elem) - { - buffer_read_range(app, buffer, name_start, name_end, elem->name.str); - buffer_read_range(app, buffer, content_start, content_end, elem->content.str); - end_element_in_index(index, elem, flags); - } - } - - return(elem); -} - -static Indexed_Content_Element * -add_element_to_index(Content_Index *index, Indexed_Content_Element_Type type, Buffer_ID buffer_id, int32_t location, String name, String content, - u32 flags = 0) -{ - Indexed_Content_Element *elem = begin_element_in_index(index, type, buffer_id, location, name.size, content.size); - if(elem) - { - copy_ss(&elem->name, name); - copy_ss(&elem->content, content); - end_element_in_index(index, elem, flags); - } - - return(elem); -} - -static Indexed_Content_Tag * -add_tag_to_index(Content_Index *index, Buffer_Summary *buffer, uint32_t type, int32_t start, int32_t end, String content) -{ - Indexed_Content_Tag *tag = 0; - - if(start <= end) - { - Indexed_Buffer *index_buffer = get_or_create_indexed_buffer(index, buffer->buffer_id); - // TODO(casey): I really just want this to be its own allocating arena, but I can't find anything like that in 4coder? - // All arenas seem to be fixed size and they can't get more memory if they run out :( - uint8_t *mem = (uint8_t *)malloc(sizeof(Indexed_Content_Tag) + content.size); - if(mem) - { - tag = (Indexed_Content_Tag *)mem; - tag->content.size = tag->content.memory_size = content.size; - tag->content.str = (char *)(tag + 1); - copy_ss(&tag->content, content); - tag->type = type; - tag->start = start; - tag->end = end; - tag->next_in_buffer = index_buffer->first_tag; - index_buffer->first_tag = tag; - } - } - - return(tag); -} - -static Indexed_Content_Element * -get_element_by_name(Content_Index *index, String name) -{ - Indexed_Content_Element *result = 0; - - if(index) - { - for(Indexed_Content_Element *elem = *get_element_slot_for_name(index, name); - elem; - elem = elem->next_in_hash) - { - if(compare_ss(elem->name, name) == 0) - { - result = elem; - break; - } - } - } - - return(result); -} - -static void -remove_buffer_from_index(Application_Links *app, Content_Index *index, Buffer_ID buffer_id) -{ - for(int hash_index = 0; - hash_index <= ArrayCount(index->name_hash); - ++hash_index) - { - for(Indexed_Content_Element **elem_ptr = &index->name_hash[hash_index]; - *elem_ptr; - ) - { - Indexed_Content_Element *elem = *elem_ptr; - if(elem->buffer_id == buffer_id) - { - *elem_ptr = elem->next_in_hash; - free(elem); - } - else - { - elem_ptr = &elem->next_in_hash; - } - } - } - - Indexed_Buffer *index_buffer = get_or_create_indexed_buffer(index, buffer_id); - while(index_buffer->first_tag) - { - Indexed_Content_Tag *tag = index_buffer->first_tag; - index_buffer->first_tag = tag->next_in_buffer; - free(tag); - } - - for(u32 type_index = 0; - type_index < ContentType_Count; - ++type_index) - { - index->element_type_counts[type_index] -= index_buffer->element_type_counts[type_index]; - index_buffer->element_type_counts[type_index] = 0; - } -} - -static void -add_buffer_to_index(Application_Links *app, Content_Index *index, Buffer_Summary *buffer) -{ - ++index->buffer_count; - - Token_Iterator iter = iterate_tokens(app, buffer, 0); - - int32_t paren_level = 0; - int32_t brace_level = 0; - - while(iter.valid) - { - Cpp_Token token = get_next_token(app, &iter); - - if(token.flags & CPP_TFLAG_PP_BODY) - { - // TODO(casey): Do we need to pick up macros here? - } - else - { - switch(token.type) - { - case CPP_TOKEN_COMMENT: - { - // NOTE(casey): Comments can contain special operations that we want to perform, so we thunk to a special parser to handle those - parse_comment(app, index, buffer, token); - } break; - - case CPP_PP_DEFINE: - { - int32_t content_start = token.start; - token = get_next_token(app, &iter); - - // TODO(casey): Allen, how do I scan for the next "not continued newline"? - int32_t content_end = token.start + token.size; - - add_element_to_index(app, index, ContentType_Macro, buffer, token.start, - token.start, token.start + token.size, - content_start, content_end); - } break; - - case CPP_TOKEN_KEY_TYPE_DECLARATION: - { - bool32 forward_declaration = true; - int32_t content_start = token.start; - Cpp_Token element_name = {}; - Cpp_Token last_identifier = {}; - - String typedef_keyword = make_lit_string("typedef"); - if(token_text_is(app, buffer, token, typedef_keyword)) - { - // NOTE(casey): Typedefs can't be "forward declared", so we always record their location. - forward_declaration = false; - - // NOTE(casey): This is a simple "usually works" parser for typedefs. It is well-known that C grammar - // doesn't actually allow you to parse typedefs properly without actually knowing the declared types - // at the time, which of course we cannot do since we parse per-file, and don't even know things we - // would need (like -D switches, etc.) - - // TODO(casey): If eventually this were upgraded to a more thoughtful parser, struct/union/enum defs - // would be parsed from brace to brace, so they could be handled recursively inside of a typedef for - // the pattern "typedef struct {} foo;", which currently we do not handle (we ignore the foo). - int typedef_paren_level = 0; - while(iter.valid) - { - token = get_next_token(app, &iter); - if(token.type == CPP_TOKEN_IDENTIFIER) - { - last_identifier = token; - } - else if(token.type == CPP_TOKEN_PARENTHESE_OPEN) - { - if(typedef_paren_level == 0) - { - // NOTE(casey): If we are going back into a parenthetical, it means that whatever the last - // identifier we saw is our best candidate. - element_name = last_identifier; - } - ++typedef_paren_level; - } - else if(token.type == CPP_TOKEN_PARENTHESE_CLOSE) - { - --typedef_paren_level; - } - else if(token.type == CPP_TOKEN_KEY_TYPE_DECLARATION) - { - // TODO(casey): If we _really_ wanted to, we could parse the type here recursively, - // and then we could capture things that were named differently a la "typedef struct foo {...} bar;" - // but I think that should wait until the 4coder parser is more structural, because I don't - // know how much parsing we _really_ want to do here. - forward_declaration = true; - break; - } - else if(token.type == CPP_TOKEN_SEMICOLON) - { - break; - } - } - - if(element_name.size == 0) - { - element_name = last_identifier; - } - } - - if(!element_name.size) - { - while(iter.valid) - { - token = peek_token(app, &iter); - if(token.type == CPP_TOKEN_IDENTIFIER) - { - element_name = token; - get_next_token(app, &iter); - } - else if((token.type == CPP_TOKEN_KEY_MODIFIER) || - (token.type == CPP_TOKEN_KEY_QUALIFIER) || - (token.type == CPP_TOKEN_KEY_ACCESS) || - (token.type == CPP_TOKEN_KEY_LINKAGE)) - { - // NOTE(casey): Let it go. - get_next_token(app, &iter); - } - else if(token.type == CPP_TOKEN_BRACE_OPEN) - { - // NOTE(casey): It's probably type definition - forward_declaration = false; - break; - } - else - { - // NOTE(casey): It's probably a forward declaration - break; - } - } - } - - int32_t content_end = token.start; - - if(element_name.size) - { - Indexed_Content_Element_Type type = ContentType_Type; - if(forward_declaration) - { - type = ContentType_ForwardDeclaration; - } - - add_element_to_index(app, index, type, buffer, element_name.start, - element_name.start, element_name.start + element_name.size, - content_start, content_end); - } - } break; - - case CPP_TOKEN_PARENTHESE_OPEN: - { - ++paren_level; - } break; - - case CPP_TOKEN_PARENTHESE_CLOSE: - { - --paren_level; - } break; - - case CPP_TOKEN_BRACE_OPEN: - { - if((paren_level == 0) && - (brace_level == 0)) - { - // NOTE(casey): This is presumably a function, see if we can find it's name. - int32_t content_end = token.start; - int32_t content_start = content_end; - int32_t name_start = 0; - int32_t name_end = 0; - - Token_Iterator back = iter; - get_prev_token(app, &back); - get_prev_token(app, &back); - Cpp_Token comment_pass = get_prev_token(app, &back); - while(comment_pass.type == CPP_TOKEN_COMMENT) - { - comment_pass = get_prev_token(app, &back); - } - if(comment_pass.type == CPP_TOKEN_PARENTHESE_CLOSE) - { - paren_level = -1; - while(back.valid) - { - if(token.type != CPP_TOKEN_COMMENT) - { - content_start = token.start; - } - token = get_prev_token(app, &back); - if((paren_level == 0) && - (brace_level == 0) && - ((token.flags & CPP_TFLAG_PP_BODY) || - (token.type == CPP_TOKEN_BRACE_CLOSE) || - (token.type == CPP_TOKEN_SEMICOLON) || - (token.type == CPP_TOKEN_EOF))) - { - break; - } - else - { - switch(token.type) - { - case CPP_TOKEN_PARENTHESE_OPEN: - { - ++paren_level; - } break; - - case CPP_TOKEN_PARENTHESE_CLOSE: - { - --paren_level; - } break; - - case CPP_TOKEN_BRACE_OPEN: - { - ++brace_level; - } break; - - case CPP_TOKEN_BRACE_CLOSE: - { - --brace_level; - } break; - - case CPP_TOKEN_IDENTIFIER: - { - if((paren_level == 0) && - (brace_level == 0) && - (name_start == 0)) - { - name_start = token.start; - name_end = token.start + token.size; - Token_Iterator probe = back; - get_next_token(app, &probe); - for(;;) - { - Cpp_Token test = get_next_token(app, &probe); - if((test.type == 0) || - (test.type == CPP_TOKEN_EOF) || - (test.type == CPP_TOKEN_PARENTHESE_CLOSE) || - (test.type == CPP_TOKEN_PARENTHESE_OPEN)) - { - name_end = test.start; - break; - } - } - } - } break; - } - } - } - - if(name_start < name_end) - { - Indexed_Content_Element_Type type = ContentType_Function; - add_element_to_index(app, index, type, buffer, name_start, - name_start, name_end, - content_start, content_end); - } - - brace_level = 0; - paren_level = 0; - } - } - - ++brace_level; - } break; - - case CPP_TOKEN_BRACE_CLOSE: - { - --brace_level; - } break; - } - } - } -} - -static void -add_all_buffers_to_index(Application_Links *app, Content_Index *index) -{ - for(Buffer_Summary buffer = get_buffer_first(app, AccessAll); - buffer.exists; - get_buffer_next(app, &buffer, AccessAll)) - { - int32_t Unimportant = true; - buffer_get_setting(app, &buffer, BufferSetting_Unimportant, &Unimportant); - - if(buffer.tokens_are_ready && !Unimportant) - { - add_buffer_to_index(app, index, &buffer); - } - } -} - -static void -update_index_for_buffer(Application_Links *app, Content_Index *index, Buffer_Summary *buffer) -{ - remove_buffer_from_index(app, index, buffer->buffer_id); - add_buffer_to_index(app, index, buffer); -} - -static Content_Index * -get_global_content_index(Application_Links *app) -{ - Content_Index *result = global_content_index; - if(!result) - { - global_content_index = create_content_index(app); - add_all_buffers_to_index(app, global_content_index); - result = global_content_index; - } - - return(result); -} - -static void -jump_to_element(Application_Links *app, View_Summary *view, Indexed_Content_Element *elem) -{ - if (view->buffer_id != elem->buffer_id) - { - view_set_buffer(app, view, elem->buffer_id, 0); - } - Buffer_Seek seek; - seek.type = buffer_seek_pos; - seek.pos = elem->last_known_location;; - view_set_cursor(app, view, seek, true); -} - -static void -jump_to_element_activate(Application_Links *app, Partition *scratch, Heap *heap, - View_Summary *view, Lister_State *state, - String text_field, void *user_data, bool32 activated_by_mouse) -{ - lister_default(app, scratch, heap, view, state, ListerActivation_Finished); - if(user_data) - { - jump_to_element(app, view, (Indexed_Content_Element *)user_data); - } -} - -typedef bool32 element_type_predicate(Application_Links *app, Content_Index *index, Indexed_Content_Element *elem, void *user_data); - -static bool32 -element_is_definition(Application_Links *app, Content_Index *index, Indexed_Content_Element *elem, void *user_data) -{ - bool32 result = ((elem->type == ContentType_Function) || - (elem->type == ContentType_Type) || - (elem->type == ContentType_Macro) || - (elem->type == ContentType_EnumValue)); - return(result); -} - -static bool32 -element_type_equals(Application_Links *app, Content_Index *index, Indexed_Content_Element *elem, void *user_data) -{ - bool32 result = (elem->type == (uint64_t)user_data); - return(result); -} - -static void -jump_to_element_lister(Application_Links *app, char *Label, element_type_predicate *predicate, void *user_data = 0) -{ - Partition *arena = &global_part; - - View_Summary view = get_active_view(app, AccessAll); - view_end_ui_mode(app, &view); - Temp_Memory temp = begin_temp_memory(arena); - - Content_Index *index = get_global_content_index(app); - - Lister_Option *options = push_array(arena, Lister_Option, index->element_count); - int32_t option_index = 0; - for(int hash_index = 0; - hash_index <= ArrayCount(index->name_hash); - ++hash_index) - { - for(Indexed_Content_Element *elem = index->name_hash[hash_index]; - elem; - elem = elem->next_in_hash) - { - if(predicate(app, index, elem, user_data)) - { - options[option_index].text_color = get_color(elem->color.fore); - options[option_index].pop_color = get_color(CC_DefaultText); - options[option_index].back_color = get_color(elem->color.back); - options[option_index].string = elem->name; - options[option_index].status = elem->content; - options[option_index].user_data = elem; - ++option_index; - } - } - } - begin_integrated_lister__basic_list(app, Label, jump_to_element_activate, 0, 0, options, option_index, index->total_string_space, &view); - end_temp_memory(temp); -} diff --git a/custom/4coder_casey_index.h b/custom/4coder_casey_index.h deleted file mode 100644 index 0ca1c552..00000000 --- a/custom/4coder_casey_index.h +++ /dev/null @@ -1,100 +0,0 @@ -/* date = October 18th 2020 3:41 pm */ - -#ifndef FCODER_CASEY_INDEX_H -#define FCODER_CASEY_INDEX_H - -struct color_pair -{ - casey_color_id fore; - casey_color_id back; -}; - -enum Indexed_Content_Element_Type -{ - ContentType_Unspecified, - - ContentType_Function, - ContentType_Type, - ContentType_Macro, - ContentType_EnumValue, - ContentType_ForwardDeclaration, - - ContentType_TODO, - ContentType_NOTE, - ContentType_IMPORTANT, - ContentType_STUDY, - - ContentType_Count, -}; - -struct Indexed_Content_Element -{ - Indexed_Content_Element *next_in_hash; - uint32_t type; - - String name; - String content; - - color_pair color; - - Buffer_ID buffer_id; - int32_t last_known_location; -}; - -enum Indexed_Content_Flag -{ - IndexFlag_NoNameLookup = 0x1, -}; - -enum Indexed_Content_Tag_Type -{ - TagType_Unspecified , - - TagType_Label, - TagType_Scope, - TagType_Highlight, -}; -struct Indexed_Content_Tag -{ - Indexed_Content_Tag *next_in_buffer; - String content; - - uint32_t type; - int32_t start; - int32_t end; - - color_pair color; -}; - -struct Indexed_Buffer -{ - Indexed_Buffer *next_in_hash; - Buffer_ID buffer_id; - - int32_t element_type_counts[ContentType_Count]; - - // TODO(casey): I really want a growable arena here, so I don't have to manage this memory. Everything - // gets cleared by buffer. - - // TODO(casey): This should be a spatial query so it is more scalable - Indexed_Content_Tag *first_tag; -}; - -struct Content_Index -{ - int32_t buffer_count; - int32_t element_count; - int32_t total_string_space; - - int32_t element_type_counts[ContentType_Count]; - - Indexed_Buffer *buffer_hash[257]; - - // NOTE(casey): unhashed _must_ come immediately aftter name_hash, as they are treated as contiguous - // { - Indexed_Content_Element *name_hash[4099]; - Indexed_Content_Element *unhashed; - // } -}; - -#endif //4CODER_CASEY_INDEX_H diff --git a/custom/4coder_default_framework.cpp b/custom/4coder_default_framework.cpp index 400815ee..91cba6be 100644 --- a/custom/4coder_default_framework.cpp +++ b/custom/4coder_default_framework.cpp @@ -1013,7 +1013,9 @@ function void set_next_rewrite(Application_Links *app, View_ID view, Rewrite_Type rewrite){ Managed_Scope scope = view_get_managed_scope(app, view); Rewrite_Type *next_rewrite = scope_attachment(app, scope, view_next_rewrite_loc, Rewrite_Type); - *next_rewrite = rewrite; + if (next_rewrite != 0){ + *next_rewrite = rewrite; + } } function void diff --git a/custom/4coder_default_framework.h b/custom/4coder_default_framework.h index 7b3095d7..4853b34c 100644 --- a/custom/4coder_default_framework.h +++ b/custom/4coder_default_framework.h @@ -133,5 +133,19 @@ struct Fade_Range_List{ #endif +//////////////////////////////// + +struct Implicit_Map_Result{ + String_ID map; + Custom_Command_Function *command; +}; + +typedef Implicit_Map_Result Implicit_Map_Function(Application_Links *app, + String_ID buffer_language, + String_ID global_mode, + Input_Event *event); + +global Implicit_Map_Function *implicit_map_function = 0; + // BOTTOM diff --git a/custom/4coder_default_hooks.cpp b/custom/4coder_default_hooks.cpp index eb87c507..dbdebc2e 100644 --- a/custom/4coder_default_hooks.cpp +++ b/custom/4coder_default_hooks.cpp @@ -48,6 +48,22 @@ CUSTOM_DOC("Default command for responding to a try-exit event") } } +function Implicit_Map_Result +default_implicit_map(Application_Links *app, String_ID lang, String_ID mode, Input_Event *event){ + Implicit_Map_Result result = {}; + + View_ID view = get_this_ctx_view(app, Access_Always); + + Command_Map_ID map_id = default_get_map_id(app, view); + Command_Binding binding = map_get_binding_recursive(&framework_mapping, map_id, event); + + // TODO(allen): map_id <-> map name? + result.map = 0; + result.command = binding.custom; + + return(result); +} + CUSTOM_COMMAND_SIG(default_view_input_handler) CUSTOM_DOC("Input consumption loop for default view behavior") { @@ -72,12 +88,12 @@ CUSTOM_DOC("Input consumption loop for default view behavior") continue; } - // NOTE(allen): Get map_id - Command_Map_ID map_id = default_get_map_id(app, view); - // NOTE(allen): Get binding - Command_Binding binding = map_get_binding_recursive(&framework_mapping, map_id, &input.event); - if (binding.custom == 0){ + if (implicit_map_function == 0){ + implicit_map_function = default_implicit_map; + } + Implicit_Map_Result map_result = implicit_map_function(app, 0, 0, &input.event); + if (map_result.command == 0){ leave_current_input_unhandled(app); continue; } @@ -85,7 +101,7 @@ CUSTOM_DOC("Input consumption loop for default view behavior") // NOTE(allen): Run the command and pre/post command stuff default_pre_command(app, scope); ProfileCloseNow(view_input_profile); - binding.custom(app); + map_result.command(app); ProfileScope(app, "after view input"); default_post_command(app, scope); } @@ -250,6 +266,7 @@ default_render_buffer(Application_Links *app, View_ID view_id, Face_ID face_id, &token_array, pairs, ArrayCount(pairs)); } +#if 0 // TODO(allen): Put in 4coder_draw.cpp // NOTE(allen): Color functions @@ -268,6 +285,7 @@ default_render_buffer(Application_Links *app, View_ID view_id, Face_ID face_id, paint_text_color(app, text_layout_id, Ii64_size(token->pos, token->size), argb); } } +#endif } else{ paint_text_color_fcolor(app, text_layout_id, visible_range, fcolor_id(defcolor_text_default)); diff --git a/custom/4coder_default_include.cpp b/custom/4coder_default_include.cpp index 00df60a3..bb8d0400 100644 --- a/custom/4coder_default_include.cpp +++ b/custom/4coder_default_include.cpp @@ -27,6 +27,7 @@ #include "generated/command_metadata.h" #endif +#include "4coder_variables.h" #include "4coder_profile.h" #include "4coder_async_tasks.h" #include "4coder_token.h" @@ -126,6 +127,7 @@ #include "4coder_doc_content_types.cpp" #include "4coder_doc_commands.cpp" #include "4coder_docs.cpp" +#include "4coder_variables.cpp" #include "4coder_examples.cpp" diff --git a/custom/4coder_variables.cpp b/custom/4coder_variables.cpp new file mode 100644 index 00000000..6547e559 --- /dev/null +++ b/custom/4coder_variables.cpp @@ -0,0 +1,237 @@ +/* +4coder_variables.cpp - Variables system +*/ + +// TOP + +//////////////////////////////// +// NOTE(allen): String hashing + +global Arena vars_arena = {}; +global Table_Data_u64 vars_string_to_id = {}; +global Table_u64_Data vars_id_to_string = {}; +global String_ID vars_string_id_counter = 0; + +function void +_vars_init(void){ + local_persist b32 did_init = false; + if (!did_init) + { + did_init = true; + Base_Allocator *base = get_base_allocator_system(); + vars_arena = make_arena(base); + vars_string_to_id = make_table_Data_u64(base, 100); + vars_id_to_string = make_table_u64_Data(base, 100); + } +} + +function String_ID +vars_save_string(String_Const_u8 string){ + _vars_init(); + + String_ID result = 0; + Data string_data = make_data(string.str, string.size); + Table_Lookup location = table_lookup(&vars_string_to_id, string_data); + if (location.found_match){ + table_read(&vars_string_to_id, location, &result); + } + else{ + vars_string_id_counter += 1; + result = vars_string_id_counter; + string_data = push_data_copy(&vars_arena, string_data); + table_insert(&vars_string_to_id, string_data, result); + table_insert(&vars_id_to_string, result, string_data); + } + return(result); +} + +function String_Const_u8 +vars_read_string(Arena *arena, String_ID id){ + _vars_init(); + + String_Const_u8 result = {}; + Table_Lookup location = table_lookup(&vars_id_to_string, id); + if (location.found_match){ + Data data = {}; + table_read(&vars_id_to_string, location, &data); + result.str = push_array(arena, u8 , data.size); + block_copy(result.str, data.data, data.size); + result.size = data.size; + } + return(result); +} + +//////////////////////////////// +// NOTE(allen): Variable structure + +global Variable vars_global_root = {}; +global Variable vars_nil = {}; +global Variable *vars_free_variables = 0; + +function Variable_Handle +vars_get_root(void){ + Variable_Handle handle = {&vars_global_root}; + return(handle); +} + +function Variable_Handle +vars_get_nil(void){ + Variable_Handle handle = {&vars_nil}; + return(handle); +} + +function b32 +vars_is_nil(Variable_Handle var){ + return(var.ptr == &vars_nil); +} + +function b32 +vars_match(Variable_Handle a, Variable_Handle b){ + return(a.ptr == b.ptr); +} + + +function String_ID +vars_string_id_from_var(Variable_Handle var){ + return(var.ptr->string); +} + +function String_Const_u8 +vars_string_from_var(Arena *arena, Variable_Handle var){ + String_ID id = vars_string_id_from_var(var); + String_Const_u8 result = vars_read_string(arena, id); + return(result); +} + +function Variable_Handle +vars_read_key(Variable_Handle var, String_ID key){ + Variable_Handle result = vars_get_nil(); + for (Variable *node = var.ptr->first; + node != 0; + node = node->next){ + if (node->key == key){ + result.ptr = node; + break; + } + } + return(result); +} + +function Variable_Handle +vars_read_key(Variable_Handle var, String_Const_u8 key){ + String_ID id = vars_save_string(key); + Variable_Handle result = vars_read_key(var, id); + return(result); +} + +function void +vars_set_string(Variable_Handle var, String_ID string){ + if (var.ptr != &vars_nil){ + var.ptr->string = string; + } +} + +function void +vars_set_string(Variable_Handle var, String_Const_u8 string){ + String_ID id = vars_save_string(string); + vars_set_string(var, id); +} + +function void +_vars_free_variable_children(Variable *var){ + for (Variable *node = var->first; + node != 0; + node = node->next){ + _vars_free_variable_children(node); + } + + if (var->last != 0){ + var->last->next = vars_free_variables; + } + if (var->first != 0){ + vars_free_variables = var->first; + } +} + +function void +vars_erase(Variable_Handle var, String_ID key){ + if (var.ptr != &vars_nil){ + Variable *prev = 0; + Variable *node = var.ptr->first; + for (; node != 0; + node = node->next){ + if (node->key == key){ + break; + } + prev = node; + } + + if (node != 0){ + _vars_free_variable_children(node); + if (prev != 0){ + prev->next = node->next; + } + if (var.ptr->first == node){ + var.ptr->first = node->next; + } + if (var.ptr->last == node){ + var.ptr->last = prev; + } + sll_stack_push(vars_free_variables, node); + } + } +} + +function Variable_Handle +vars_new_variable(Variable_Handle var, String_ID key){ + Variable_Handle handle = vars_get_nil(); + if (var.ptr != &vars_nil){ + Variable *prev = 0; + Variable *node = var.ptr->first; + for (; node != 0; + node = node->next){ + if (node->key == key){ + break; + } + prev = node; + } + + if (node != 0){ + handle.ptr = node; + _vars_free_variable_children(node); + } + else{ + handle.ptr = vars_free_variables; + if (handle.ptr == 0){ + sll_stack_pop(vars_free_variables); + } + else{ + handle.ptr = push_array(&vars_arena, Variable, 1); + } + sll_queue_push(var.ptr->first, var.ptr->last, handle.ptr); + handle.ptr->key = key; + } + + handle.ptr->string = 0; + handle.ptr->first = 0; + handle.ptr->last = 0; + } + return(handle); +} + +function Variable_Handle +vars_new_variable(Variable_Handle var, String_ID key, String_ID string){ + Variable_Handle result = vars_new_variable(var, key); + vars_set_string(var, string); + return(result); +} + +function void +vars_clear_keys(Variable_Handle var){ + if (var.ptr != &vars_nil){ + _vars_free_variable_children(var.ptr); + } +} + +// BOTTOM + diff --git a/custom/4coder_variables.h b/custom/4coder_variables.h new file mode 100644 index 00000000..2f2825dd --- /dev/null +++ b/custom/4coder_variables.h @@ -0,0 +1,51 @@ +/* +4coder_variables.h - Variables system +*/ + +// TOP + +#if !defined(FCODER_VARIABLES_H) +#define FCODER_VARIABLES_H + +//////////////////////////////// +// NOTE(allen): Types + +typedef u64 String_ID; + +struct Variable{ + Variable *next; + String_ID key; + String_ID string; + Variable *first; + Variable *last; +}; + +struct Variable_Handle{ + Variable *ptr; +}; + +//////////////////////////////// +// NOTE(allen): Functions + +function String_ID vars_save_string(String_Const_u8 string); +#define vars_save_string_lit(S) vars_save_string(string_u8_litexpr(S)) +function String_Const_u8 vars_read_string(Arena *arena, String_ID id); + +function Variable_Handle vars_get_root(void); +function Variable_Handle vars_get_nil(void); +function b32 vars_is_nil(Variable_Handle var); +function b32 vars_match(Variable_Handle a, Variable_Handle b); + +function Variable_Handle vars_read_key(Variable_Handle var, String_ID key); +function String_ID vars_string_id_from_var(Variable_Handle var); +function String_Const_u8 vars_string_from_var(Arena *arena, Variable_Handle var); + +function void vars_set_string(Variable_Handle var, String_ID string); +function void vars_erase(Variable_Handle var, String_ID key); +function Variable_Handle vars_new_variable(Variable_Handle var, String_ID key); +function Variable_Handle vars_new_variable(Variable_Handle var, String_ID key, String_ID string); +function void vars_clear_keys(Variable_Handle var); + +#endif //4CODER_VARIABLES_H + +// BOTTOM diff --git a/custom/generated/command_metadata.h b/custom/generated/command_metadata.h index a70a6b70..067070d0 100644 --- a/custom/generated/command_metadata.h +++ b/custom/generated/command_metadata.h @@ -308,7 +308,7 @@ static Command_Metadata fcoder_metacmd_table[248] = { { PROC_LINKS(default_file_externally_modified, 0), false, "default_file_externally_modified", 32, "Notes the external modification of attached files by printing a message.", 72, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2055 }, { PROC_LINKS(default_startup, 0), false, "default_startup", 15, "Default command for responding to a startup event", 49, "W:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 7 }, { PROC_LINKS(default_try_exit, 0), false, "default_try_exit", 16, "Default command for responding to a try-exit event", 50, "W:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 23 }, -{ PROC_LINKS(default_view_input_handler, 0), false, "default_view_input_handler", 26, "Input consumption loop for default view behavior", 48, "W:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 51 }, +{ PROC_LINKS(default_view_input_handler, 0), false, "default_view_input_handler", 26, "Input consumption loop for default view behavior", 48, "W:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 67 }, { PROC_LINKS(delete_alpha_numeric_boundary, 0), false, "delete_alpha_numeric_boundary", 29, "Delete characters between the cursor position and the first alphanumeric boundary to the right.", 95, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 161 }, { PROC_LINKS(delete_char, 0), false, "delete_char", 11, "Deletes the character to the right of the cursor.", 49, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 79 }, { PROC_LINKS(delete_current_scope, 0), false, "delete_current_scope", 20, "Deletes the braces surrounding the currently selected scope. Leaves the contents within the scope.", 99, "W:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 112 }, diff --git a/ship_files/changes.txt b/ship_files/changes.txt index c4ed6fb1..ea04f84f 100644 --- a/ship_files/changes.txt +++ b/ship_files/changes.txt @@ -1,4 +1,11 @@ +4.1.7 + + Core string hash features "save_string" "read_string" + + Added lookup acceleration to code index data + + Added highlighting for functions, types, and macros in code index + + Default input is now dispatched through an "implicit map" callback + + Fix: crash when pasting in read only buffer + 4.1.6 + In config.4coder "bind_by_physical_key" uses a key-layout that does not change with language + Deprecated GlyphFlag_Rotate90, rotation of immediate mode text is entirely derived from the delta vector