luaur_repl_cli/functions/
complete_indexer.rs1use core::ffi::c_char;
2
3use luaur_vm::functions::lua_checkstack::lua_checkstack;
4use luaur_vm::functions::lua_pushlstring::lua_pushlstring;
5use luaur_vm::functions::lua_pushvalue::lua_pushvalue;
6use luaur_vm::functions::lua_remove::lua_remove;
7use luaur_vm::macros::lua_globalsindex::LUA_GLOBALSINDEX;
8use luaur_vm::macros::lua_istable::lua_istable;
9use luaur_vm::macros::lua_minstack::LUA_MINSTACK;
10use luaur_vm::macros::lua_pop::lua_pop;
11use luaur_vm::type_aliases::lua_state::lua_State;
12
13use crate::functions::complete_partial_matches::complete_partial_matches;
14use crate::functions::safe_get_table::safe_get_table;
15use crate::functions::try_replace_top_with_index::try_replace_top_with_index;
16
17pub unsafe fn complete_indexer(
18 l: *mut lua_State,
19 edit_buffer: &str,
20 add_completion_callback: &dyn Fn(&str, &str),
21) {
22 let mut lookup = edit_buffer;
23 let mut complete_only_functions = false;
24
25 lua_checkstack(l, LUA_MINSTACK);
26
27 lua_pushvalue(l, LUA_GLOBALSINDEX);
29
30 loop {
31 let sep = lookup.find(['.', ':']);
32 let prefix = match sep {
33 Some(s) => &lookup[..s],
34 None => lookup,
35 };
36
37 match sep {
38 None => {
39 complete_partial_matches(
40 l,
41 complete_only_functions,
42 edit_buffer,
43 prefix,
44 add_completion_callback,
45 );
46 break;
47 }
48 Some(sep) => {
49 lua_pushlstring(l, prefix.as_ptr() as *const c_char, prefix.len());
51 safe_get_table(l, -2);
52 lua_remove(l, -2);
53
54 if lua_istable!(l, -1) || try_replace_top_with_index(l) {
55 complete_only_functions = lookup.as_bytes()[sep] == b':';
56 lookup = &lookup[sep + 1..];
57 } else {
58 break;
60 }
61 }
62 }
63 }
64
65 lua_pop(l, 1);
66}