@@ -949,17 +949,108 @@ rd_title_fstrs_from_view(Arena *arena, RD_View *view, Vec4F32 primary_color, Vec
949949 Temp scratch = scratch_begin(&arena, 1);
950950 String8 query = str8(view->query_buffer, view->query_string_size);
951951 String8 file_path = rd_file_path_from_eval_string(scratch.arena, query);
952+
953+ //- rjf: query is file path - do specific file name strings
952954 if(file_path.size != 0)
953955 {
956+ // rjf: compute disambiguated file name
957+ String8List qualifiers = {0};
958+ String8 file_name = str8_skip_last_slash(file_path);
959+ if(rd_state->ambiguous_path_slots_count != 0)
960+ {
961+ U64 hash = d_hash_from_string__case_insensitive(file_name);
962+ U64 slot_idx = hash%rd_state->ambiguous_path_slots_count;
963+ RD_AmbiguousPathNode *node = 0;
964+ {
965+ for(RD_AmbiguousPathNode *n = rd_state->ambiguous_path_slots[slot_idx];
966+ n != 0;
967+ n = n->next)
968+ {
969+ if(str8_match(n->name, file_name, StringMatchFlag_CaseInsensitive))
970+ {
971+ node = n;
972+ break;
973+ }
974+ }
975+ }
976+ if(node != 0 && node->paths.node_count > 1)
977+ {
978+ // rjf: get all colliding paths
979+ String8Array collisions = str8_array_from_list(scratch.arena, &node->paths);
980+
981+ // rjf: get all reversed path parts for each collision
982+ String8List *collision_parts_reversed = push_array(scratch.arena, String8List, collisions.count);
983+ for EachIndex(idx, collisions.count)
984+ {
985+ String8List parts = str8_split_path(scratch.arena, collisions.v[idx]);
986+ for(String8Node *n = parts.first; n != 0; n = n->next)
987+ {
988+ str8_list_push_front(scratch.arena, &collision_parts_reversed[idx], n->string);
989+ }
990+ }
991+
992+ // rjf: get the search path & its reversed parts
993+ String8List parts = str8_split_path(scratch.arena, file_path);
994+ String8List parts_reversed = {0};
995+ for(String8Node *n = parts.first; n != 0; n = n->next)
996+ {
997+ str8_list_push_front(scratch.arena, &parts_reversed, n->string);
998+ }
999+
1000+ // rjf: iterate all collision part reversed lists, in lock-step with
1001+ // search path; disqualify until we only have one path remaining; gather
1002+ // qualifiers
1003+ {
1004+ U64 num_collisions_left = collisions.count;
1005+ String8Node **collision_nodes = push_array(scratch.arena, String8Node *, collisions.count);
1006+ for EachIndex(idx, collisions.count)
1007+ {
1008+ collision_nodes[idx] = collision_parts_reversed[idx].first;
1009+ }
1010+ for(String8Node *n = parts_reversed.first; num_collisions_left > 1 && n != 0; n = n->next)
1011+ {
1012+ B32 part_is_qualifier = 0;
1013+ for EachIndex(idx, collisions.count)
1014+ {
1015+ if(collision_nodes[idx] != 0 && !str8_match(collision_nodes[idx]->string, n->string, StringMatchFlag_CaseInsensitive))
1016+ {
1017+ collision_nodes[idx] = 0;
1018+ num_collisions_left -= 1;
1019+ part_is_qualifier = 1;
1020+ }
1021+ else if(collision_nodes[idx] != 0)
1022+ {
1023+ collision_nodes[idx] = collision_nodes[idx]->next;
1024+ }
1025+ }
1026+ if(part_is_qualifier)
1027+ {
1028+ str8_list_push_front(scratch.arena, &qualifiers, n->string);
1029+ }
1030+ }
1031+ }
1032+ }
1033+ }
1034+
1035+ // rjf: push qualifiers
1036+ for(String8Node *n = qualifiers.first; n != 0; n = n->next)
1037+ {
1038+ String8 string = push_str8f(arena, "<%S> ", n->string);
1039+ dr_fancy_string_list_push_new(arena, &result, rd_font_from_slot(RD_FontSlot_Main), size*0.95f, secondary_color, string);
1040+ }
1041+
1042+ // rjf: push file name
9541043 DR_FancyString fstr =
9551044 {
9561045 rd_font_from_slot(RD_FontSlot_Main),
957- push_str8_copy(arena, str8_skip_last_slash(file_path) ),
1046+ push_str8_copy(arena, file_name ),
9581047 primary_color,
9591048 size,
9601049 };
9611050 dr_fancy_string_list_push(arena, &result, &fstr);
9621051 }
1052+
1053+ //- rjf: query is not file path - do general case, for view rule & expression
9631054 else
9641055 {
9651056 DR_FancyString fstr1 =
@@ -16505,6 +16596,55 @@ rd_frame(void)
1650516596 }
1650616597 }
1650716598
16599+ //////////////////////////////
16600+ //- rjf: compute all ambiguous paths from view titles
16601+ //
16602+ {
16603+ Temp scratch = scratch_begin(0, 0);
16604+ rd_state->ambiguous_path_slots_count = 512;
16605+ rd_state->ambiguous_path_slots = push_array(rd_frame_arena(), RD_AmbiguousPathNode *, rd_state->ambiguous_path_slots_count);
16606+ for(RD_Window *w = rd_state->first_window; w != 0; w = w->next)
16607+ {
16608+ for(RD_Panel *p = w->root_panel; !rd_panel_is_nil(p); p = rd_panel_rec_depth_first_pre(p).next)
16609+ {
16610+ for(RD_View *v = p->first_tab_view; !rd_view_is_nil(v); v = v->order_next)
16611+ {
16612+ if(rd_view_is_project_filtered(v))
16613+ {
16614+ continue;
16615+ }
16616+ String8 eval_string = str8(v->query_buffer, v->query_string_size);
16617+ String8 file_path = rd_file_path_from_eval_string(scratch.arena, eval_string);
16618+ if(file_path.size != 0)
16619+ {
16620+ String8 name = str8_skip_last_slash(file_path);
16621+ U64 hash = d_hash_from_string__case_insensitive(name);
16622+ U64 slot_idx = hash%rd_state->ambiguous_path_slots_count;
16623+ RD_AmbiguousPathNode *node = 0;
16624+ for(RD_AmbiguousPathNode *n = rd_state->ambiguous_path_slots[slot_idx];
16625+ n != 0;
16626+ n = n->next)
16627+ {
16628+ if(str8_match(n->name, name, StringMatchFlag_CaseInsensitive))
16629+ {
16630+ node = n;
16631+ break;
16632+ }
16633+ }
16634+ if(node == 0)
16635+ {
16636+ node = push_array(rd_frame_arena(), RD_AmbiguousPathNode, 1);
16637+ SLLStackPush(rd_state->ambiguous_path_slots[slot_idx], node);
16638+ node->name = push_str8_copy(rd_frame_arena(), name);
16639+ }
16640+ str8_list_push(rd_frame_arena(), &node->paths, push_str8_copy(rd_frame_arena(), file_path));
16641+ }
16642+ }
16643+ }
16644+ }
16645+ scratch_end(scratch);
16646+ }
16647+
1650816648 //////////////////////////////
1650916649 //- rjf: update/render all windows
1651016650 //
0 commit comments