eliminate stateful keybindings data structure - move to on-the-fly cfg tree usage

This commit is contained in:
Ryan Fleury
2025-01-14 17:30:07 -08:00
parent b98ebc8da4
commit 6fe9a14778
4 changed files with 281 additions and 202 deletions
+179 -130
View File
@@ -1143,6 +1143,48 @@ rd_cfg_is_project_filtered(RD_Cfg *cfg)
return result;
}
internal RD_KeyMapNodePtrList
rd_key_map_node_ptr_list_from_name(Arena *arena, String8 string)
{
RD_KeyMapNodePtrList list = {0};
{
U64 hash = d_hash_from_string(string);
U64 slot_idx = hash%rd_state->key_map->name_slots_count;
for(RD_KeyMapNode *n = rd_state->key_map->name_slots[slot_idx].first; n != 0; n = n->name_hash_next)
{
if(str8_match(n->name, string, 0))
{
RD_KeyMapNodePtr *ptr = push_array(arena, RD_KeyMapNodePtr, 1);
ptr->v = n;
SLLQueuePush(list.first, list.last, ptr);
list.count += 1;
}
}
}
return list;
}
internal RD_KeyMapNodePtrList
rd_key_map_node_ptr_list_from_binding(Arena *arena, RD_Binding binding)
{
RD_KeyMapNodePtrList list = {0};
{
U64 hash = d_hash_from_string(str8_struct(&binding));
U64 slot_idx = hash%rd_state->key_map->binding_slots_count;
for(RD_KeyMapNode *n = rd_state->key_map->binding_slots[slot_idx].first; n != 0; n = n->binding_hash_next)
{
if(MemoryMatchStruct(&binding, &n->binding))
{
RD_KeyMapNodePtr *ptr = push_array(arena, RD_KeyMapNodePtr, 1);
ptr->v = n;
SLLQueuePush(list.first, list.last, ptr);
list.count += 1;
}
}
}
return list;
}
////////////////////////////////
//~ rjf: Entity State Functions
@@ -4231,7 +4273,8 @@ rd_window_frame(void)
.display_name__matches = name_matches,
.description = cmd_desc,
.description__matches = desc_matches,
.is_non_code = 1);
.is_non_code = 1,
.can_have_bindings = 1);
}
}
}
@@ -4391,9 +4434,17 @@ rd_window_frame(void)
}
// rjf: bindings
if(0) UI_Column
if(item->can_have_bindings)
{
ui_set_next_flags(UI_BoxFlag_Clickable);
UI_PrefWidth(ui_children_sum(1.f)) UI_HeightFill UI_NamedColumn(str8_lit("binding_column")) UI_Padding(ui_em(1.5f, 1.f))
{
ui_set_next_flags(UI_BoxFlag_Clickable);
UI_NamedRow(str8_lit("binding_row")) UI_Padding(ui_em(1.f, 1.f))
{
rd_cmd_binding_buttons(item->string);
}
}
}
}
@@ -9997,123 +10048,6 @@ rd_push_search_string(Arena *arena)
////////////////////////////////
//~ rjf: Colors, Fonts, Config
//- rjf: keybindings
internal OS_Key
rd_os_key_from_cfg_string(String8 string)
{
OS_Key result = OS_Key_Null;
{
for(OS_Key key = OS_Key_Null; key < OS_Key_COUNT; key = (OS_Key)(key+1))
{
if(str8_match(string, os_g_key_cfg_string_table[key], StringMatchFlag_CaseInsensitive))
{
result = key;
break;
}
}
}
return result;
}
internal void
rd_clear_bindings(void)
{
arena_clear(rd_state->key_map_arena);
rd_state->key_map_table_size = 1024;
rd_state->key_map_table = push_array(rd_state->key_map_arena, RD_KeyMapSlot, rd_state->key_map_table_size);
rd_state->key_map_total_count = 0;
}
internal RD_BindingList
rd_bindings_from_name(Arena *arena, String8 name)
{
RD_BindingList result = {0};
U64 hash = d_hash_from_string(name);
U64 slot = hash%rd_state->key_map_table_size;
for(RD_KeyMapNode *n = rd_state->key_map_table[slot].first; n != 0; n = n->hash_next)
{
if(str8_match(n->name, name, 0))
{
RD_BindingNode *node = push_array(arena, RD_BindingNode, 1);
node->binding = n->binding;
SLLQueuePush(result.first, result.last, node);
result.count += 1;
}
}
return result;
}
internal void
rd_bind_name(String8 name, RD_Binding binding)
{
if(binding.key != OS_Key_Null)
{
U64 hash = d_hash_from_string(name);
U64 slot = hash%rd_state->key_map_table_size;
RD_KeyMapNode *existing_node = 0;
for(RD_KeyMapNode *n = rd_state->key_map_table[slot].first; n != 0; n = n->hash_next)
{
if(str8_match(n->name, name, 0) && n->binding.key == binding.key && n->binding.modifiers == binding.modifiers)
{
existing_node = n;
break;
}
}
if(existing_node == 0)
{
RD_KeyMapNode *n = rd_state->free_key_map_node;
if(n == 0)
{
n = push_array(rd_state->arena, RD_KeyMapNode, 1);
}
else
{
rd_state->free_key_map_node = rd_state->free_key_map_node->hash_next;
}
n->name = push_str8_copy(rd_state->arena, name);
n->binding = binding;
DLLPushBack_NP(rd_state->key_map_table[slot].first, rd_state->key_map_table[slot].last, n, hash_next, hash_prev);
rd_state->key_map_total_count += 1;
}
}
}
internal void
rd_unbind_name(String8 name, RD_Binding binding)
{
U64 hash = d_hash_from_string(name);
U64 slot = hash%rd_state->key_map_table_size;
for(RD_KeyMapNode *n = rd_state->key_map_table[slot].first, *next = 0; n != 0; n = next)
{
next = n->hash_next;
if(str8_match(n->name, name, 0) && n->binding.key == binding.key && n->binding.modifiers == binding.modifiers)
{
DLLRemove_NP(rd_state->key_map_table[slot].first, rd_state->key_map_table[slot].last, n, hash_next, hash_prev);
n->hash_next = rd_state->free_key_map_node;
rd_state->free_key_map_node = n;
rd_state->key_map_total_count -= 1;
}
}
}
internal String8List
rd_cmd_name_list_from_binding(Arena *arena, RD_Binding binding)
{
String8List result = {0};
for(U64 idx = 0; idx < rd_state->key_map_table_size; idx += 1)
{
for(RD_KeyMapNode *n = rd_state->key_map_table[idx].first; n != 0; n = n->hash_next)
{
if(n->binding.key == binding.key && n->binding.modifiers == binding.modifiers)
{
str8_list_push(arena, &result, n->name);
}
}
}
return result;
}
//- rjf: colors
internal Vec4F32
@@ -11335,7 +11269,7 @@ rd_cmd_kind_info_from_string(String8 string)
{
RD_CmdKindInfo *info = &rd_nil_cmd_kind_info;
{
// TODO(rjf): extend this by looking up into dynamically-registered commands by views
// TODO(rjf): @dynamic_cmds extend this by looking up into dynamically-registered commands by views
RD_CmdKind kind = rd_cmd_kind_from_string(string);
if(kind != RD_CmdKind_Null)
{
@@ -11419,7 +11353,6 @@ rd_init(CmdLine *cmdln)
rd_state->entities_base = push_array(rd_state->entities_arena, RD_Entity, 0);
rd_state->entities_count = 0;
rd_state->entities_root = rd_entity_alloc(&rd_nil_entity, RD_EntityKind_Root);
rd_state->key_map_arena = arena_alloc();
rd_state->popup_arena = arena_alloc();
rd_state->ctx_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("top_level_ctx_menu"));
rd_state->drop_completion_key = ui_key_from_string(ui_key_zero(), str8_lit("drop_completion_ctx_menu"));
@@ -11432,7 +11365,6 @@ rd_init(CmdLine *cmdln)
rd_state->drag_drop_arena = arena_alloc();
rd_state->drag_drop_regs = push_array(rd_state->drag_drop_arena, RD_Regs, 1);
rd_state->top_regs = &rd_state->base_regs;
rd_clear_bindings();
// rjf: set up top-level config entity trees
{
@@ -11704,6 +11636,109 @@ rd_frame(void)
}
}
//////////////////////////////
//- rjf: build key map from config
//
{
//- rjf: set up table
rd_state->key_map = push_array(rd_frame_arena(), RD_KeyMap, 1);
RD_KeyMap *key_map = rd_state->key_map;
key_map->name_slots_count = 4096;
key_map->name_slots = push_array(rd_frame_arena(), RD_KeyMapSlot, key_map->name_slots_count);
key_map->binding_slots_count = 4096;
key_map->binding_slots = push_array(rd_frame_arena(), RD_KeyMapSlot, key_map->binding_slots_count);
//- rjf: gather & parse all explicitly stored keybinding sets
RD_CfgList keybindings_cfg_list = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("keybindings"));
for(RD_CfgNode *n = keybindings_cfg_list.first; n != 0; n = n->next)
{
RD_Cfg *keybindings_root = n->v;
for(RD_Cfg *keybinding = keybindings_root->first; keybinding != &rd_nil_cfg; keybinding = keybinding->next)
{
String8 name = {0};
RD_Binding binding = {0};
for(RD_Cfg *child = keybinding->first; child != &rd_nil_cfg; child = child->next)
{
if(0){}
else if(str8_match(child->string, str8_lit("ctrl"), 0)) { binding.modifiers |= OS_Modifier_Ctrl; }
else if(str8_match(child->string, str8_lit("alt"), 0)) { binding.modifiers |= OS_Modifier_Alt; }
else if(str8_match(child->string, str8_lit("shift"), 0)) { binding.modifiers |= OS_Modifier_Shift; }
else
{
OS_Key key = OS_Key_Null;
for EachEnumVal(OS_Key, k)
{
if(str8_match(child->string, os_g_key_cfg_string_table[k], StringMatchFlag_CaseInsensitive))
{
key = k;
break;
}
}
if(key != OS_Key_Null)
{
binding.key = key;
}
else
{
name = child->string;
for(U64 idx = 0; idx < ArrayCount(rd_binding_version_remap_old_name_table); idx += 1)
{
if(str8_match(rd_binding_version_remap_old_name_table[idx], name, StringMatchFlag_CaseInsensitive))
{
name = rd_binding_version_remap_new_name_table[idx];
}
}
}
}
}
if(name.size != 0)
{
U64 name_hash = d_hash_from_string(name);
U64 binding_hash = d_hash_from_string(str8_struct(&binding));
U64 name_slot_idx = name_hash%key_map->name_slots_count;
U64 binding_slot_idx = binding_hash%key_map->binding_slots_count;
RD_KeyMapNode *n = push_array(rd_frame_arena(), RD_KeyMapNode, 1);
n->cfg = keybinding;
n->name = push_str8_copy(rd_frame_arena(), name);
n->binding = binding;
SLLQueuePush_N(key_map->name_slots[name_slot_idx].first, key_map->name_slots[name_slot_idx].last, n, name_hash_next);
SLLQueuePush_N(key_map->binding_slots[binding_slot_idx].first, key_map->binding_slots[binding_slot_idx].last, n, binding_hash_next);
}
}
}
//- rjf: iterate all commands - if they are not found in the map, then use
// the default binding.
// TODO(rjf): @dynamic_cmds
for EachElement(idx, rd_default_binding_table)
{
String8 name = rd_default_binding_table[idx].string;
B32 name_was_mapped = 0;
U64 name_hash = d_hash_from_string(name);
U64 name_slot_idx = name_hash%key_map->name_slots_count;
for(RD_KeyMapNode *n = key_map->name_slots[name_slot_idx].first; n != 0; n = n->name_hash_next)
{
if(str8_match(n->name, name, 0))
{
name_was_mapped = 1;
break;
}
}
if(!name_was_mapped)
{
RD_Binding binding = rd_default_binding_table[idx].binding;
U64 binding_hash = d_hash_from_string(str8_struct(&binding));
U64 binding_slot_idx = binding_hash%key_map->binding_slots_count;
RD_KeyMapNode *n = push_array(rd_frame_arena(), RD_KeyMapNode, 1);
n->cfg = &rd_nil_cfg;
n->name = push_str8_copy(rd_frame_arena(), name);
n->binding = binding;
SLLQueuePush_N(key_map->name_slots[name_slot_idx].first, key_map->name_slots[name_slot_idx].last, n, name_hash_next);
SLLQueuePush_N(key_map->binding_slots[binding_slot_idx].first, key_map->binding_slots[binding_slot_idx].last, n, binding_hash_next);
}
}
}
//////////////////////////////
//- rjf: get events from the OS
//
@@ -11774,7 +11809,7 @@ rd_frame(void)
if(os_key_press(&events, os_handle_zero(), 0, OS_Key_Delete))
{
rd_request_frame();
rd_unbind_name(rd_state->bind_change_cmd_name, rd_state->bind_change_binding);
// TODO(rjf): @cfg rd_unbind_name(rd_state->bind_change_cmd_name, rd_state->bind_change_binding);
rd_state->bind_change_active = 0;
rd_cmd(rd_cfg_src_write_cmd_kind_table[RD_CfgSrc_User]);
}
@@ -11798,8 +11833,8 @@ rd_frame(void)
binding.key = event->key;
binding.modifiers = event->modifiers;
}
rd_unbind_name(rd_state->bind_change_cmd_name, rd_state->bind_change_binding);
rd_bind_name(rd_state->bind_change_cmd_name, binding);
// TODO(rjf): @cfg rd_unbind_name(rd_state->bind_change_cmd_name, rd_state->bind_change_binding);
// TODO(rjf): @cfg rd_bind_name(rd_state->bind_change_cmd_name, binding);
U32 codepoint = os_codepoint_from_modifiers_and_key(event->modifiers, event->key);
os_text(&events, event->window, codepoint);
os_eat_event(&events, event);
@@ -11887,13 +11922,13 @@ rd_frame(void)
if(!take && event->kind == OS_EventKind_Press)
{
RD_Binding binding = {event->key, event->modifiers};
String8List spec_candidates = rd_cmd_name_list_from_binding(scratch.arena, binding);
if(spec_candidates.first != 0)
RD_KeyMapNodePtrList key_map_nodes = rd_key_map_node_ptr_list_from_binding(scratch.arena, binding);
if(key_map_nodes.first != 0)
{
U32 hit_char = os_codepoint_from_modifiers_and_key(event->modifiers, event->key);
if(hit_char == 0 || allow_text_hotkeys)
{
rd_cmd(RD_CmdKind_RunCommand, .cmd_name = spec_candidates.first->string);
rd_cmd(RD_CmdKind_RunCommand, .cmd_name = key_map_nodes.first->v->name);
if(allow_text_hotkeys)
{
os_text(&events, event->window, hit_char);
@@ -13118,6 +13153,7 @@ rd_frame(void)
}
//- rjf: apply keybindings
#if 0 // TODO(rjf): @cfg
if(src == RD_CfgSrc_User)
{
rd_clear_bindings();
@@ -13150,7 +13186,15 @@ rd_frame(void)
}
else
{
OS_Key k = rd_os_key_from_cfg_string(child->string);
OS_Key k = OS_Key_Null;
for EachEnumVal(OS_Key, key)
{
if(str8_match(child->string, os_g_key_cfg_string_table[key], StringMatchFlag_CaseInsensitive))
{
k = key;
break;
}
}
if(k != OS_Key_Null)
{
key = k;
@@ -13180,6 +13224,7 @@ rd_frame(void)
}
}
}
#endif
//- rjf: reset theme to default
MemoryCopy(rd_state->cfg_theme_target.colors, rd_theme_preset_colors__default_dark, sizeof(rd_theme_preset_colors__default_dark));
@@ -13362,6 +13407,7 @@ rd_frame(void)
#endif
//- rjf: if config bound 0 keys, we need to do some sensible default
#if 0 // TODO(rjf): @cfg
if(src == RD_CfgSrc_User && rd_state->key_map_total_count == 0)
{
for(U64 idx = 0; idx < ArrayCount(rd_default_binding_table); idx += 1)
@@ -13370,8 +13416,10 @@ rd_frame(void)
rd_bind_name(pair->string, pair->binding);
}
}
#endif
//- rjf: always ensure that the meta controls have bindings
#if 0 // TODO(rjf): @cfg
if(src == RD_CfgSrc_User)
{
struct
@@ -13395,6 +13443,7 @@ rd_frame(void)
}
}
}
#endif
}break;
//- rjf: writing config changes
+86 -60
View File
@@ -29,6 +29,38 @@ struct RD_HandleList
U64 count;
};
////////////////////////////////
//~ rjf: Binding Types
typedef struct RD_Binding RD_Binding;
struct RD_Binding
{
OS_Key key;
OS_Modifiers modifiers;
};
typedef struct RD_BindingNode RD_BindingNode;
struct RD_BindingNode
{
RD_BindingNode *next;
RD_Binding binding;
};
typedef struct RD_BindingList RD_BindingList;
struct RD_BindingList
{
RD_BindingNode *first;
RD_BindingNode *last;
U64 count;
};
typedef struct RD_StringBindingPair RD_StringBindingPair;
struct RD_StringBindingPair
{
String8 string;
RD_Binding binding;
};
////////////////////////////////
//~ rjf: Evaluation Spaces
@@ -84,57 +116,6 @@ enum
RD_EntityFlag_MarkedForDeletion = (1<<31),
};
////////////////////////////////
//~ rjf: Binding Types
typedef struct RD_Binding RD_Binding;
struct RD_Binding
{
OS_Key key;
OS_Modifiers modifiers;
};
typedef struct RD_BindingNode RD_BindingNode;
struct RD_BindingNode
{
RD_BindingNode *next;
RD_Binding binding;
};
typedef struct RD_BindingList RD_BindingList;
struct RD_BindingList
{
RD_BindingNode *first;
RD_BindingNode *last;
U64 count;
};
typedef struct RD_StringBindingPair RD_StringBindingPair;
struct RD_StringBindingPair
{
String8 string;
RD_Binding binding;
};
////////////////////////////////
//~ rjf: Key Map Types
typedef struct RD_KeyMapNode RD_KeyMapNode;
struct RD_KeyMapNode
{
RD_KeyMapNode *hash_next;
RD_KeyMapNode *hash_prev;
String8 name;
RD_Binding binding;
};
typedef struct RD_KeyMapSlot RD_KeyMapSlot;
struct RD_KeyMapSlot
{
RD_KeyMapNode *first;
RD_KeyMapNode *last;
};
////////////////////////////////
//~ rjf: Setting Types
@@ -330,6 +311,50 @@ struct RD_CfgRec
S32 pop_count;
};
////////////////////////////////
//~ rjf: Key Map Types
typedef struct RD_KeyMapNode RD_KeyMapNode;
struct RD_KeyMapNode
{
RD_KeyMapNode *name_hash_next;
RD_KeyMapNode *binding_hash_next;
RD_Cfg *cfg;
String8 name;
RD_Binding binding;
};
typedef struct RD_KeyMapNodePtr RD_KeyMapNodePtr;
struct RD_KeyMapNodePtr
{
RD_KeyMapNodePtr *next;
RD_KeyMapNode *v;
};
typedef struct RD_KeyMapNodePtrList RD_KeyMapNodePtrList;
struct RD_KeyMapNodePtrList
{
RD_KeyMapNodePtr *first;
RD_KeyMapNodePtr *last;
U64 count;
};
typedef struct RD_KeyMapSlot RD_KeyMapSlot;
struct RD_KeyMapSlot
{
RD_KeyMapNode *first;
RD_KeyMapNode *last;
};
typedef struct RD_KeyMap RD_KeyMap;
struct RD_KeyMap
{
U64 name_slots_count;
RD_KeyMapSlot *name_slots;
U64 binding_slots_count;
RD_KeyMapSlot *binding_slots;
};
////////////////////////////////
//~ rjf: New Panel Types (Queried From Config)
@@ -550,6 +575,7 @@ struct RD_ListerItem
FuzzyMatchRangeList description__matches;
U64 group;
B32 is_non_code;
B32 can_have_bindings;
};
typedef struct RD_ListerItemChunkNode RD_ListerItemChunkNode;
@@ -789,10 +815,13 @@ struct RD_State
// rjf: dbgi match store
DI_MatchStore *match_store;
// rjf: ambiguous path table
// rjf: ambiguous path table (constructed from-scratch each frame)
U64 ambiguous_path_slots_count;
RD_AmbiguousPathNode **ambiguous_path_slots;
// rjf: key map (constructed from-scratch each frame)
RD_KeyMap *key_map;
// rjf: registers stack
RD_RegsNode base_regs;
RD_RegsNode *top_regs;
@@ -890,11 +919,13 @@ struct RD_State
RD_EntityListCache kind_caches[RD_EntityKind_COUNT];
// rjf: key map table
#if 0 // TODO(rjf): @cfg
Arena *key_map_arena;
U64 key_map_table_size;
RD_KeyMapSlot *key_map_table;
RD_KeyMapNode *free_key_map_node;
U64 key_map_total_count;
#endif
// rjf: bind change
Arena *bind_change_arena;
@@ -1121,6 +1152,9 @@ internal Rng2F32 rd_target_rect_from_panel_node(Rng2F32 root_rect, RD_PanelNode
internal B32 rd_cfg_is_project_filtered(RD_Cfg *cfg);
internal RD_KeyMapNodePtrList rd_key_map_node_ptr_list_from_name(Arena *arena, String8 string);
internal RD_KeyMapNodePtrList rd_key_map_node_ptr_list_from_binding(Arena *arena, RD_Binding binding);
////////////////////////////////
//~ rjf: Entity Stateful Functions
@@ -1303,14 +1337,6 @@ internal String8 rd_push_search_string(Arena *arena);
////////////////////////////////
//~ rjf: Colors, Fonts, Config
//- rjf: keybindings
internal OS_Key rd_os_key_from_cfg_string(String8 string);
internal void rd_clear_bindings(void);
internal RD_BindingList rd_bindings_from_name(Arena *arena, String8 name);
internal void rd_bind_name(String8 name, RD_Binding binding);
internal void rd_unbind_name(String8 name, RD_Binding binding);
internal String8List rd_cmd_name_list_from_binding(Arena *arena, RD_Binding binding);
//- rjf: colors
internal Vec4F32 rd_rgba_from_theme_color(RD_ThemeColor color);
internal RD_ThemeColor rd_theme_color_from_txt_token_kind(TXT_TokenKind kind);
+2
View File
@@ -25,6 +25,8 @@
// etc., all need to be merged, and optionally contextualized/filtered.
// right-clicking a tab should be equivalent to spawning a command lister,
// but only with commands that are directly
//
// [ ] r8 bitmap view rule seems incorrect?
////////////////////////////////
//~ rjf: post-0.9.12 TODO notes
+14 -12
View File
@@ -95,26 +95,28 @@ internal void
rd_cmd_binding_buttons(String8 name)
{
Temp scratch = scratch_begin(0, 0);
RD_BindingList bindings = rd_bindings_from_name(scratch.arena, name);
RD_KeyMapNodePtrList key_map_nodes = rd_key_map_node_ptr_list_from_name(scratch.arena, name);
//- rjf: build buttons for each binding
for(RD_BindingNode *n = bindings.first; n != 0; n = n->next)
for(RD_KeyMapNodePtr *n = key_map_nodes.first; n != 0; n = n->next)
{
RD_Binding binding = n->binding;
RD_Binding binding = n->v->binding;
B32 rebinding_active_for_this_binding = (rd_state->bind_change_active &&
str8_match(rd_state->bind_change_cmd_name, name, 0) &&
rd_state->bind_change_binding.key == binding.key &&
rd_state->bind_change_binding.modifiers == binding.modifiers);
//- rjf: grab all conflicts
String8List specs_with_binding = rd_cmd_name_list_from_binding(scratch.arena, binding);
B32 has_conflicts = 0;
for(String8Node *n = specs_with_binding.first; n != 0; n = n->next)
RD_KeyMapNodePtrList nodes_with_this_binding = rd_key_map_node_ptr_list_from_binding(scratch.arena, binding);
{
if(!str8_match(n->string, name, 0))
for(RD_KeyMapNodePtr *n2 = nodes_with_this_binding.first; n2 != 0; n2 = n2->next)
{
has_conflicts = 1;
break;
if(!str8_match(n->v->name, n2->v->name, 0))
{
has_conflicts = 1;
break;
}
}
}
@@ -196,11 +198,11 @@ rd_cmd_binding_buttons(String8 name)
if(ui_hovering(sig) && has_conflicts) UI_Tooltip
{
UI_PrefWidth(ui_children_sum(1)) rd_error_label(str8_lit("This binding conflicts with those for:"));
for(String8Node *n = specs_with_binding.first; n != 0; n = n->next)
for(RD_KeyMapNodePtr *n2 = nodes_with_this_binding.first; n2 != 0; n2 = n2->next)
{
if(!str8_match(n->string, name, 0))
if(!str8_match(n2->v->name, n->v->name, 0))
{
RD_CmdKindInfo *info = rd_cmd_kind_info_from_string(n->string);
RD_CmdKindInfo *info = rd_cmd_kind_info_from_string(n2->v->name);
ui_labelf("%S", info->display_name);
}
}
@@ -219,7 +221,7 @@ rd_cmd_binding_buttons(String8 name)
UI_Signal sig = rd_icon_button(RD_IconKind_X, 0, str8_lit("###delete_binding"));
if(ui_clicked(sig))
{
rd_unbind_name(name, binding);
// TODO(rjf): @cfg rd_unbind_name(name, binding);
rd_state->bind_change_active = 0;
}
}