98cf845071fc — Leonard Ritter 9 days ago
* REPL: console now autocompletes after dots if the left hand resolves to a valid scope or type
3 files changed, 39 insertions(+), 9 deletions(-)

M include/scopes/scopes.h
M lib/scopes/console.sc
M src/globals.cpp
M include/scopes/scopes.h +2 -1
@@ 292,7 292,8 @@ SCOPES_LIBEXPORT void sc_prompt_save_his
 SCOPES_LIBEXPORT void sc_prompt_load_history(const sc_string_t *path);
 SCOPES_LIBEXPORT void sc_prompt_set_autocomplete_handler(sc_autocomplete_func_t func);
 SCOPES_LIBEXPORT void sc_prompt_add_completion(void *ctx, const char *text);
-SCOPES_LIBEXPORT void sc_prompt_add_completion_from_scope(void *ctx, const char *searchtext, const sc_scope_t* scope);
+SCOPES_LIBEXPORT void sc_prompt_add_completion_from_scope(void *ctx,
+    const char *searchtext, int offset, const sc_scope_t* scope);
 
 SCOPES_LIBEXPORT const sc_string_t *sc_format_message(const sc_anchor_t *anchor, const sc_string_t *message);
 SCOPES_LIBEXPORT void sc_write(const sc_string_t *value);

          
M lib/scopes/console.sc +28 -3
@@ 118,15 118,40 @@ case (global-scope, show-logo : bool = f
                 typedef (do "Enter 'exit;' or Ctrl+D to exit")
                     inline __typecall () (if true (exit 0))
 
+    fn autocomplete-symbol (text ctx scope)
+        loop (i0 i scope = 0 0 scope)
+            let c = (text @ i)
+            if (c == 0:i8)
+            elseif ((c == 46:i8) & (i != i0))
+                let key =
+                    Symbol (string (& (text @ i0)) (i - i0))
+                let subkey = ('@ scope key)
+                let i = (i + 1)
+                if ('constant? subkey)
+                    let T = ('typeof subkey)
+                    if (T == Scope)
+                        repeat i i (subkey as Scope)
+                    elseif (T == type)
+                        repeat i i
+                            fold (scope = (Scope)) for k v in ('symbols (subkey as type))
+                                'bind scope k v
+
+            else
+                repeat i0 (i + 1) scope
+            sc_prompt_add_completion_from_scope ctx text i0 scope
+            return;
+
     global autocomplete-scope : Scope
     fn autocomplete (text ctx)
         # Tab on an empty string gives an indentation
-            TODO: is this really necessary anymore?
         if ((@ text) == 0)
             sc_prompt_add_completion ctx "    "
             return;
-        if ((deref autocomplete-scope) != null)
-            sc_prompt_add_completion_from_scope ctx text autocomplete-scope
+        let scope = (deref autocomplete-scope)
+        if (scope != null)
+            try
+                autocomplete-symbol text ctx scope
+            else;
         ;
 
     loop (preload cmdlist counter eval-scope = "" "" 0 eval-scope)

          
M src/globals.cpp +9 -5
@@ 379,13 379,17 @@ void sc_prompt_add_completion(void *ctx,
     linenoiseAddCompletion((linenoiseCompletions *)ctx, text);
 }
 
-void sc_prompt_add_completion_from_scope(void *ctx, const char *searchtext, const sc_scope_t* scope) {
+void sc_prompt_add_completion_from_scope(void *ctx, const char *searchtext, int offset, const sc_scope_t* scope) {
     using namespace scopes;
-    const String* name = String::from_cstr(searchtext);
+    const String* name = String::from_cstr(searchtext + offset);
     Symbol sym(name);
     scope = scope ? scope : globals;
-    for (const auto& m : scope->find_elongations(sym))
-        linenoiseAddCompletion((linenoiseCompletions *)ctx, m.name()->data);
+
+    for (const auto& m : scope->find_elongations(sym)) {
+        auto result =
+            std::string(searchtext, offset) + std::string(m.name()->data);
+        linenoiseAddCompletion((linenoiseCompletions *)ctx, result.c_str());
+    }
 }
 
 const sc_string_t *sc_format_message(const sc_anchor_t *anchor, const sc_string_t *message) {

          
@@ 2332,7 2336,7 @@ void init_globals(int argc, char *argv[]
     DEFINE_EXTERN_C_FUNCTION(sc_prompt_save_history, _void, TYPE_String);
     DEFINE_EXTERN_C_FUNCTION(sc_prompt_load_history, _void, TYPE_String);
     DEFINE_EXTERN_C_FUNCTION(sc_prompt_add_completion, _void, voidstar, rawstring);
-    DEFINE_EXTERN_C_FUNCTION(sc_prompt_add_completion_from_scope, _void, voidstar, rawstring, TYPE_Scope);
+    DEFINE_EXTERN_C_FUNCTION(sc_prompt_add_completion_from_scope, _void, voidstar, rawstring, TYPE_I32, TYPE_Scope);
 
     DEFINE_EXTERN_C_FUNCTION(sc_default_styler, TYPE_String, TYPE_Symbol, TYPE_String);
     DEFINE_EXTERN_C_FUNCTION(sc_format_message, TYPE_String, TYPE_Anchor, TYPE_String);