cfg schema-based path relativization on save, derelativization on load; omit for file path maps

This commit is contained in:
Ryan Fleury
2025-04-30 10:50:36 -07:00
parent 005ff83d67
commit ee9017d5db
6 changed files with 118 additions and 41 deletions
+5 -5
View File
@@ -90,7 +90,7 @@ path_absolute_dst_from_relative_dst_src(Arena *arena, String8 dst, String8 src)
if(dst_style == PathStyle_Relative)
{
Temp scratch = scratch_begin(&arena, 1);
String8 dst_from_src_absolute = push_str8f(scratch.arena, "%S/%S", src, dst);
String8 dst_from_src_absolute = push_str8f(scratch.arena, "%S/%S", str8_chop_last_slash(src), dst);
String8 dst_from_src_absolute_normalized = path_normalized_from_string(arena, dst_from_src_absolute);
result = dst_from_src_absolute_normalized;
scratch_end(scratch);
@@ -160,10 +160,10 @@ path_char_from_style(PathStyle style)
String8 result = str8_zero();
switch (style)
{
case PathStyle_Null: break;
case PathStyle_Relative: break;
case PathStyle_WindowsAbsolute: result = str8_lit("\\"); break;
case PathStyle_UnixAbsolute: result = str8_lit("/"); break;
case PathStyle_Null: break;
case PathStyle_Relative: break;
case PathStyle_WindowsAbsolute: result = str8_lit("\\"); break;
case PathStyle_UnixAbsolute: result = str8_lit("/"); break;
}
return result;
}
+4 -2
View File
@@ -52,7 +52,7 @@ str8_lit_comp(""),
str8_lit_comp(""),
};
RD_VocabInfo rd_vocab_info_table[325] =
RD_VocabInfo rd_vocab_info_table[327] =
{
{str8_lit_comp("auto_view_rule"), str8_lit_comp("auto_view_rules"), str8_lit_comp("Auto View Rule"), str8_lit_comp("Auto View Rules"), RD_IconKind_Binoculars},
{str8_lit_comp("file_path_map"), str8_lit_comp("file_path_maps"), str8_lit_comp("File Path Map"), str8_lit_comp("File Path Maps"), RD_IconKind_FileOutline},
@@ -87,6 +87,8 @@ RD_VocabInfo rd_vocab_info_table[325] =
{str8_lit_comp("recent_file"), str8_lit_comp("recent_files"), str8_lit_comp("Recent File"), str8_lit_comp("Recent Files"), RD_IconKind_FileOutline},
{str8_lit_comp("src"), str8_lit_comp("srcs"), str8_lit_comp("Source"), str8_lit_comp("Sources"), RD_IconKind_Null},
{str8_lit_comp("dst"), str8_lit_comp("dsts"), str8_lit_comp("Destination"), str8_lit_comp("Destinations"), RD_IconKind_Null},
{str8_lit_comp("source"), str8_lit_comp("sources"), str8_lit_comp("Source"), str8_lit_comp("Sources"), RD_IconKind_Null},
{str8_lit_comp("dest"), str8_lit_comp("dests"), str8_lit_comp("Destination"), str8_lit_comp("Destinations"), RD_IconKind_Null},
{str8_lit_comp("conversion_task"), str8_lit_comp("conversion_tasks"), str8_lit_comp("Conversion Task"), str8_lit_comp("Conversion Tasks"), RD_IconKind_Null},
{str8_lit_comp("conversion_fail"), str8_lit_comp("conversion_fails"), str8_lit_comp("Conversion Fail"), str8_lit_comp("Conversion Fails"), RD_IconKind_Null},
{str8_lit_comp("lang"), str8_lit_comp("langs"), str8_lit_comp("Language"), str8_lit_comp("Languages"), RD_IconKind_Null},
@@ -398,7 +400,7 @@ RD_NameSchemaInfo rd_name_schema_info_table[23] =
{str8_lit_comp("target"), str8_lit_comp("@row_commands(enable_cfg, launch_and_run, launch_and_step_into, duplicate_cfg, remove_cfg)\n@collection_commands(add_target)\nx:\n{\n 'label': code_string,\n 'executable': path,\n 'arguments': string,\n 'working_directory': path,\n 'entry_point': code_string,\n 'stdout_path': path,\n 'stderr_path': path,\n 'stdin_path': path,\n 'environment': query,\n 'debug_subprocesses': bool,\n @no_expand @default(0) 'enabled': bool,\n}\n")},
{str8_lit_comp("breakpoint"), str8_lit_comp("@row_commands(enable_cfg, duplicate_cfg, remove_cfg)\n@collection_commands(toggle_breakpoint, add_breakpoint, add_address_breakpoint)\nx:\n{\n 'label': code_string,\n 'condition': code_string,\n 'source_location': string,\n 'address_location': code_string,\n 'hit_count': u64,\n 'address_range_size': @or(0, 1, 2, 4, 8) u64,\n 'break_on_write': bool,\n 'break_on_read': bool,\n 'break_on_execute': bool,\n @no_expand @default(1) 'enabled': bool,\n}\n")},
{str8_lit_comp("watch_pin"), str8_lit_comp("@row_commands(duplicate_cfg, remove_cfg)\n@collection_commands(add_watch_pin, toggle_watch_pin)\nx:\n{\n 'expression': code_string,\n 'source_location': string,\n 'address_location': code_string,\n}\n")},
{str8_lit_comp("file_path_map"), str8_lit_comp("@collection_commands(add_file_path_map) @row_commands(remove_cfg) x:{'source':path, 'dest':path}")},
{str8_lit_comp("file_path_map"), str8_lit_comp("@collection_commands(add_file_path_map) @row_commands(remove_cfg) x:{'source': @absolute path, 'dest': @absolute path}")},
{str8_lit_comp("auto_view_rule"), str8_lit_comp("@collection_commands(add_auto_view_rule) @row_commands(remove_cfg) x:{'type':code_string, 'view_rule':code_string}")},
{str8_lit_comp("recent_project"), str8_lit_comp("x:{'path':path}")},
{str8_lit_comp("recent_file"), str8_lit_comp("x:{'path':path}")},
+1 -1
View File
@@ -678,7 +678,7 @@ Z(getting_started)\
C_LINKAGE_BEGIN
extern String8 rd_tab_fast_path_view_name_table[20];
extern String8 rd_tab_fast_path_query_name_table[20];
extern RD_VocabInfo rd_vocab_info_table[325];
extern RD_VocabInfo rd_vocab_info_table[327];
extern RD_NameSchemaInfo rd_name_schema_info_table[23];
extern Rng1U64 rd_reg_slot_range_table[43];
extern String8 rd_binding_version_remap_old_name_table[8];
+3 -1
View File
@@ -112,6 +112,8 @@ RD_VocabTable:
{recent_file _ "Recent File" _ FileOutline }
{src _ "Source" _ Null }
{dst _ "Destination" _ Null }
{source _ "Source" _ Null }
{dest _ "Destination" _ Null }
{conversion_task _ "Conversion Task" _ Null }
{conversion_fail _ "Conversion Fail" _ Null }
{lang _ "Language" _ Null }
@@ -581,7 +583,7 @@ RD_VocabTable:
//- rjf: file path maps
{
file_path_map,
```@collection_commands(add_file_path_map) @row_commands(remove_cfg) x:{'source':path, 'dest':path}```,
```@collection_commands(add_file_path_map) @row_commands(remove_cfg) x:{'source': @absolute path, 'dest': @absolute path}```,
}
//- rjf: auto view rules
+103 -30
View File
@@ -607,11 +607,15 @@ rd_cfg_array_from_list(Arena *arena, RD_CfgList *list)
}
internal RD_CfgList
rd_cfg_tree_list_from_string(Arena *arena, String8 string)
rd_cfg_tree_list_from_string(Arena *arena, String8 root_path, String8 string)
{
RD_CfgList result = {0};
Temp scratch = scratch_begin(&arena, 1);
//- rjf: parse the string as metadesk
MD_Node *root = md_tree_from_string(scratch.arena, string);
//- rjf: iterate the top-level metadesk trees, generate new cfg trees for each
for MD_EachNode(tln, root->first)
{
RD_Cfg *dst_root_n = &rd_nil_cfg;
@@ -619,14 +623,39 @@ rd_cfg_tree_list_from_string(Arena *arena, String8 string)
MD_NodeRec rec = {0};
for(MD_Node *src_n = tln; !md_node_is_nil(src_n); src_n = rec.next)
{
// rjf: lookup schema for this string
MD_Node *schema = &md_nil_node;
{
MD_NodePtrList schemas = rd_schemas_from_name(dst_active_parent_n->parent->string);
for(MD_NodePtrNode *n = schemas.first; n != 0 && schema == &md_nil_node; n = n->next)
{
schema = md_child_from_string(n->v, dst_active_parent_n->string, 0);
}
}
// rjf: extract & transform metadesk node's string (it is raw textual data, so we need to
// go escaped -> raw, and derelativize paths)
String8 dst_n_string = {0};
{
String8 src_n_string = src_n->string;
String8 src_n_string__raw = raw_from_escaped_str8(scratch.arena, src_n_string);
if(str8_match(schema->first->string, str8_lit("path"), 0) &&
!md_node_has_tag(schema->first, str8_lit("absolute"), 0))
{
src_n_string__raw = path_absolute_dst_from_relative_dst_src(scratch.arena, src_n_string__raw, root_path);
}
dst_n_string = src_n_string__raw;
}
// rjf: allocate, fill, & insert new cfg for this metadesk node
RD_Cfg *dst_n = rd_cfg_alloc();
String8 src_n_string = src_n->string;
String8 src_n_string__raw = raw_from_escaped_str8(scratch.arena, src_n_string);
rd_cfg_equip_string(dst_n, src_n_string__raw);
rd_cfg_equip_string(dst_n, dst_n_string);
if(dst_active_parent_n != &rd_nil_cfg)
{
rd_cfg_insert_child(dst_active_parent_n, dst_active_parent_n->last, dst_n);
}
// rjf: recurse
rec = md_node_rec_depth_first_pre(src_n, tln);
if(dst_active_parent_n == &rd_nil_cfg)
{
@@ -648,7 +677,7 @@ rd_cfg_tree_list_from_string(Arena *arena, String8 string)
}
internal String8
rd_string_from_cfg_tree(Arena *arena, RD_Cfg *cfg)
rd_string_from_cfg_tree(Arena *arena, String8 root_path, RD_Cfg *cfg)
{
Temp scratch = scratch_begin(&arena, 1);
String8List strings = {0};
@@ -658,49 +687,92 @@ rd_string_from_cfg_tree(Arena *arena, RD_Cfg *cfg)
{
NestTask *next;
RD_Cfg *cfg;
MD_Node *schema;
B32 is_simple;
};
NestTask *top_nest_task = 0;
RD_CfgRec rec = {0};
for(RD_Cfg *c = cfg; c != &rd_nil_cfg; c = rec.next)
{
// rjf: look up parent's schemas
MD_NodePtrList schemas = {0};
if(top_nest_task != 0)
{
RD_Cfg *parent = top_nest_task->cfg;
schemas = rd_schemas_from_name(parent->string);
}
// rjf: look up child schema
MD_Node *c_schema = &md_nil_node;
for(MD_NodePtrNode *n = schemas.first; n != 0 && c_schema == &md_nil_node; n = n->next)
{
c_schema = md_child_from_string(n->v, c->string, 0);
}
// rjf: push name of this node
if(c->string.size != 0 || c->first == &rd_nil_cfg)
{
// rjf: extract the textualized form for this string (we may need to escape / relativize)
String8 c_serialized_string = c->string;
{
MD_Node *c_schema = &md_nil_node;
if(top_nest_task != 0)
{
c_schema = top_nest_task->schema;
}
// rjf: paths -> relativize
if(str8_match(c_schema->first->string, str8_lit("path"), 0) &&
!md_node_has_tag(c_schema->first, str8_lit("absolute"), 0))
{
String8 path_absolute = c->string;
String8 path_relative = path_relative_dst_from_absolute_dst_src(arena, path_absolute, root_path);
c_serialized_string = path_relative;
}
// rjf: all strings -> escape
c_serialized_string = escaped_from_raw_str8(arena, c_serialized_string);
}
// rjf: generate all strings for this node's string
String8List c_name_strings = {0};
B32 name_can_be_pushed_standalone = 0;
{
Temp temp = temp_begin(scratch.arena);
MD_TokenizeResult c_name_tokenize = md_tokenize_from_text(temp.arena, c->string);
name_can_be_pushed_standalone = (c_name_tokenize.tokens.count == 1 && c_name_tokenize.tokens.v[0].flags & (MD_TokenFlag_Identifier|
MD_TokenFlag_Numeric|
MD_TokenFlag_StringLiteral|
MD_TokenFlag_Symbol));
temp_end(temp);
}
if(name_can_be_pushed_standalone)
{
str8_list_push(scratch.arena, &c_name_strings, c->string);
}
else
{
String8 c_name_escaped = escaped_from_raw_str8(scratch.arena, c->string);
str8_list_push(scratch.arena, &c_name_strings, str8_lit("\""));
str8_list_push(scratch.arena, &c_name_strings, c_name_escaped);
str8_list_push(scratch.arena, &c_name_strings, str8_lit("\""));
B32 name_can_be_pushed_standalone = 0;
{
Temp temp = temp_begin(scratch.arena);
MD_TokenizeResult c_name_tokenize = md_tokenize_from_text(temp.arena, c_serialized_string);
name_can_be_pushed_standalone = (c_name_tokenize.tokens.count == 1 && c_name_tokenize.tokens.v[0].flags & (MD_TokenFlag_Identifier|
MD_TokenFlag_Numeric|
MD_TokenFlag_StringLiteral|
MD_TokenFlag_Symbol));
temp_end(temp);
}
if(name_can_be_pushed_standalone)
{
str8_list_push(scratch.arena, &c_name_strings, c_serialized_string);
}
else
{
str8_list_push(scratch.arena, &c_name_strings, str8_lit("\""));
str8_list_push(scratch.arena, &c_name_strings, c_serialized_string);
str8_list_push(scratch.arena, &c_name_strings, str8_lit("\""));
}
}
// rjf: if we're in a simple nesting task, then just break children by space
if(top_nest_task != 0 && top_nest_task->is_simple)
{
str8_list_push(scratch.arena, &strings, str8_lit(" "));
}
// rjf: join c's strings with main string list
str8_list_concat_in_place(&strings, &c_name_strings);
}
// rjf: grab next recursion
rec = rd_cfg_rec__depth_first(cfg, c);
// rjf: determine if this node is simple, and can be encoded on a single line -
// if so, push a new nesting task onto the stack
// rjf: push a new nesting task before descending to children
if(c->first != &rd_nil_cfg)
{
B32 is_simple_children_list = 1;
@@ -714,6 +786,7 @@ rd_string_from_cfg_tree(Arena *arena, RD_Cfg *cfg)
}
NestTask *task = push_array(scratch.arena, NestTask, 1);
task->cfg = c;
task->schema = c_schema;
task->is_simple = is_simple_children_list;
SLLStackPush(top_nest_task, task);
}
@@ -5717,7 +5790,7 @@ rd_window_frame(void)
{
ThemeTask *t = push_array(scratch.arena, ThemeTask, 1);
SLLQueuePushFront(first_task, last_task, t);
t->tree = md_tree_from_string(scratch.arena, rd_string_from_cfg_tree(scratch.arena, n->v));
t->tree = md_tree_from_string(scratch.arena, rd_string_from_cfg_tree(scratch.arena, str8_zero(), n->v));
}
}
@@ -12707,7 +12780,7 @@ rd_frame(void)
for(String8Node *text_n = raddbg_data_text_parts.first; text_n != 0; text_n = text_n->next)
{
String8 text = text_n->string;
RD_CfgList cfgs = rd_cfg_tree_list_from_string(scratch.arena, text);
RD_CfgList cfgs = rd_cfg_tree_list_from_string(scratch.arena, str8_zero(), text);
String8 module_name = ctrl_string_from_handle(scratch.arena, module->handle);
for(RD_CfgNode *n = cfgs.first; n != 0; n = n->next, cfg_idx += 1)
{
@@ -13098,7 +13171,7 @@ rd_frame(void)
RD_CfgList file_cfg_list = {0};
if(file_is_okay)
{
file_cfg_list = rd_cfg_tree_list_from_string(scratch.arena, file_data);
file_cfg_list = rd_cfg_tree_list_from_string(scratch.arena, file_path, file_data);
}
//- rjf: store path
@@ -13221,7 +13294,7 @@ rd_frame(void)
str8_list_pushf(scratch.arena, &strings, "// raddbg %s %S file\n\n", BUILD_VERSION_STRING_LITERAL, bucket_name);
for(RD_Cfg *child = tree_root->first; child != &rd_nil_cfg; child = child->next)
{
str8_list_push(scratch.arena, &strings, rd_string_from_cfg_tree(scratch.arena, child));
str8_list_push(scratch.arena, &strings, rd_string_from_cfg_tree(scratch.arena, dst_path, child));
}
String8 data = str8_list_join(scratch.arena, &strings, 0);
B32 temp_write_good = os_write_data_to_file_path(temp_path, data);
+2 -2
View File
@@ -865,8 +865,8 @@ internal RD_Cfg *rd_cfg_child_from_string_or_parent(RD_Cfg *parent, String8 stri
internal RD_CfgList rd_cfg_child_list_from_string(Arena *arena, RD_Cfg *parent, String8 string);
internal RD_CfgList rd_cfg_top_level_list_from_string(Arena *arena, String8 string);
internal RD_CfgArray rd_cfg_array_from_list(Arena *arena, RD_CfgList *list);
internal RD_CfgList rd_cfg_tree_list_from_string(Arena *arena, String8 string);
internal String8 rd_string_from_cfg_tree(Arena *arena, RD_Cfg *cfg);
internal RD_CfgList rd_cfg_tree_list_from_string(Arena *arena, String8 root_path, String8 string);
internal String8 rd_string_from_cfg_tree(Arena *arena, String8 root_path, RD_Cfg *cfg);
internal RD_CfgRec rd_cfg_rec__depth_first(RD_Cfg *root, RD_Cfg *cfg);
internal void rd_cfg_list_push(Arena *arena, RD_CfgList *list, RD_Cfg *cfg);
internal void rd_cfg_list_push_front(Arena *arena, RD_CfgList *list, RD_Cfg *cfg);