From 52b7136e01d8155f64434765ccd1506732606d22 Mon Sep 17 00:00:00 2001 From: Alec Murphy Date: Sun, 21 Sep 2025 13:34:27 -0400 Subject: [PATCH] System/Libraries/Stdio: Initial support for @dir_entry autocomplete --- System/Libraries/Stdio.HC | 138 ++++++++++++++++++++++++++++++++++---- 1 file changed, 125 insertions(+), 13 deletions(-) diff --git a/System/Libraries/Stdio.HC b/System/Libraries/Stdio.HC index 108c066..5961275 100644 --- a/System/Libraries/Stdio.HC +++ b/System/Libraries/Stdio.HC @@ -147,7 +147,7 @@ U0 @stdio_read_line_autocomplete_cmd(@shell* sh, U8* str, U8* line, I64* pos) } } -I64 @stdio_read_line_autocomplete_sort_cmds(U8** e1, U8** e2) +I64 @stdio_read_line_autocomplete_sort(U8** e1, U8** e2) { return StrCmp(*e1, *e2); } @@ -179,7 +179,7 @@ U0 @stdio_read_line_autocomplete_list_cmds(@shell* sh, U8* prompt, U8* str, U8* tbl = tbl->next; } if (cnt) { - QSort(cmds, cnt, sizeof(U8*), &@stdio_read_line_autocomplete_sort_cmds); + QSort(cmds, cnt, sizeof(U8*), &@stdio_read_line_autocomplete_sort); for (i = 0; i < cnt; i++) { @stdio_write_line(sh, "%s\n", cmds[i]); } @@ -188,24 +188,136 @@ U0 @stdio_read_line_autocomplete_list_cmds(@shell* sh, U8* prompt, U8* str, U8* Free(cmds); } +I64 @stdio_read_line_autocomplete_dir_entry_count(@shell* sh, U8* str, @dir_entry* de) +{ + I64 cnt = 0; + I64 len = StrLen(str); + @dir_entry* tmpf = de; + + while (tmpf) { + if (StrCmp(tmpf->name, ".") && StrCmp(tmpf->name, "..")) { + switch (len) { + case 0: + ++cnt; + break; + default: + if (!MemCmp(tmpf->name, str, len)) { + ++cnt; + } + break; + } + } + tmpf = tmpf->next; + } + return cnt; +} + +U0 @stdio_read_line_autocomplete_dir_entry(@shell* sh, U8* str, @dir_entry* de, U8* line, I64* pos) +{ + U8* ac_ch_ptr = NULL; + I64 len = StrLen(str); + @dir_entry* tmpf = de; + Bool matched = FALSE; + + while (tmpf) { + if (!MemCmp(tmpf->name, str, len) && !matched) { + ac_ch_ptr = tmpf->name + len; + while (*ac_ch_ptr) { + String.Append(line, "%c", *ac_ch_ptr); + FifoU8Ins(sh->output, *ac_ch_ptr); + ++pos[0]; + ++ac_ch_ptr; + } + if (tmpf->type == DE_TYPE_DIR) { + String.Append(line, "/"); + FifoU8Ins(sh->output, '/'); + } else { + String.Append(line, " "); + FifoU8Ins(sh->output, ' '); + } + ++pos[0]; + matched = TRUE; + } + tmpf = tmpf->next; + } +} + +U0 @stdio_read_line_autocomplete_list_dir_entries(@shell* sh, U8* prompt, U8* str, @dir_entry* de, U8* line, I64* pos, I64 entry_count) +{ + I64 cnt = 0; + + I64 i; + U8** entries = CAlloc(sizeof(U8*) * entry_count); + I64 len = StrLen(str); + @dir_entry* tmpf = de; + + while (tmpf) { + if (!MemCmp(tmpf->name, str, len)) { + if (!cnt) { + @stdio_write_line(sh, "\n"); + } + entries[cnt] = tmpf->name; + ++cnt; + } + tmpf = tmpf->next; + } + if (cnt) { + QSort(entries, cnt, sizeof(U8*), &@stdio_read_line_autocomplete_sort); + for (i = 0; i < cnt; i++) { + @stdio_write_line(sh, "%s\n", entries[i]); + } + @stdio_write_line(sh, "%s%s", prompt, line); + } + Free(entries); +} + +U0 @stdio_read_line_autocompletion_from_cmd(@shell* sh, U8* prompt, U8* ac_buf, U8* str, I64* pos) +{ + StrPrint(ac_buf, "@shell_cmd_%s", str); + I64 word_count = @stdio_read_line_autocomplete_cmd_count(ac_buf); + switch (word_count) { + case 1: + @stdio_read_line_autocomplete_cmd(sh, ac_buf, str, pos); + break; + default: + @stdio_read_line_autocomplete_list_cmds(sh, prompt, ac_buf, str, pos, word_count); + break; + } +} + +U0 @stdio_read_line_autocompletion_from_dir_entry(@shell* sh, U8* prompt, U8* ac_buf, U8* str, I64* pos) +{ + StrPrint(ac_buf, StrLastOcc(str, " ") + 1); + @dir_entry* de = FileSystem.GetFiles(sh->cwd); + @dir_entry* de2 = NULL; + I64 word_count = @stdio_read_line_autocomplete_dir_entry_count(sh, ac_buf, de); + switch (word_count) { + case 1: + @stdio_read_line_autocomplete_dir_entry(sh, ac_buf, de, str, pos); + break; + default: + @stdio_read_line_autocomplete_list_dir_entries(sh, prompt, ac_buf, de, str, pos, word_count); + break; + } + // Free @dir_entries + while (de) { + de2 = de; + de = de->next; + Free(de2); + } +} + U0 @stdio_read_line_autocomplete(@shell* sh, U8* prompt, U8* str, I64* pos) { U8 ac_buf[4096]; I64 space_count = StrOcc(str, ' '); - I64 cmd_count = 0; switch (space_count) { case 0: - StrPrint(ac_buf, "@shell_cmd_%s", str); - cmd_count = @stdio_read_line_autocomplete_cmd_count(ac_buf); - switch (cmd_count) { - case 1: - @stdio_read_line_autocomplete_cmd(sh, ac_buf, str, pos); - break; - default: - @stdio_read_line_autocomplete_list_cmds(sh, prompt, ac_buf, str, pos, cmd_count); - break; - } + @stdio_read_line_autocompletion_from_cmd(sh, prompt, ac_buf, str, pos); + break; default: + // TODO: Handle completion for specific commands + @stdio_read_line_autocompletion_from_dir_entry(sh, prompt, ac_buf, str, pos); break; } }