diff --git a/dshash-completion.bash b/dshash-completion.bash new file mode 100644 index 0000000..615c8b4 --- /dev/null +++ b/dshash-completion.bash @@ -0,0 +1,11 @@ +#!/bin/bash +# Bash completion for dshash + +_dshash_autocomplete() { + local cur="${COMP_WORDS[COMP_CWORD]}" + mapfile -t completions < <(dshash autocomplete "${COMP_WORDS[@]:1:${COMP_CWORD}-1}") + mapfile -t COMPREPLY < <(compgen -W "${completions[*]}" -- "$cur") +} + +# Use -o default to enable file/directory completion in addition to custom completions +complete -o default -F _dshash_autocomplete dshash \ No newline at end of file diff --git a/dshash/dshash b/dshash/dshash index 9195cd4..df19e61 100755 Binary files a/dshash/dshash and b/dshash/dshash differ diff --git a/dshash/main.cpp b/dshash/main.cpp index 998f235..139d853 100644 --- a/dshash/main.cpp +++ b/dshash/main.cpp @@ -27,16 +27,66 @@ int main(int argc, char* argv[]) { // Check for autocomplete command if (std::string(argv[1]) == "autocomplete") { - // Return available options for autocomplete - std::cout << "-v\n"; - std::cout << "version\n"; - // Suggest files and directories in current directory - try { - for (const auto& entry : std::filesystem::directory_iterator(".")) { - std::cout << entry.path().filename().string() << "\n"; + // Parse the arguments passed by bash completion + // argv[2] onwards contains the current command line words (excluding the command itself) + + // If no args typed yet, suggest commands and flags + if (argc == 2) { + std::cout << "-v\n"; + std::cout << "version\n"; + // Also list files/directories in current directory + try { + for (const auto& entry : std::filesystem::directory_iterator(".")) { + std::string name = entry.path().filename().string(); + // Skip hidden files starting with . + if (!name.empty() && name[0] != '.') { + if (entry.is_directory()) { + std::cout << name << "/\n"; + } else { + std::cout << name << "\n"; + } + } + } + } catch (...) { + // Ignore errors + } + } else { + // Get the last argument (the partial word being completed) + std::string partial = argv[argc - 1]; + + // Handle file/directory path completion + std::filesystem::path partial_path(partial); + std::filesystem::path dir_path = partial_path.parent_path(); + std::string prefix = partial_path.filename().string(); + + if (dir_path.empty()) { + dir_path = "."; + } + + try { + if (std::filesystem::exists(dir_path) && std::filesystem::is_directory(dir_path)) { + for (const auto& entry : std::filesystem::directory_iterator(dir_path)) { + std::string name = entry.path().filename().string(); + + // Skip hidden files unless user is explicitly typing them + if (prefix.empty() && !name.empty() && name[0] == '.') { + continue; + } + + // Check if filename starts with the prefix + if (name.find(prefix) == 0) { + std::filesystem::path full_path = entry.path(); + if (entry.is_directory()) { + std::cout << full_path.string() << "/\n"; + } else { + std::cout << full_path.string() << "\n"; + } + } + } + } + } catch (...) { + // Ignore errors in autocomplete } - } catch (...) { - // Ignore errors in autocomplete } return 0; } diff --git a/dshash/main.o b/dshash/main.o index 7d8f501..e4e82fa 100644 Binary files a/dshash/main.o and b/dshash/main.o differ