System/Libraries/Stdio: Initial support for @dir_entry autocomplete

This commit is contained in:
Alec Murphy
2025-09-21 13:34:27 -04:00
parent e0946c6d45
commit 52b7136e01

View File

@@ -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;
}
}