sketch out first pass of autocompletion list-expr/replace-range/filter based on cursor-offset -> expression-node path

This commit is contained in:
Ryan Fleury
2025-05-01 09:47:20 -07:00
parent 3a46e66efa
commit aa9a00f754
5 changed files with 123 additions and 29 deletions
+15 -7
View File
@@ -1177,20 +1177,28 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
// rjf: look for member name
E_Token member_name_maybe = e_token_at_it(it, &tokens);
String8 member_name_maybe_string = str8_substr(text, member_name_maybe.range);
B32 member_name_is_good = (member_name_maybe.kind == E_TokenKind_Identifier);
// rjf: if we have a member name, build dot-operator tree
if(member_name_maybe.kind == E_TokenKind_Identifier)
// rjf: build dot-operator tree
E_Expr *lhs = atom;
E_Expr *rhs = &e_expr_nil;
if(member_name_is_good)
{
it += 1;
E_Expr *lhs = atom;
E_Expr *rhs = e_push_expr(arena, E_ExprKind_LeafIdentifier, member_name_maybe.range);
rhs = e_push_expr(arena, E_ExprKind_LeafIdentifier, member_name_maybe.range);
rhs->string = member_name_maybe_string;
atom = e_push_expr(arena, E_ExprKind_MemberAccess, token.range);
e_expr_push_child(atom, lhs);
}
atom = e_push_expr(arena, E_ExprKind_MemberAccess, token.range);
e_expr_push_child(atom, lhs);
if(member_name_is_good)
{
e_expr_push_child(atom, rhs);
}
// rjf: no identifier after `.`? -> error
if(member_name_is_good)
{
it += 1;
}
else
{
e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Missing member name after `%S`.", token_string);
+86 -7
View File
@@ -3578,13 +3578,12 @@ rd_view_ui(Rng2F32 rect)
if(autocomplete_hint_string.size != 0)
{
take_autocomplete = 1;
String8 word_query = rd_lister_query_word_from_input_string_off(string, edit_state->cursor.column-1);
U64 word_off = (U64)(word_query.str - string.str);
String8 new_string = ui_push_string_replace_range(scratch.arena, string, r1s64(word_off+1, word_off+1+word_query.size), autocomplete_hint_string);
RD_AutocompCursorInfo autocomp_cursor_info = rd_autocomp_cursor_info_from_input_string_off(scratch.arena, string, edit_state->cursor.column-1);
String8 new_string = ui_push_string_replace_range(scratch.arena, string, r1s64(autocomp_cursor_info.replaced_range.min+1, autocomp_cursor_info.replaced_range.max+1), autocomplete_hint_string);
new_string.size = Min(sizeof(edit_state->input_buffer), new_string.size);
MemoryCopy(edit_state->input_buffer, new_string.str, new_string.size);
edit_state->input_size = new_string.size;
edit_state->cursor = edit_state->mark = txt_pt(1, word_off+1+autocomplete_hint_string.size);
edit_state->cursor = edit_state->mark = txt_pt(1, 1+autocomp_cursor_info.replaced_range.min+autocomplete_hint_string.size);
string = str8(edit_state->input_buffer, edit_state->input_size);
op = ui_single_line_txt_op_from_event(scratch.arena, evt, string, edit_state->cursor, edit_state->mark);
}
@@ -4956,7 +4955,10 @@ rd_view_ui(Rng2F32 rect)
txt_pt_match(cell_edit_state->cursor, cell_edit_state->mark))
{
String8 input = str8(cell_edit_state->input_buffer, cell_edit_state->input_size);
rd_set_autocomp_regs(.ui_key = sig.box->key, .string = input, .cursor = cell_edit_state->cursor);
RD_AutocompCursorInfo cursor_info = rd_autocomp_cursor_info_from_input_string_off(scratch.arena, input, cell_edit_state->cursor.column-1);
rd_set_autocomp_regs(.ui_key = sig.box->key,
.string = cursor_info.filter,
.expr = cursor_info.list_expr);
}
}
}
@@ -6663,7 +6665,7 @@ rd_window_frame(void)
RD_Cfg *input = rd_cfg_child_from_string_or_alloc(query, str8_lit("input"));
rd_cfg_new_replace(input, ws->autocomp_regs->string);
RD_Cfg *expr = rd_cfg_child_from_string_or_alloc(view, str8_lit("expression"));
rd_cfg_new_replacef(expr, "query:locals, query:globals, query:thread_locals, query:procedures, query:types");
rd_cfg_new_replace(expr, ws->autocomp_regs->expr);
// rjf: determine container size
EV_BlockTree predicted_block_tree = {0};
@@ -9722,8 +9724,85 @@ rd_set_hover_eval(Vec2F32 pos, String8 string)
////////////////////////////////
//~ rjf: Autocompletion Lister
internal RD_AutocompCursorInfo
rd_autocomp_cursor_info_from_input_string_off(Arena *arena, String8 input, U64 cursor_off)
{
RD_AutocompCursorInfo result = {0};
{
result.list_expr = str8_lit("query:locals, query:globals, query:thread_locals, query:procedures, query:types");
result.filter = input;
result.replaced_range = r1u64(0, input.size);
}
Temp scratch = scratch_begin(&arena, 1);
E_Parse parse = e_parse_from_string(input);
//- rjf: cursor offset -> cursor containing node
E_Expr *cursor_expr = &e_expr_nil;
E_Expr *cursor_expr_parent = &e_expr_nil;
{
typedef struct ExprWalkTask ExprWalkTask;
struct ExprWalkTask
{
ExprWalkTask *next;
E_Expr *parent;
E_Expr *expr;
};
ExprWalkTask start_task = {0, &e_expr_nil, parse.expr};
ExprWalkTask *first_task = &start_task;
ExprWalkTask *last_task = first_task;
for(E_Expr *chain = parse.expr->next; chain != &e_expr_nil; chain = chain->next)
{
ExprWalkTask *task = push_array(scratch.arena, ExprWalkTask, 1);
SLLQueuePush(first_task, last_task, task);
task->parent = &e_expr_nil;
task->expr = chain;
}
for(ExprWalkTask *t = first_task; t != 0; t = t->next)
{
E_Expr *e = t->expr;
if(contains_1u64(e->range, cursor_off) || cursor_off == e->range.max)
{
cursor_expr_parent = t->parent;
cursor_expr = e;
break;
}
for(E_Expr *child = e->first; child != &e_expr_nil; child = child->next)
{
ExprWalkTask *task = push_array(scratch.arena, ExprWalkTask, 1);
SLLQueuePush(first_task, last_task, task);
task->parent = e;
task->expr = child;
}
}
}
//- rjf: cursor is on right-hand-side of dot? -> show members of left-hand-side
{
E_Expr *dot_expr = &e_expr_nil;
if(cursor_expr->kind == E_ExprKind_MemberAccess && cursor_off == cursor_expr->range.max)
{
dot_expr = cursor_expr;
}
else if(cursor_expr_parent->kind == E_ExprKind_MemberAccess && cursor_expr == cursor_expr_parent->first->next)
{
dot_expr = cursor_expr_parent;
}
if(dot_expr != &e_expr_nil)
{
E_Eval lhs_eval = e_eval_from_expr(dot_expr->first);
E_Eval type_of_lhs_eval = e_eval_wrapf(lhs_eval, "typeof($)");
result.list_expr = e_full_expr_string_from_key(arena, type_of_lhs_eval.key);
result.filter = cursor_expr->string;
result.replaced_range = union_1u64(dot_expr->range, cursor_expr->range);
}
}
scratch_end(scratch);
return result;
}
internal String8
rd_lister_query_word_from_input_string_off(String8 input, U64 cursor_off)
rd_autocomp_query_word_from_input_string_off(String8 input, U64 cursor_off)
{
U64 word_start_off = 0;
for(U64 off = 0; off < input.size && off < cursor_off; off += 1)
+13 -1
View File
@@ -162,6 +162,17 @@ enum
RD_CmdKindFlag_ListInTextRng = (1<<4),
};
////////////////////////////////
//~ rjf: Autocompletion Cursor Info Type
typedef struct RD_AutocompCursorInfo RD_AutocompCursorInfo;
struct RD_AutocompCursorInfo
{
String8 list_expr;
String8 filter;
Rng1U64 replaced_range;
};
////////////////////////////////
//~ rjf: Generated Code
@@ -951,7 +962,8 @@ internal void rd_set_hover_eval(Vec2F32 pos, String8 string);
////////////////////////////////
//~ rjf: Autocompletion Lister
internal String8 rd_lister_query_word_from_input_string_off(String8 input, U64 cursor_off);
internal RD_AutocompCursorInfo rd_autocomp_cursor_info_from_input_string_off(Arena *arena, String8 input, U64 cursor_off);
internal String8 rd_autocomp_query_word_from_input_string_off(String8 input, U64 cursor_off);
internal void rd_set_autocomp_regs_(RD_Regs *regs);
#define rd_set_autocomp_regs(...) rd_set_autocomp_regs_(&(RD_Regs){rd_regs_lit_init_top __VA_ARGS__})
+4 -8
View File
@@ -1689,14 +1689,10 @@ rd_info_from_watch_row_cell(Arena *arena, EV_Row *row, EV_StringFlags string_fla
// do a code-string of ".member_name"
String8 member_name = notable_expr->first->next->string;
String8 fancy_name = {0};
if(str8_match(member_name, str8_lit("$padding"), StringMatchFlag_RightSideSloppy))
{
fancy_name = str8_lit("Padding");
}
else if(cell->eval.space.kind == RD_EvalSpaceKind_MetaCfg ||
cell->eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity ||
cell->eval.space.kind == E_SpaceKind_File ||
cell->eval.space.kind == E_SpaceKind_FileSystem)
if(cell->eval.space.kind == RD_EvalSpaceKind_MetaCfg ||
cell->eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity ||
cell->eval.space.kind == E_SpaceKind_File ||
cell->eval.space.kind == E_SpaceKind_FileSystem)
{
fancy_name = rd_display_from_code_name(member_name);
}
+5 -6
View File
@@ -3576,13 +3576,12 @@ rd_cell(RD_CellParams *params, String8 string)
// rjf: any valid op & autocomplete hint? -> perform autocomplete first, then re-compute op
if(autocomplete_hint_string.size != 0)
{
String8 word_query = rd_lister_query_word_from_input_string_off(edit_string, params->cursor->column-1);
U64 word_off = (U64)(word_query.str - edit_string.str);
String8 new_string = ui_push_string_replace_range(scratch.arena, edit_string, r1s64(word_off+1, word_off+1+word_query.size), autocomplete_hint_string);
RD_AutocompCursorInfo autocomp_cursor_info = rd_autocomp_cursor_info_from_input_string_off(scratch.arena, edit_string, params->cursor->column-1);
String8 new_string = ui_push_string_replace_range(scratch.arena, edit_string, r1s64(autocomp_cursor_info.replaced_range.min+1, autocomp_cursor_info.replaced_range.max+1), autocomplete_hint_string);
new_string.size = Min(params->edit_buffer_size, new_string.size);
MemoryCopy(params->edit_buffer, new_string.str, new_string.size);
params->edit_string_size_out[0] = new_string.size;
params->cursor[0] = params->mark[0] = txt_pt(1, word_off+1+autocomplete_hint_string.size);
params->cursor[0] = params->mark[0] = txt_pt(1, 1+autocomp_cursor_info.replaced_range.min+autocomplete_hint_string.size);
edit_string = str8(params->edit_buffer, params->edit_string_size_out[0]);
op = ui_single_line_txt_op_from_event(scratch.arena, evt, edit_string, params->cursor[0], params->mark[0]);
MemoryZeroStruct(&autocomplete_hint_string);
@@ -3652,8 +3651,8 @@ rd_cell(RD_CellParams *params, String8 string)
DR_FStrList code_fstrs = rd_fstrs_from_code_string(scratch.arena, 1.f, 0, ui_color_from_name(str8_lit("text")), edit_string);
if(autocomplete_hint_string.size != 0)
{
String8 query_word = rd_lister_query_word_from_input_string_off(edit_string, params->cursor->column-1);
String8 autocomplete_append_string = str8_skip(autocomplete_hint_string, query_word.size);
RD_AutocompCursorInfo autocomp_cursor_info = rd_autocomp_cursor_info_from_input_string_off(scratch.arena, edit_string, params->cursor->column-1);
String8 autocomplete_append_string = str8_skip(autocomplete_hint_string, params->cursor->column-1 - autocomp_cursor_info.replaced_range.min);
U64 off = 0;
U64 cursor_off = params->cursor->column-1;
DR_FStrNode *prev_n = 0;