diff --git a/kernel/src/Api/BuildNo.hpp b/kernel/src/Api/BuildNo.hpp index 3b58095..1c68e2b 100644 --- a/kernel/src/Api/BuildNo.hpp +++ b/kernel/src/Api/BuildNo.hpp @@ -12,4 +12,4 @@ #pragma once -#define MONTAUK_BUILD_NUMBER 82 +#define MONTAUK_BUILD_NUMBER 104 diff --git a/programs/src/shell/main.cpp b/programs/src/shell/main.cpp index 9ad4348..fc77818 100644 --- a/programs/src/shell/main.cpp +++ b/programs/src/shell/main.cpp @@ -439,7 +439,7 @@ extern "C" void _start() { if (pos == 0) continue; char* table[128] = { }; - int n = get_completions(line, table, 128); + int n = get_completions(line, table, 128, cwd, current_drive); montauk::print("\n"); for (int i = 0; i < n; i++) { diff --git a/programs/src/shell/shell.h b/programs/src/shell/shell.h index b775065..10f82bd 100644 --- a/programs/src/shell/shell.h +++ b/programs/src/shell/shell.h @@ -129,7 +129,7 @@ int exec_external(const char* cmd, const char* args); // ---- Tab completion (tabcompletion.cpp) ---- -int get_completions(char* string, char** array, int arrayMax); +int get_completions(char* string, char** array, int arrayMax, char* cwd = nullptr, int volume_number = 0); // ---- Shell builtins ---- diff --git a/programs/src/shell/tabcompletion.cpp b/programs/src/shell/tabcompletion.cpp index 9942d88..0515c61 100644 --- a/programs/src/shell/tabcompletion.cpp +++ b/programs/src/shell/tabcompletion.cpp @@ -53,10 +53,64 @@ const char* strip_elf_extension(const char* path) { return (const char*)p; } +const char* build_montauk_path( + char* buffer, + int max, + + int volume_number, + const char* subpath + ) { + + char volume_number_str[4]; // 3 digits (max. 999) + null byte + int_to_str(volume_number, volume_number_str, 4); + + // example path: + size_t vn_length = slen(volume_number_str); // 0 + size_t subpath_length = slen(subpath); // users/admin + size_t bytes_required = vn_length + subpath_length + 2; // + ":" and "/" (full path 0:/users/admin) + + if (max < bytes_required) { + return nullptr; + } + + int pos = 0; + + for (int i = 0; i < vn_length; i++) { + buffer[pos] = volume_number_str[i]; + pos++; + } + + buffer[pos] = ':'; pos++; + buffer[pos] = '/'; pos++; + + for (int i = 0; i < subpath_length; i++) { + buffer[pos] = subpath[i]; + pos++; + } + + return buffer; +} + +const char* remove_path_prefix( + const char* prefix, // users/admin + const char* string // users/admin/config/ +) { // result: config/ + int pos = 0; + + while (string[pos] == prefix[pos]) { + pos++; + } + + return &string[pos]; +} + int get_completions( // returns no. of results char* string, // String to match/complete char** array, // Array of strings containing completions - int arrayMax + int arrayMax, + + char* cwd, + int volume_number ) { // --- System commands (0:/os/*.elf) ---- @@ -92,7 +146,7 @@ int get_completions( // returns no. of results } // ---- Shell builtins ---- - + size_t builtins_count = sizeof(shell_builtins) / sizeof(const char*); for (size_t i = 0; i < builtins_count; i++) { @@ -105,5 +159,32 @@ int get_completions( // returns no. of results } } + // ---- cwd file matching ---- + + if (cwd != nullptr) { + char full_path[RD_MAX] = { }; + build_montauk_path(full_path, RD_MAX, volume_number, cwd); + + const char* cwd_entries[RD_MAX] = { }; + + int n = montauk::readdir(full_path, cwd_entries, RD_MAX); + + for (int i = 0; i < n; i++) { + const char* cwd_entry_path = remove_path_prefix(cwd, cwd_entries[i]); + + if (cwd_entry_path[0] == '/') { + cwd_entry_path++; + } + + if (montauk::starts_with(cwd_entry_path, (const char*)string)) { + if (r > arrayMax) + break; + + array[r] = (char *)cwd_entry_path; + r++; + } + } + } + return r; }