From d8cc74fef7817a32f33dea961c410e2c203228ca Mon Sep 17 00:00:00 2001 From: min0911Y <1474635462@qq.com> Date: Sat, 14 Dec 2024 17:50:45 +0800 Subject: [PATCH] =?UTF-8?q?pl=5Freadline=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/pl_readline.h | 77 +++--- src/kernel/task/shell.c | 2 +- src/pl_readline/plreadln.c | 335 +++++++++++++----------- src/pl_readline/plreadln_intellisense.c | 185 ++++++++----- src/pl_readline/plreadln_wordmk.c | 26 +- 5 files changed, 349 insertions(+), 276 deletions(-) diff --git a/include/pl_readline.h b/include/pl_readline.h index 16bc69af..a0629d42 100755 --- a/include/pl_readline.h +++ b/include/pl_readline.h @@ -1,75 +1,76 @@ #pragma once #include #include - #define PL_READLINE_KEY_UP 0xff00 #define PL_READLINE_KEY_DOWN 0xff01 #define PL_READLINE_KEY_LEFT 0xff02 #define PL_READLINE_KEY_RIGHT 0xff03 +#define PL_READLINE_KEY_HOME 0xff04 +#define PL_READLINE_KEY_END 0xff05 +#define PL_READLINE_KEY_PAGE_UP 0xff06 +#define PL_READLINE_KEY_PAGE_DOWN 0xff07 #define PL_READLINE_KEY_ENTER '\n' #define PL_READLINE_KEY_TAB '\t' #define PL_READLINE_KEY_CTRL_A 0x01 #define PL_READLINE_KEY_CTRL_C 0x03 #define PL_READLINE_KEY_BACKSPACE '\b' -#define _SELF pl_readline_t self -#define PL_READLINE_SUCCESS 0 -#define PL_READLINE_FAILED -1 -#define PL_READLINE_NOT_FINISHED 1 + +#define _self pl_readline_t self +#define PL_READLINE_SUCCESS 0 +#define PL_READLINE_FAILED -1 +#define PL_READLINE_NOT_FINISHED 1 +#define PL_READLINE_DEFAULT_BUFFER_LEN 32 typedef struct pl_readline_word { char *word; // 词组 /** - 如果first为true, - 这个word必须在第一个参数的位置的时候才能得到补全 - 如abc 则必须输入"ab"然后按tab,才会有可能有"abc" - 如果是“qwe ab”则不会补全"qwe abc",除非first为false. - */ + 如果first为true, + 这个word必须在第一个参数的位置的时候才能得到补全 + 如abc 则必须输入"ab"然后按tab,才会有可能有"abc" + 如果是“qwe ab”则不会补全"qwe abc",除非first为false. + */ bool first; - - char sep; // 分隔符 + char sep; // 分隔符 } pl_readline_word; typedef struct pl_readline_words { - int len; // 词组数量 - int max_len; // 词组最大数量 + size_t len; // 词组数量 + size_t max_len; // 词组最大数量 pl_readline_word *words; // 词组列表 } *pl_readline_words_t; typedef struct pl_readline { - int (*pl_readline_hal_getch)(); // 输入函数 + int (*pl_readline_hal_getch)(void); // 输入函数 void (*pl_readline_hal_putch)(int ch); // 输出函数 - void (*pl_readline_hal_flush)(); // 刷新函数 + void (*pl_readline_hal_flush)(void); // 刷新函数 void (*pl_readline_get_words)(char *buf, pl_readline_words_t words); // 获取词组列表 - list_t history; // 历史记录列表 -} *pl_readline_t; -typedef struct pl_readline_runtime { - char *buffer; // 输入缓冲区 - int p; // 输入缓冲区指针 - int length; // 输入缓冲区长度(已经输入的字符数) + char *buffer; // 输入缓冲区 + char *input_buf; // 输入缓冲区(补全的前缀) + size_t ptr; // 输入缓冲区指针 + size_t input_ptr; // 输入缓冲区(补全的前缀)指针 + size_t maxlen; // 缓冲区最大长度 + size_t length; // 输入缓冲区长度(已经输入的字符数) + list_t history; // 历史记录列表 int history_idx; // 历史记录指针 char *prompt; // 提示符 - size_t maxlen; // 缓冲区最大长度 - char *input_buf; // 输入缓冲区(补全的前缀) - int input_buf_ptr; // 输入缓冲区(补全的前缀)指针 bool intellisense_mode; // 智能补全模式 char *intellisense_word; // 智能补全词组 -} pl_readline_runtime; +} *pl_readline_t; -pl_readline_words_t pl_readline_word_maker_init(); -pl_readline_t pl_readline_init(int (*pl_readline_hal_getch)(), +pl_readline_words_t pl_readline_word_maker_init(void); +pl_readline_t pl_readline_init(int (*pl_readline_hal_getch)(void), void (*pl_readline_hal_putch)(int ch), - void (*pl_readline_hal_flush)(), + void (*pl_readline_hal_flush)(void), void (*pl_readline_get_words)(char *buf, pl_readline_words_t words)); -int pl_readline(_SELF, char *prompt, char *buffer, size_t maxlen); -pl_readline_word pl_readline_intellisense(_SELF, pl_readline_runtime *rt, - pl_readline_words_t words); -void pl_readline_insert_char_and_view(_SELF, char ch, pl_readline_runtime *rt); +const char *pl_readline(_self, char *prompt); +pl_readline_word pl_readline_intellisense(_self, pl_readline_words_t words); +void pl_readline_insert_char_and_view(_self, char ch); void pl_readline_insert_char(char *str, char ch, int idx); int pl_readline_word_maker_add(char *word, pl_readline_words_t words, bool is_first, char sep); -void pl_readline_print(_SELF, char *str); -void pl_readline_intellisense_insert(_SELF, pl_readline_runtime *rt, pl_readline_word words); +void pl_readline_print(_self, char *str); +void pl_readline_intellisense_insert(_self, pl_readline_word words); void pl_readline_word_maker_destroy(pl_readline_words_t words); -void pl_readline_next_line(_SELF, pl_readline_runtime *rt); -int pl_readline_handle_key(_SELF, int ch, pl_readline_runtime *rt); -void pl_readline_uninit(_SELF); \ No newline at end of file +void pl_readline_next_line(_self); +int pl_readline_handle_key(_self, int ch); +void pl_readline_uninit(_self); diff --git a/src/kernel/task/shell.c b/src/kernel/task/shell.c index 95ffbc9f..429cb8bc 100644 --- a/src/kernel/task/shell.c +++ b/src/kernel/task/shell.c @@ -252,7 +252,7 @@ void shell() { char prompt[256]; while (true) { sprintf(prompt, "%s# ", path); - pl_readline(n, prompt, line, 255); + cstr line = pl_readline(n, prompt); shell_exec(path, line); } } diff --git a/src/pl_readline/plreadln.c b/src/pl_readline/plreadln.c index 57a52fec..ed6a4a3d 100755 --- a/src/pl_readline/plreadln.c +++ b/src/pl_readline/plreadln.c @@ -9,23 +9,24 @@ // // plreadln.c: 实现pl_readline的核心功能 - #include -int pl_readline_add_history(_SELF, char *line) { +int pl_readline_add_history(_self, char *line) { list_prepend(self->history, strdup(line)); return PL_READLINE_SUCCESS; } -int pl_readline_remove_history(_SELF) { - auto list = list_head(self->history); - if (list) list_delete_node_with(self->history, list, free); +int pl_readline_modify_history(_self) { + list_t node = list_nth(self->history, self->history_idx); + // 当前历史记录肯定不为空,如果为空炸了算了 + free(node->data); + node->data = strdup(self->buffer); return PL_READLINE_SUCCESS; } pl_readline_t -pl_readline_init(int (*pl_readline_hal_getch)(), void (*pl_readline_hal_putch)(int ch), - void (*pl_readline_hal_flush)(), +pl_readline_init(int (*pl_readline_hal_getch)(void), void (*pl_readline_hal_putch)(int ch), + void (*pl_readline_hal_flush)(void), void (*pl_readline_get_words)(char *buf, pl_readline_words_t words)) { pl_readline_t plreadln = malloc(sizeof(struct pl_readline)); if (!plreadln) return NULL; @@ -36,91 +37,102 @@ pl_readline_init(int (*pl_readline_hal_getch)(), void (*pl_readline_hal_putch)(i plreadln->pl_readline_get_words = pl_readline_get_words; // 设置history链表 plreadln->history = NULL; + plreadln->maxlen = PL_READLINE_DEFAULT_BUFFER_LEN; + // 设置输入缓冲区 + plreadln->buffer = malloc(plreadln->maxlen); + plreadln->input_buf = malloc(plreadln->maxlen); + if (!plreadln->buffer || !plreadln->input_buf) { + pl_readline_uninit(plreadln); + return NULL; + } pl_readline_add_history(plreadln, ""); return plreadln; } -void pl_readline_uninit(_SELF) { + +void pl_readline_uninit(_self) { list_free_with(self->history, free); + free(self->buffer); + free(self->input_buf); free(self); } + void pl_readline_insert_char(char *str, char ch, int idx) { int len = strlen(str); if (len) memmove(str + idx + 1, str + idx, len - idx); str[idx] = ch; } + static void pl_readline_delete_char(char *str, int idx) { int len = strlen(str); if (len) memmove(str + idx, str + idx + 1, len - idx); str[len] = '\0'; } -void pl_readline_print(_SELF, char *str) { +void pl_readline_print(_self, char *str) { while (*str) { self->pl_readline_hal_putch(*str++); } } -static void pl_readline_reset(_SELF, int p, int len) { + +static void pl_readline_reset(_self, int p, int len) { char buf[255] = {0}; if (p) { - sprintf(buf, "\e[%dD", p); + sprintf(buf, "\033[%dD", p); pl_readline_print(self, buf); } if (len) { for (int i = 0; i < len; i++) { self->pl_readline_hal_putch(' '); } - sprintf(buf, "\e[%dD", len); + sprintf(buf, "\033[%dD", len); pl_readline_print(self, buf); } } -static void pl_readline_to_the_end(_SELF, int n) { + +static void pl_readline_to_the_end(_self, int n) { char buf[255] = {0}; - sprintf(buf, "\e[%dC", n); + sprintf(buf, "\033[%dC", n); pl_readline_print(self, buf); } -// 处理向上向下键 -static void pl_readline_handle_key_down_up(_SELF, pl_readline_runtime *rt, int n) { - if (rt->history_idx < 0) return; - list_t node = list_nth(self->history, rt->history_idx); // 获取历史记录 - if (!node) { - rt->history_idx += n; // 超出历史记录的范围,回退到上一个记录 - return; - } - pl_readline_reset(self, rt->p, rt->length); // 重置光标和输入的字符 - self->pl_readline_hal_flush(); // 刷新输出缓冲区,在Linux下需要,否则会导致输入不显示 - rt->p = 0; // 光标移动到最左边 - rt->length = 0; // 清空缓冲区长度 - memset(rt->buffer, 0, rt->maxlen); // 清空缓冲区 - strcpy(rt->buffer, node->data); - pl_readline_print(self, rt->buffer); // 打印历史记录 - rt->length = strlen(rt->buffer); // 更新缓冲区长度 - rt->p = rt->length; +// 处理向上向下键(移动到第n个历史) +static bool pl_readline_handle_history(_self, int n) { + list_t node = list_nth(self->history, n); // 获取历史记录 + if (!node) return false; + pl_readline_reset(self, self->ptr, self->length); // 重置光标和输入的字符 + self->pl_readline_hal_flush(); // 刷新输出缓冲区,在Linux下需要,否则会导致输入不显示 + self->ptr = 0; // 光标移动到最左边 + self->length = 0; // 清空缓冲区长度 + memset(self->buffer, 0, self->maxlen); // 清空缓冲区 + strcpy(self->buffer, node->data); + pl_readline_print(self, self->buffer); // 打印历史记录 + self->length = strlen(self->buffer); // 更新缓冲区长度 + self->ptr = self->length; - memset(rt->input_buf, 0, rt->maxlen); // 清空输入缓冲区 - rt->input_buf_ptr = 0; // 输入缓冲区指针置0 - // strcpy(rt->input_buf, node->data); // 复制历史记录到输入缓冲区 - char *p = node->data; + memset(self->input_buf, 0, self->maxlen); // 清空输入缓冲区 + self->input_ptr = 0; // 输入缓冲区指针置0 + char *p = node->data; while (*p) { if (*p == ' ') { - rt->input_buf_ptr = 0; + self->input_ptr = 0; p++; continue; } - rt->input_buf[rt->input_buf_ptr++] = *p++; + self->input_buf[self->input_ptr++] = *p++; } - rt->input_buf[rt->input_buf_ptr] = '\0'; - rt->input_buf_ptr = strlen(rt->input_buf); // 更新输入缓冲区指针 + self->input_buf[self->input_ptr] = '\0'; + self->input_ptr = strlen(self->input_buf); // 更新输入缓冲区指针 + return true; } -void pl_readline_insert_char_and_view(_SELF, char ch, pl_readline_runtime *rt) { - pl_readline_insert_char(rt->buffer, ch, rt->p++); - rt->length++; - int n = rt->length - rt->p; +void pl_readline_insert_char_and_view(_self, char ch) { + pl_readline_insert_char(self->buffer, ch, self->ptr++); + self->length++; + int n = self->length - self->ptr; if (n) { char buf[255] = {0}; - pl_readline_print(self, rt->buffer + rt->p - 1); - sprintf(buf, "\e[%dD", n); + pl_readline_print(self, self->buffer + self->ptr - 1); + sprintf(buf, "\033[%dD", n); pl_readline_print(self, buf); } else { @@ -128,166 +140,157 @@ void pl_readline_insert_char_and_view(_SELF, char ch, pl_readline_runtime *rt) { } } -void pl_readline_next_line(_SELF, pl_readline_runtime *rt) { - int n = rt->length - rt->p; +void pl_readline_next_line(_self) { + int n = self->length - self->ptr; char buf[255] = {0}; if (!n) { pl_readline_print(self, "\n"); return; } - sprintf(buf, "\e[%dC", n); // 光标移动到最右边 + sprintf(buf, "\033[%dC", n); // 光标移动到最右边 pl_readline_print(self, buf); pl_readline_print(self, "\n"); } // 处理输入的字符 -int pl_readline_handle_key(_SELF, int ch, pl_readline_runtime *rt) { +int pl_readline_handle_key(_self, int ch) { if (ch != PL_READLINE_KEY_TAB) { - rt->intellisense_mode = false; - if (rt->intellisense_word) { - free(rt->intellisense_word); - rt->intellisense_word = NULL; + self->intellisense_mode = false; + if (self->intellisense_word) { + free(self->intellisense_word); + self->intellisense_word = NULL; } } - if (rt->length >= rt->maxlen) { // 输入的字符数超过最大长度 - pl_readline_to_the_end(self, rt->length - rt->p); - self->pl_readline_hal_putch('\n'); - rt->buffer[rt->length] = '\0'; - pl_readline_add_history(self, rt->buffer); - return PL_READLINE_SUCCESS; + if (self->length >= self->maxlen) { + self->maxlen *= 2; + self->buffer = realloc(self->buffer, self->maxlen); + self->input_buf = realloc(self->input_buf, self->maxlen); + if (!self->buffer) return PL_READLINE_FAILED; } switch (ch) { case PL_READLINE_KEY_DOWN: - rt->history_idx--; - // n = 1是为了的失败的时候还原 - pl_readline_handle_key_down_up(self, rt, 1); + pl_readline_modify_history(self); + if (pl_readline_handle_history(self, self->history_idx - 1)) self->history_idx--; break; case PL_READLINE_KEY_UP: { - if (rt->history_idx == 0) { - pl_readline_remove_history(self); - pl_readline_add_history(self, rt->buffer); - } - rt->history_idx++; - // n = -1是为了的失败的时候还原 - pl_readline_handle_key_down_up(self, rt, -1); + pl_readline_modify_history(self); + if (pl_readline_handle_history(self, self->history_idx + 1)) self->history_idx++; break; } case PL_READLINE_KEY_LEFT: - if (!rt->p) // 光标在最左边 + if (!self->ptr) // 光标在最左边 return PL_READLINE_NOT_FINISHED; - rt->p--; - pl_readline_print(self, "\e[D"); - if (rt->buffer[rt->p] == ' ') { - memset(rt->input_buf, 0, rt->maxlen); + self->ptr--; + pl_readline_print(self, "\033[D"); + if (self->buffer[self->ptr] == ' ') { + memset(self->input_buf, 0, self->maxlen); // 光标移动到前一个空格 - int i = rt->p; - while (i && rt->buffer[i - 1] != ' ') { + size_t i = self->ptr; + while (i && self->buffer[i - 1] != ' ') { i--; } - rt->input_buf_ptr = 0; - // 从i开始复制到rt->input_buf,直到遇到空格 - int len = rt->p - i; - while (i < rt->p && rt->buffer[i] != ' ') { - rt->input_buf[rt->input_buf_ptr++] = rt->buffer[i]; + self->input_ptr = 0; + // 从i开始复制到self->input_buf,直到遇到空格 + while (i < self->ptr && self->buffer[i] != ' ') { + self->input_buf[self->input_ptr++] = self->buffer[i]; i++; } // 字符串结束符号 - rt->input_buf[rt->input_buf_ptr] = '\0'; + self->input_buf[self->input_ptr] = '\0'; } else { - rt->input_buf_ptr--; + self->input_ptr--; } break; case PL_READLINE_KEY_RIGHT: - if (rt->p == rt->length) // 光标在最右边 + if (self->ptr == self->length) // 光标在最右边 return PL_READLINE_NOT_FINISHED; - rt->p++; - pl_readline_print(self, "\e[C"); - if (rt->buffer[rt->p - 1] == ' ') { - memset(rt->input_buf, 0, rt->maxlen); + self->ptr++; + pl_readline_print(self, "\033[C"); + if (self->buffer[self->ptr - 1] == ' ') { + memset(self->input_buf, 0, self->maxlen); // 光标移动到前一个空格 - int i = rt->p; - int j = i; - while (i < rt->length && rt->buffer[i + 1] != ' ') { + size_t i = self->ptr; + size_t j = i; + while (i < self->length && self->buffer[i + 1] != ' ') { i++; } - rt->input_buf_ptr = 0; - // 从i开始复制到rt->input_buf,直到遇到空格 - int len = i - j; - while (j <= i && rt->buffer[i] != ' ') { - rt->input_buf[rt->input_buf_ptr++] = rt->buffer[j]; + self->input_ptr = 0; + // 从i开始复制到self->input_buf,直到遇到空格 + while (j <= i && self->buffer[i] != ' ') { + self->input_buf[self->input_ptr++] = self->buffer[j]; j++; } // 字符串结束符号 - rt->input_buf[rt->input_buf_ptr] = '\0'; - rt->input_buf_ptr = 0; + self->input_buf[self->input_ptr] = '\0'; + self->input_ptr = 0; } else { - rt->input_buf_ptr++; + self->input_ptr++; } break; case PL_READLINE_KEY_BACKSPACE: - if (!rt->p) // 光标在最左边 + if (!self->ptr) // 光标在最左边 return PL_READLINE_NOT_FINISHED; - --rt->p; - if (rt->buffer[rt->p] == ' ') { - memset(rt->input_buf, 0, rt->maxlen); + --self->ptr; + if (self->buffer[self->ptr] == ' ') { + memset(self->input_buf, 0, self->maxlen); // 光标移动到前一个空格 - int i = rt->p; - while (i && rt->buffer[i - 1] != ' ') { + size_t i = self->ptr; + while (i && self->buffer[i - 1] != ' ') { i--; } - rt->input_buf_ptr = 0; - // 从i开始复制到rt->input_buf,直到遇到空格 - while (i < rt->p && rt->buffer[i] != ' ') { - rt->input_buf[rt->input_buf_ptr++] = rt->buffer[i]; + self->input_ptr = 0; + // 从i开始复制到self->input_buf,直到遇到空格 + while (i < self->ptr && self->buffer[i] != ' ') { + self->input_buf[self->input_ptr++] = self->buffer[i]; i++; } // 字符串结束符号 - rt->input_buf[rt->input_buf_ptr] = '\0'; + self->input_buf[self->input_ptr] = '\0'; } else { - if (rt->input_buf_ptr) pl_readline_delete_char(rt->input_buf, --rt->input_buf_ptr); + if (self->input_ptr) pl_readline_delete_char(self->input_buf, --self->input_ptr); } - pl_readline_delete_char(rt->buffer, rt->p); + pl_readline_delete_char(self->buffer, self->ptr); - rt->length--; + self->length--; - int n = rt->length - rt->p; + int n = self->length - self->ptr; if (n) { char buf[255] = {0}; - sprintf(buf, "\e[%dC\e[D ", n); + sprintf(buf, "\033[%dC\033[D ", n); pl_readline_print(self, buf); - sprintf(buf, "\e[%dD", n); + sprintf(buf, "\033[%dD", n); pl_readline_print(self, buf); - pl_readline_print(self, "\e[D"); - pl_readline_print(self, rt->buffer + rt->p); + pl_readline_print(self, "\033[D"); + pl_readline_print(self, self->buffer + self->ptr); pl_readline_print(self, buf); } else { - pl_readline_print(self, "\e[D \e[D"); + pl_readline_print(self, "\033[D \033[D"); } break; case PL_READLINE_KEY_ENTER: - pl_readline_to_the_end(self, rt->length - rt->p); + pl_readline_to_the_end(self, self->length - self->ptr); self->pl_readline_hal_putch('\n'); - rt->buffer[rt->length] = '\0'; - pl_readline_remove_history(self); - pl_readline_add_history(self, rt->buffer); - pl_readline_add_history(self, ""); + self->buffer[self->length] = '\0'; + self->history_idx = 0; + pl_readline_modify_history(self); + if (self->buffer[0] != '\0') { pl_readline_add_history(self, ""); } return PL_READLINE_SUCCESS; case PL_READLINE_KEY_TAB: { // 自动补全 pl_readline_words_t words = pl_readline_word_maker_init(); - pl_readline_word word_seletion = pl_readline_intellisense(self, rt, words); + pl_readline_word word_seletion = pl_readline_intellisense(self, words); if (word_seletion.word) { - pl_readline_intellisense_insert(self, rt, word_seletion); + pl_readline_intellisense_insert(self, word_seletion); self->pl_readline_hal_flush(); } else if (word_seletion.first) { pl_readline_print(self, "\n"); - pl_readline_print(self, rt->prompt); - pl_readline_print(self, rt->buffer); - int n = rt->length - rt->p; + pl_readline_print(self, self->prompt); + pl_readline_print(self, self->buffer); + int n = self->length - self->ptr; char buf[255] = {0}; if (n) { - sprintf(buf, "\e[%dD", n); + sprintf(buf, "\033[%dD", n); pl_readline_print(self, buf); } self->pl_readline_hal_flush(); @@ -295,49 +298,75 @@ int pl_readline_handle_key(_SELF, int ch, pl_readline_runtime *rt) { break; } case PL_READLINE_KEY_CTRL_A: - pl_readline_reset(self, rt->p, 0); - rt->p = 0; + case PL_READLINE_KEY_HOME: + pl_readline_reset(self, self->ptr, 0); + self->ptr = 0; + break; + case PL_READLINE_KEY_END: { + size_t diff = self->length - self->ptr; + if (diff) { + pl_readline_to_the_end(self, self->length - self->ptr); + self->ptr = self->length; + } + break; + } + case PL_READLINE_KEY_PAGE_UP: { + size_t len = list_length(self->history); + pl_readline_modify_history(self); + pl_readline_handle_history(self, len - 1); + self->history_idx = len - 1; + break; + } + case PL_READLINE_KEY_PAGE_DOWN: + pl_readline_modify_history(self); + pl_readline_handle_history(self, 0); + self->history_idx = 0; break; case PL_READLINE_KEY_CTRL_C: - rt->buffer[0] = '\0'; + self->buffer[0] = '\0'; pl_readline_print(self, "^C\n"); return PL_READLINE_SUCCESS; case ' ': { - memset(rt->input_buf, 0, rt->maxlen); - rt->input_buf_ptr = 0; + memset(self->input_buf, 0, self->maxlen); + self->input_ptr = 0; goto handle; } default: { - pl_readline_insert_char(rt->input_buf, ch, rt->input_buf_ptr++); + pl_readline_insert_char(self->input_buf, ch, self->input_ptr++); handle: - pl_readline_insert_char_and_view(self, ch, rt); + pl_readline_insert_char_and_view(self, ch); break; } } return PL_READLINE_NOT_FINISHED; } + // 主体函数 -int pl_readline(_SELF, char *prompt, char *buffer, size_t maxlen) { - // 为了实现自动补全,需要将输入的字符保存到缓冲区中 - char *input_buf = malloc(maxlen + 1); - memset(input_buf, 0, maxlen + 1); - int input_buf_ptr = 0; - assert(input_buf); - pl_readline_runtime rt = {buffer, 0, 0, 0, prompt, maxlen, input_buf, 0, false, NULL}; +const char *pl_readline(_self, char *prompt) { + // 清空运行时状态 + memset(self->buffer, 0, self->maxlen); + memset(self->input_buf, 0, self->maxlen); + self->input_ptr = 0; + self->ptr = 0; + self->length = 0; + self->history_idx = 0; + self->prompt = prompt; + self->intellisense_mode = false; + self->intellisense_word = NULL; - // 清空缓冲区 - memset(input_buf, 0, maxlen + 1); - memset(buffer, 0, maxlen); // 打印提示符 pl_readline_print(self, prompt); - self->pl_readline_hal_flush(); // 刷新输出缓冲区,在Linux下需要,否则会导致输入不显示 + // 刷新输出缓冲区,在Linux下需要,否则会导致输入不显示 + self->pl_readline_hal_flush(); + // 循环读取输入 while (true) { int ch = self->pl_readline_hal_getch(); // 读取输入 - int status = pl_readline_handle_key(self, ch, &rt); + int status = pl_readline_handle_key(self, ch); if (status == PL_READLINE_SUCCESS) { break; } } - free(input_buf); - if (rt.intellisense_word) { free(rt.intellisense_word); } - return PL_READLINE_SUCCESS; -} \ No newline at end of file + + if (self->intellisense_word) { free(self->intellisense_word); } + + return self->buffer; +} diff --git a/src/pl_readline/plreadln_intellisense.c b/src/pl_readline/plreadln_intellisense.c index 20def51d..2e2ed336 100755 --- a/src/pl_readline/plreadln_intellisense.c +++ b/src/pl_readline/plreadln_intellisense.c @@ -1,25 +1,41 @@ +// +// This file is part of pl_readline. +// pl_readline is free software: you can redistribute it and/or modify +// it under the terms of MIT license. +// See file LICENSE or https://opensource.org/licenses/MIT for full license +// details. +// +// Copyright (c) 2024 min0911_ https://github.com/min0911Y +// + +// pl_readline_intellisense.c : Intellisense feature for pl_readline. + #include -static void insert_char(_SELF, char ch, pl_readline_runtime *rt) { - pl_readline_insert_char_and_view(self, ch, rt); - pl_readline_insert_char(rt->input_buf, ch, rt->input_buf_ptr++); +// 向输入缓冲区插入字符 +static void insert_char(_self, char ch) { + pl_readline_insert_char_and_view(self, ch); + pl_readline_insert_char(self->input_buf, ch, self->input_ptr++); } -static void insert_string(_SELF, char *str, pl_readline_runtime *rt) { +// 向输入缓冲区插入字符串 +static void insert_string(_self, char *str) { while (*str) { - insert_char(self, *str++, rt); + insert_char(self, *str++); } } -static char *get_the_same_prefix_in_words(_SELF, pl_readline_words_t words) { - char *prefix = NULL; - int len = 0; - for (int i = 0; i < words->len; i++) { +// 找到相同前缀的单词 +// 使用此函数需要记得free返回的指针 +static char *get_same_prefix(pl_readline_words_t words) { + char *prefix = NULL; + size_t len = 0; + for (size_t i = 0; i < words->len; i++) { if (prefix == NULL) { prefix = strdup(words->words[i].word); len = strlen(prefix); } else { - int j = 0; + size_t j = 0; while (j < len && j < strlen(words->words[i].word) && prefix[j] == words->words[i].word[j]) { j++; } @@ -33,100 +49,125 @@ static char *get_the_same_prefix_in_words(_SELF, pl_readline_words_t words) { return prefix; } -static bool check_if_is_first(_SELF, pl_readline_runtime *rt) { - int p = rt->p; +// 检查是否是第一个单词 +static bool check_is_first(_self) { + int p = self->ptr; while (p) { - if (rt->buffer[--p] == ' ') { return false; } + if (self->buffer[--p] == ' ') { // 看一下前面有没有空格 + return false; // 不是第一个单词 + } } return true; } -pl_readline_word pl_readline_intellisense(_SELF, pl_readline_runtime *rt, - pl_readline_words_t words) { - char *buf; - char *the_word = NULL; - int times = 0; - int idx; - int flag = 0; - bool is_first = check_if_is_first(self, rt); - if (rt->intellisense_mode == false) { - buf = strdup(rt->input_buf); - rt->intellisense_word = buf; - buf[rt->input_buf_ptr] = '\0'; - idx = rt->input_buf_ptr; - } else { - assert(rt->intellisense_word != NULL); - buf = rt->intellisense_word; - idx = strlen(buf); +// 自动补全 +pl_readline_word pl_readline_intellisense(_self, pl_readline_words_t words) { + char *buf; // 用户输入的缓冲区 + int times = 0; // 输出补全词库的次数 + size_t idx; // self->intellisense_word的索引 + int flag = 0; // 用户输入的词存不存在 + bool is_first = check_is_first(self); // 是否是第一个单词 + if (self->intellisense_mode == false) { // 如果是这个模式,则我们需要插入些东西 + buf = strdup(self->input_buf); // 保存一下 + // self->intellisense_word将会在后面被释放,不用担心内存泄漏 + self->intellisense_word = buf; + buf[self->input_ptr] = '\0'; // 加上结束符 + idx = self->input_ptr; // 索引 + } else { // 列出模式 + assert(self->intellisense_word != NULL); // 这个指针一定不为空 + buf = self->intellisense_word; // 重定向buf + idx = strlen(buf); // 设置索引 } - self->pl_readline_get_words(buf, words); - int can_be_selected = 0; - char sep; - for (int i = 0; i < words->len; i++) { - if (strncmp(buf, words->words[i].word, idx) == 0 && (is_first || !words->words[i].first)) { - if (strlen(words->words[i].word) > rt->input_buf_ptr) can_be_selected++; - if (strlen(words->words[i].word) == rt->input_buf_ptr) { - char *buf1 = strdup(rt->input_buf); - buf1[rt->input_buf_ptr] = '\0'; - if (strcmp(words->words[i].word, buf1) == 0) { - flag = 1; - sep = words->words[i].sep; + self->pl_readline_get_words(buf, words); // 请求词库 + int can_be_selected = 0; // 可能的单词数 + char sep; // 用于分隔符 + for (size_t i = 0; i < words->len; i++) { + if (strncmp(buf, words->words[i].word, idx) == 0 && + (is_first || !words->words[i].first)) { // 找到相同前缀的单词 + if (strlen(words->words[i].word) > self->input_ptr) // 找到的单词比输入的长 + can_be_selected++; // 可能的单词数加一 + if (strlen(words->words[i].word) == self->input_ptr) { // 找到的单词和输入的一样长 + char *temp_buffer = strdup(self->input_buf); // 临时缓冲区 + temp_buffer[self->input_ptr] = '\0'; // 加上结束符 + if (strcmp(words->words[i].word, temp_buffer) == 0) { // 找到的单词和输入一样 + flag = 1; // flag代表有这个词 + sep = words->words[i].sep; // 用于分隔符 } else { - can_be_selected++; + can_be_selected++; // 可能的单词数加一 } - free(buf1); + free(temp_buffer); // 释放临时缓冲区 } } } + // 该单词在词库中只有一个可匹配项,那么不需要补全 if (can_be_selected == 0 && flag == 1) { - pl_readline_word_maker_destroy(words); - if (sep) pl_readline_handle_key(self, sep, rt); + pl_readline_word_maker_destroy(words); // 释放words + if (sep) // 有分隔符,插入一下即可 + pl_readline_handle_key(self, sep); return (pl_readline_word){0}; } pl_readline_words_t words_temp = NULL; - if (!rt->intellisense_mode) { - words_temp = pl_readline_word_maker_init(); - if (idx == 0) { goto NOTHING_INPUT; } + if (!self->intellisense_mode) { + words_temp = pl_readline_word_maker_init(); // 临时词库,用于存储“可能”的单词 + if (idx == 0) { // 没东西我们直接输出词库 + goto NOTHING_INPUT; + } } - for (int i = 0; i < words->len; i++) { + for (size_t i = 0; i < words->len; i++) { if (strncmp(buf, words->words[i].word, idx) == 0 && (is_first || !words->words[i].first)) { - if (!rt->intellisense_mode && strlen(words->words[i].word) == idx) { continue; } - if (!rt->intellisense_mode) { - pl_readline_word_maker_add(words->words[i].word, words_temp, false, 0); - if (the_word == NULL || strlen(words->words[i].word) < strlen(the_word)) - the_word = words->words[i].word; + // 和用户输入一样的单词有什么好必要补全的? + if (!self->intellisense_mode && strlen(words->words[i].word) == idx) { + // 直接下一个 + continue; + } + if (!self->intellisense_mode) { // 如果是需要输出模式 + pl_readline_word_maker_add(words->words[i].word, words_temp, false, + 0); // 加入临时词库 } else { - if (times == 0) { pl_readline_next_line(self, rt); } - if (times) pl_readline_print(self, " "); - pl_readline_print(self, words->words[i].word); - times++; + if (times == 0) { // 第一次输出 + pl_readline_next_line(self); // 换行 + } + if (times) // 不是第一次输出 + pl_readline_print(self, " "); // 空格分隔 + pl_readline_print(self, words->words[i].word); // 输出单词 + times++; // 输出次数加一 } } } pl_readline_word ret = {0}; - if (rt->intellisense_mode == false) { - char *prefix = get_the_same_prefix_in_words(self, words_temp); + if (self->intellisense_mode == false) { + // 找到相同前缀的单词 + // 作者按:这里 get_same_prefix 不可能找不到相同前缀的单词, + // 因为 words_temp + // 里只有可能的单词,那么,天然的,他们已经有相同的前缀,只是多与少而已。 + // 但 prefix 仍然有可能为NULL,即:words_temp 里没有单词。 + char *prefix = get_same_prefix(words_temp); + /* + 找到的相同前缀和输入的一样 + 那么就是什么都没有改变,因而直接输出补全列表 + */ if (prefix && strcmp(prefix, buf) == 0) { free(prefix); NOTHING_INPUT: - rt->intellisense_mode = true; - pl_readline_word_maker_destroy(words_temp); - pl_readline_word_maker_destroy(words); - words = pl_readline_word_maker_init(); + self->intellisense_mode = true; // 设置为列出模式 + pl_readline_word_maker_destroy(words_temp); // 释放words_temp + pl_readline_word_maker_destroy(words); // 释放words + words = pl_readline_word_maker_init(); // 重新初始化words - return pl_readline_intellisense(self, rt, words); + return pl_readline_intellisense(self, words); } - ret.word = prefix; - rt->intellisense_mode = true; + // 若prefix为NULL,则不会去插入,这是调用者决定的,我这里不管 + ret.word = prefix; + self->intellisense_mode = true; pl_readline_word_maker_destroy(words_temp); } - if (rt->intellisense_mode && times) { ret.first = true; } - pl_readline_word_maker_destroy(words); + if (self->intellisense_mode && times) { ret.first = true; } + pl_readline_word_maker_destroy(words); // 释放words return ret; } -void pl_readline_intellisense_insert(_SELF, pl_readline_runtime *rt, pl_readline_word word) { - insert_string(self, word.word + rt->input_buf_ptr, rt); +void pl_readline_intellisense_insert(_self, pl_readline_word word) { + insert_string(self, word.word + self->input_ptr); free(word.word); } diff --git a/src/pl_readline/plreadln_wordmk.c b/src/pl_readline/plreadln_wordmk.c index 7be73b76..e7986f2b 100755 --- a/src/pl_readline/plreadln_wordmk.c +++ b/src/pl_readline/plreadln_wordmk.c @@ -12,38 +12,40 @@ #include -pl_readline_words_t pl_readline_word_maker_init() { +pl_readline_words_t pl_readline_word_maker_init(void) { pl_readline_words_t words = malloc(sizeof(struct pl_readline_words)); - words->len = 0; // initial length - words->max_len = 16; // initial max length - words->words = malloc(words->max_len * sizeof(pl_readline_word)); + words->len = 0; // initial length + words->max_len = 16; // initial max length + words->words = malloc(words->max_len * sizeof(pl_readline_word)); assert(words->words != NULL); return words; } + void pl_readline_word_maker_destroy(pl_readline_words_t words) { - for (int i = 0; i < words->len; i++) { + for (size_t i = 0; i < words->len; i++) { char *p = words->words[i].word; free(p); } free(words->words); free(words); } -int pl_readline_word_maker_add(char *word, pl_readline_words_t words, - bool is_first, char sep) { + +int pl_readline_word_maker_add(char *word, pl_readline_words_t words, bool is_first, char sep) { if (words->len >= words->max_len) { words->max_len *= 2; - words->words = realloc(words->words, words->max_len * sizeof(pl_readline_word)); + words->words = realloc(words->words, words->max_len * sizeof(pl_readline_word)); assert(words->words != NULL); } words->words[words->len].first = is_first; - words->words[words->len].word = strdup(word); - words->words[words->len].sep = sep; + words->words[words->len].word = strdup(word); + words->words[words->len].sep = sep; words->len++; return 0; } + void pl_readline_word_maker_clear(pl_readline_words_t words) { - for (int i = 0; i < words->len; i++) { + for (size_t i = 0; i < words->len; i++) { free(words->words[i].word); } words->len = 0; -} \ No newline at end of file +}