lyon 9 месяцев назад
Родитель
Сommit
26f435434c
7 измененных файлов с 196 добавлено и 5 удалено
  1. 2 1
      port/linux/.vscode/launch.json
  2. 1 1
      port/linux/test/module-test.cpp
  3. 177 1
      src/PikaObj.c
  4. 4 0
      src/PikaObj.h
  5. 3 1
      src/PikaParser.c
  6. 1 1
      src/PikaVersion.h
  7. 8 0
      src/pika_config_valid.h

+ 2 - 1
port/linux/.vscode/launch.json

@@ -14,7 +14,8 @@
                 // "--gtest_filter=module.REPL_big_script"
                 // "--gtest_filter=parser.input_issue1"
                 // "--gtest_filter=except.raise_type"
-                "--gtest_filter=module.REPL_big_script"
+                // "--gtest_filter=module.REPL_big_script"
+                "--gtest_filter=builtin.repl_mode"
             ],
             "stopAtEntry": false,
             "cwd": "${workspaceFolder}",

+ 1 - 1
port/linux/test/module-test.cpp

@@ -603,7 +603,7 @@ TEST(module, REPL_big_script) {
     fclose((FILE*)f_getchar_fp);
     /* collect */
     /* assert */
-    EXPECT_STREQ(log_buff[0],
+    EXPECT_STREQ(log_buff[3],
                  "\r\nError: line buff overflow, please use bigger "
                  "'PIKA_LINE_BUFF_SIZE'\r\n");
     /* deinit */

+ 177 - 1
src/PikaObj.c

@@ -1395,6 +1395,135 @@ typedef enum {
     __FILTER_SUCCESS_DROP_ALL_PEEKED
 } FilterReturn;
 
+typedef struct {
+    int count;
+    char** completions;
+} CompletionList;
+
+typedef struct {
+    char lineBuff[PIKA_LINE_BUFF_SIZE];
+    size_t line_position;
+    size_t line_curpos;
+    char prefix[32];
+} Shell;
+
+const char* dictionary[] = {
+    "import",        "PikaStdLib",  "from",        "high",
+    "low",           "Pin",         "value",       "def",
+    "PikaStdDevice", "setPin",      "enable",      "print",
+    "sleep_ms",      "read",        "setMode",     "setCallBack",
+    "setPull",       "as",          "MemChecker",  "max",
+    "min",           "float",       "int",         "str",
+    "list",          "dict",        "tuple",       "if",
+    "else",          "elif",        "for",         "while",
+    "break",         "continue",    "return",      "try",
+    "except",        "finally",     "with",        "open",
+    "write",         "append",      "close",       "True",
+    "False",         "None",        "self",        "class",
+    "init",          "len",         "range",       "input",
+    "output",        "config",      "setup",       "loop",
+    "GPIO",          "UART",        "I2C",         "SPI",
+    "ADC",           "PWM",         "digitalRead", "digitalWrite",
+    "analogRead",    "analogWrite", "time",        "datetime",
+    "random",        "OS",          "sys",         "math",
+    "json",          "readFile",    "writeFile",   ""};
+
+int dictSize = sizeof(dictionary) / sizeof(dictionary[0]);
+
+static CompletionList filtered_complete = {0, NULL};
+
+void shCompletePrint(CompletionList* completeList, const char* prefix) {
+    for (int i = 0; i < completeList->count; i++) {
+        printf("%s  ", completeList->completions[i]);
+    }
+}
+
+void getFilteredCompletions(const char* prefix,
+                            const char** dictionary,
+                            int dictSize,
+                            CompletionList* result) {
+    printf("\n");
+    if (result->completions != NULL) {
+        for (int i = 0; i < result->count; i++) {
+            free(result->completions[i]);
+        }
+        free(result->completions);
+        result->completions = NULL;
+    }
+    result->count = 0;
+    result->completions = (char**)malloc(dictSize * sizeof(char*));
+    if (result->completions == NULL) {
+        printf("Memory allocation failed\n");
+        return;
+    }
+
+    for (int i = 0; i < dictSize; i++) {
+        if (strncmp(dictionary[i], prefix, strlen(prefix)) == 0) {
+            result->completions[result->count] = strdup(dictionary[i]);
+            if (result->completions[result->count] == NULL) {
+                printf("Memory allocation failed for completion\n");
+                continue;
+            }
+            result->count++;
+        }
+    }
+
+    if (result->count == 0) {
+        printf("Warning: No matches found for '%s'\n", prefix);
+    }
+}
+
+/*free CompletionList*/
+void freeCompletionList(CompletionList* list) {
+    for (int i = 0; i < list->count; ++i) {
+        free(list->completions[i]);
+    }
+    free(list->completions);
+    list->completions = NULL;
+    list->count = 0;
+}
+
+void handleTabCompletion(ShellConfig* shell, char* prefix) {
+#if PIKA_TAB_ENABLE
+    if (shell->line_position > 0) {
+        if (prefix == NULL) {
+            printf("Memory allocation failed for prefix\n");
+            return;
+        }
+
+        // printf("\n================[fetch : %s ]=====================\n",
+        // prefix);
+        getFilteredCompletions(prefix, dictionary, dictSize,
+                               &filtered_complete);
+
+        if (filtered_complete.count == 1) {
+            char* last_space = strrchr(shell->lineBuff, ' ');
+            size_t start_pos = 0;
+
+            if (last_space != NULL) {
+                start_pos = last_space - shell->lineBuff + 1;
+            }
+
+            memset(shell->lineBuff + start_pos, 0,
+                   sizeof(shell->lineBuff) - start_pos);
+            strncpy(shell->lineBuff + start_pos,
+                    filtered_complete.completions[0],
+                    sizeof(shell->lineBuff) - start_pos - 1);
+            shell->lineBuff[sizeof(shell->lineBuff) - 1] = '\0';
+            shell->line_position = strlen(shell->lineBuff);
+            shell->line_curpos = shell->line_position;
+
+            printf(">>> %s", shell->lineBuff);
+        } else {
+            shCompletePrint(&filtered_complete, prefix);
+            printf("\n>>> %s", shell->lineBuff);
+        }
+        free(prefix);
+    }
+#endif
+    freeCompletionList(&filtered_complete);
+}
+
 pika_bool _filter_msg_hi_pika_handler(FilterItem* msg,
                                       PikaObj* self,
                                       ShellConfig* shell) {
@@ -1668,6 +1797,14 @@ enum shellCTRL _inner_do_obj_runChar(PikaObj* self,
                                      ShellConfig* shell) {
     char* input_line = NULL;
     enum shellCTRL ctrl = SHELL_CTRL_CONTINUE;
+    static uint64_t tick_start_block_input = 0;
+    if (tick_start_block_input != 0) {
+        if (pika_platform_get_tick() - tick_start_block_input < 5000) {
+            return SHELL_CTRL_CONTINUE;
+        } else {
+            tick_start_block_input = 0;
+        }
+    }
     if (inputChar == 0x7F) {
         inputChar = '\b';
     }
@@ -1682,6 +1819,34 @@ enum shellCTRL _inner_do_obj_runChar(PikaObj* self,
         ctrl = SHELL_CTRL_CONTINUE;
         goto __exit;
     }
+    if (inputChar == 0x09) {
+#if PIKA_TAB_ENABLE
+        if (shell->line_position > 0) {
+            // printf("Current cursor position: %zu, Line position: %zu\n",
+            // shell->line_curpos, shell->line_position);
+            char* shell_content = NULL;
+            char* last_space = strrchr(shell->lineBuff, ' ');
+
+            if (last_space == NULL) {
+                shell_content = strndup(shell->lineBuff, shell->line_position);
+            } else {
+                shell_content = strdup(last_space + 1);
+            }
+
+            if (shell_content == NULL) {
+                printf("Memory allocation failed for shell_content\n");
+                // return;
+            }
+
+            handleTabCompletion(shell, shell_content);
+            ctrl = SHELL_CTRL_CONTINUE;
+            // __clearBuff(shell);
+            goto __exit;
+        }
+#endif
+        ctrl = SHELL_CTRL_CONTINUE;
+        goto __exit;
+    }
     if (inputChar == 0x1b) {
         shell->stat = PIKA_SHELL_STATE_WAIT_SPEC_KEY;
         ctrl = SHELL_CTRL_CONTINUE;
@@ -1762,7 +1927,12 @@ enum shellCTRL _inner_do_obj_runChar(PikaObj* self,
             pika_platform_printf(
                 "\r\nError: line buff overflow, please use bigger "
                 "'PIKA_LINE_BUFF_SIZE'\r\n");
-            ctrl = SHELL_CTRL_EXIT;
+            ctrl = SHELL_CTRL_CONTINUE;
+            pika_platform_printf(
+                "Input is blocked for 5 seconds to protect the "
+                "kernel...\r\n");
+            tick_start_block_input = pika_platform_get_tick();
+            pika_platform_printf(">>> ");
             __clearBuff(shell);
             goto __exit;
         }
@@ -1981,6 +2151,12 @@ void _do_pikaScriptShell(PikaObj* self, ShellConfig* cfg) {
     while (1) {
         inputChar[1] = inputChar[0];
         inputChar[0] = _await_getchar(cfg->fn_getchar);
+#ifdef __linux
+        if (inputChar[0] == EOF) {
+            pika_platform_printf("\r\n");
+            return;
+        }
+#endif
 #if !PIKA_NANO_ENABLE
         /* run python script */
         if (inputChar[0] == '!' && inputChar[1] == '#') {

+ 4 - 0
src/PikaObj.h

@@ -498,6 +498,10 @@ char* shHistory_getPrev(ShellHistory* self);
 char* shHistory_getNext(ShellHistory* self);
 #endif
 
+#if PIKA_TAB_ENABLE
+void handleTabCompletion(ShellConfig* shell, char* prefix);
+#endif
+
 void _do_pikaScriptShell(PikaObj* self, ShellConfig* cfg);
 
 void _temp__do_pikaScriptShell(PikaObj* self, ShellConfig* cfg);

+ 3 - 1
src/PikaParser.c

@@ -2720,7 +2720,9 @@ static char* Suger_semicolon(Args* outbuffs, char* sLine) {
         sStmtItem = strsAppend(&buffs, sStmtItem, "\n");
         sStmtAfter = strsAppend(&buffs, sStmtAfter, sStmtItem);
     }
-    sStmtAfter[strGetSize(sStmtAfter) - 1] = '\0';
+    if (sStmtAfter[0] != '\0') {
+        sStmtAfter[strGetSize(sStmtAfter) - 1] = '\0';
+    }
     sStmtAfter = strsCopy(outbuffs, sStmtAfter);
     strsDeinit(&buffs);
     return sStmtAfter;

+ 1 - 1
src/PikaVersion.h

@@ -2,4 +2,4 @@
 #define PIKA_VERSION_MINOR 13
 #define PIKA_VERSION_MICRO 4
 
-#define PIKA_EDIT_TIME "2025/05/21 20:12:08"
+#define PIKA_EDIT_TIME "2025/06/02 13:54:26"

+ 8 - 0
src/pika_config_valid.h

@@ -93,6 +93,10 @@ extern "C" {
             #define PIKA_SHELL_HISTORY_ENABLE 0
         #endif
 
+        #ifndef PIKA_TAB_ENABLE
+            #define PIKA_TAB_ENABLE 0
+        #endif
+        
     #endif
 
     /* default optimize */
@@ -495,6 +499,10 @@ extern "C" {
         #define PIKA_SHELL_HISTORY_ENABLE 1
     #endif
 
+    #ifndef PIKA_TAB_ENABLE
+        #define PIKA_TAB_ENABLE 1
+    #endif
+
     #ifndef PIKA_SHELL_HISTORY_NUM
         #define PIKA_SHELL_HISTORY_NUM 5
     #endif