Skip to main content

luaur_repl_cli/functions/
complete_indexer.rs

1use 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    // Push the global variable table to begin the search
28    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                // find the key in the table
50                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                    // Unable to search for keys, so stop searching
59                    break;
60                }
61            }
62        }
63    }
64
65    lua_pop(l, 1);
66}