mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:47:34 +00:00
Shell: Auto-completion shouldn't suggest non-executable files for the program name
This commit is contained in:
parent
e45e0eeb47
commit
111ac4b1f4
3 changed files with 13 additions and 7 deletions
|
@ -336,7 +336,7 @@ Vector<Line::CompletionSuggestion> Node::complete_for_editor(Shell& shell, size_
|
||||||
|
|
||||||
// If the literal isn't an option, treat it as a path.
|
// If the literal isn't an option, treat it as a path.
|
||||||
if (!(text.starts_with("-") || text == "--" || text == "-"))
|
if (!(text.starts_with("-") || text == "--" || text == "-"))
|
||||||
return shell.complete_path("", text, corrected_offset);
|
return shell.complete_path("", text, corrected_offset, Shell::ExecutableOnly::No);
|
||||||
|
|
||||||
// If the literal is an option, we have to know the program name
|
// If the literal is an option, we have to know the program name
|
||||||
// should we have no way to get that, bail early.
|
// should we have no way to get that, bail early.
|
||||||
|
@ -2349,7 +2349,7 @@ Vector<Line::CompletionSuggestion> PathRedirectionNode::complete_for_editor(Shel
|
||||||
if (corrected_offset > node->text().length())
|
if (corrected_offset > node->text().length())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return shell.complete_path("", node->text(), corrected_offset);
|
return shell.complete_path("", node->text(), corrected_offset, Shell::ExecutableOnly::No);
|
||||||
}
|
}
|
||||||
|
|
||||||
PathRedirectionNode::~PathRedirectionNode()
|
PathRedirectionNode::~PathRedirectionNode()
|
||||||
|
@ -2895,7 +2895,7 @@ Vector<Line::CompletionSuggestion> Juxtaposition::complete_for_editor(Shell& she
|
||||||
|
|
||||||
auto text = node->text().substring(1, node->text().length() - 1);
|
auto text = node->text().substring(1, node->text().length() - 1);
|
||||||
|
|
||||||
return shell.complete_path(tilde_value, text, corrected_offset - 1);
|
return shell.complete_path(tilde_value, text, corrected_offset - 1, Shell::ExecutableOnly::No);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Node::complete_for_editor(shell, offset, hit_test_result);
|
return Node::complete_for_editor(shell, offset, hit_test_result);
|
||||||
|
|
|
@ -1304,7 +1304,8 @@ Vector<Line::CompletionSuggestion> Shell::complete()
|
||||||
return ast->complete_for_editor(*this, line.length());
|
return ast->complete_for_editor(*this, line.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<Line::CompletionSuggestion> Shell::complete_path(const String& base, const String& part, size_t offset)
|
Vector<Line::CompletionSuggestion> Shell::complete_path(const String& base,
|
||||||
|
const String& part, size_t offset, ExecutableOnly executable_only)
|
||||||
{
|
{
|
||||||
auto token = offset ? part.substring_view(0, offset) : "";
|
auto token = offset ? part.substring_view(0, offset) : "";
|
||||||
String path;
|
String path;
|
||||||
|
@ -1358,7 +1359,7 @@ Vector<Line::CompletionSuggestion> Shell::complete_path(const String& base, cons
|
||||||
struct stat program_status;
|
struct stat program_status;
|
||||||
String file_path = String::format("%s/%s", path.characters(), file.characters());
|
String file_path = String::format("%s/%s", path.characters(), file.characters());
|
||||||
int stat_error = stat(file_path.characters(), &program_status);
|
int stat_error = stat(file_path.characters(), &program_status);
|
||||||
if (!stat_error) {
|
if (!stat_error && (executable_only == ExecutableOnly::No || access(file_path.characters(), X_OK) == 0)) {
|
||||||
if (S_ISDIR(program_status.st_mode)) {
|
if (S_ISDIR(program_status.st_mode)) {
|
||||||
suggestions.append({ escape_token(file), "/" });
|
suggestions.append({ escape_token(file), "/" });
|
||||||
} else {
|
} else {
|
||||||
|
@ -1381,7 +1382,7 @@ Vector<Line::CompletionSuggestion> Shell::complete_program_name(const String& na
|
||||||
[](auto& name, auto& program) { return strncmp(name.characters(), program.characters(), name.length()); });
|
[](auto& name, auto& program) { return strncmp(name.characters(), program.characters(), name.length()); });
|
||||||
|
|
||||||
if (!match)
|
if (!match)
|
||||||
return complete_path("", name, offset);
|
return complete_path("", name, offset, ExecutableOnly::Yes);
|
||||||
|
|
||||||
String completion = *match;
|
String completion = *match;
|
||||||
auto token_length = escape_token(name).length();
|
auto token_length = escape_token(name).length();
|
||||||
|
|
|
@ -178,9 +178,14 @@ public:
|
||||||
static bool is_glob(const StringView&);
|
static bool is_glob(const StringView&);
|
||||||
static Vector<StringView> split_path(const StringView&);
|
static Vector<StringView> split_path(const StringView&);
|
||||||
|
|
||||||
|
enum class ExecutableOnly {
|
||||||
|
Yes,
|
||||||
|
No
|
||||||
|
};
|
||||||
|
|
||||||
void highlight(Line::Editor&) const;
|
void highlight(Line::Editor&) const;
|
||||||
Vector<Line::CompletionSuggestion> complete();
|
Vector<Line::CompletionSuggestion> complete();
|
||||||
Vector<Line::CompletionSuggestion> complete_path(const String& base, const String&, size_t offset);
|
Vector<Line::CompletionSuggestion> complete_path(const String& base, const String&, size_t offset, ExecutableOnly executable_only);
|
||||||
Vector<Line::CompletionSuggestion> complete_program_name(const String&, size_t offset);
|
Vector<Line::CompletionSuggestion> complete_program_name(const String&, size_t offset);
|
||||||
Vector<Line::CompletionSuggestion> complete_variable(const String&, size_t offset);
|
Vector<Line::CompletionSuggestion> complete_variable(const String&, size_t offset);
|
||||||
Vector<Line::CompletionSuggestion> complete_user(const String&, size_t offset);
|
Vector<Line::CompletionSuggestion> complete_user(const String&, size_t offset);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue