mirror of
https://gitee.com/Lyon1998/pikapython.git
synced 2025-01-29 17:22:56 +08:00
Merge branch 'master' of https://gitee.com/lyon1998/pikascript
This commit is contained in:
commit
e1013eb1d6
37
port/linux/.vscode/launch.json
vendored
37
port/linux/.vscode/launch.json
vendored
@ -11,40 +11,9 @@
|
||||
"program": "${workspaceFolder}/build/test/pikascript_test",
|
||||
// "program": "${workspaceFolder}/build/boot/demo06-pikamain/pikascript_demo06-pikamain",
|
||||
"args": [
|
||||
// "--gtest_filter=vm.keyword_2"
|
||||
// "--gtest_filter=compiler.find_break_point"
|
||||
// "--gtest_filter=pikaMain.REPL_pdb_set_break"
|
||||
// "--gtest_filter=vm.subsrc_import",
|
||||
// "--gtest_filter=vm.run_file_subsrc"
|
||||
// "--gtest_filter=vm.run_file"
|
||||
// "--gtest_filter=stddata.encode_decode"
|
||||
// "--gtest_filter=packtool.packfiles_txt"
|
||||
// "--gtest_filter=cmodule.class_attr_obj"
|
||||
// "--gtest_filter=except.try_import_except"
|
||||
// "--gtest_filter=vm.test_cmodule_import_as"
|
||||
// "--gtest_filter=vm.subsrc_import"
|
||||
// "--gtest_filter=event.event_thread3"
|
||||
// "--gtest_filter=parser.semicolon*"
|
||||
// "--gtest_filter=time*"
|
||||
// "--gtest_filter=flashdb.tsdb1"
|
||||
// "--gtest_filter=flashdb.base"
|
||||
// "--gtest_filter=jrpc.server"
|
||||
// "--gtest_filter=jrpc.client"
|
||||
// "--gtest_filter=jrpc.BlockingRequestBetweenTwoJRPC"
|
||||
// "--gtest_filter=jrpc.cmd"
|
||||
// "--gtest_filter=jrpc.exec_get_val"
|
||||
// "--gtest_filter=jrpc.exec_get_val"
|
||||
// "--gtest_filter=thread.issue1"
|
||||
// "--gtest_filter=except.isinstance"
|
||||
// "--gtest_filter=builtin.isinstance"
|
||||
// "--gtest_filter=bytes.bytes_split"
|
||||
// "--gtest_filter=except.dict"
|
||||
// "--gtest_filter=except.*"
|
||||
// "--gtest_filter=except.try1"
|
||||
// "--gtest_filter=except.for_loop"
|
||||
// "--gtest_filter=builtin.init_raise"
|
||||
// "--gtest_filter=builtin.strformat"
|
||||
// "--gtest_filter=except.typeerr"
|
||||
// "--gtest_filter=module.REPL_big_script"
|
||||
// "--gtest_filter=parser.input_issue1"
|
||||
"--gtest_filter=except.raise_type"
|
||||
],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
|
@ -504,9 +504,9 @@ char f_getchar(void) {
|
||||
if (n > 0) {
|
||||
return c;
|
||||
}
|
||||
pika_platform_printf("f_getchar error\r\n");
|
||||
pika_assert(0);
|
||||
return -1;
|
||||
// pika_platform_printf("f_getchar error\r\n");
|
||||
// pika_assert(0);
|
||||
return EOF;
|
||||
}
|
||||
void pikaScriptShell_withGetchar(PikaObj* self, sh_getchar getchar_fn);
|
||||
}
|
||||
@ -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 */
|
||||
|
@ -2753,6 +2753,27 @@ TEST(pikaMain, REPL_backspace) {
|
||||
EXPECT_EQ(pikaMemNow(), 0);
|
||||
}
|
||||
|
||||
#if PIKA_TAB_ENABLE
|
||||
TEST(pikaMain, REPL_tab_completion) {
|
||||
char lines[] = {'p', 'r', 0x09, '(', '\"',
|
||||
't', 'e', 's', 't', '\"', ')', '\r', '\n', 0x00};
|
||||
/* init */
|
||||
g_PikaMemInfo.heapUsedMax = 0;
|
||||
PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain);
|
||||
/* run */
|
||||
__platform_printf("BEGIN\r\n");
|
||||
for (size_t i = 0; i < strGetSize(lines); i++) {
|
||||
obj_runChar(pikaMain, lines[i]);
|
||||
}
|
||||
/* collect */
|
||||
/* assert */
|
||||
EXPECT_STREQ(log_buff[1], "test\r\n");
|
||||
/* deinit */
|
||||
obj_deinit(pikaMain);
|
||||
EXPECT_EQ(pikaMemNow(), 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(pikaMain, REPL_backspace_issue_1) {
|
||||
char* lines = "print('test'\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b'a'\r\n";
|
||||
/* init */
|
||||
|
163
src/PikaObj.c
163
src/PikaObj.c
@ -1395,6 +1395,121 @@ 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 +1783,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 +1805,33 @@ 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 +1912,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 +2136,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] == '#') {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user