mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-07-02 00:51:15 -03:00
Call "fish_command_not_found" if a command wasn't found
Previously, when a command wasn't found, fish would emit the
"fish_command_not_found" *event*.
This was annoying as it was hard to override (the code ended up
checking for a function called `__fish_command_not_found_handler`
anyway!), the setup was ugly,
and it's useless - there is no use case for multiple command-not-found handlers.
Instead, let's just call a function `fish_command_not_found` if it
exists, or print the default message otherwise.
The event is completely removed, but because a missing event is not an error
(MEISNAE in C++-speak) this isn't an issue.
Note that, for backwards-compatibility, we still keep the default
handler function around even tho the new one is hard-coded in C++.
Also, if we detect a previous handler, the new handler just calls it.
This way, the backwards-compatible way to install a custom handler is:
```fish
function __fish_command_not_found_handler --on-event fish_command_not_found
# do a little dance, make a little love, get down tonight
end
```
and the new hotness is
```fish
function fish_command_not_found
# do the thing
end
```
Fixes #7293.
This commit is contained in:
@@ -749,10 +749,39 @@ end_execution_reason_t parse_execution_context_t::handle_command_not_found(
|
||||
event_args.insert(event_args.begin(), cmd_str);
|
||||
}
|
||||
|
||||
event_fire_generic(*parser, L"fish_command_not_found", &event_args);
|
||||
wcstring buffer;
|
||||
wcstring error;
|
||||
|
||||
// Here we want to report an error (so it shows a backtrace), but with no text.
|
||||
return this->report_error(STATUS_CMD_UNKNOWN, statement, L"");
|
||||
// Redirect to stderr
|
||||
auto io = io_chain_t{};
|
||||
io.append_from_specs({redirection_spec_t{STDOUT_FILENO, redirection_mode_t::fd, L"2"}}, L"");
|
||||
|
||||
if (function_exists(L"fish_command_not_found", *parser)) {
|
||||
buffer = L"fish_command_not_found";
|
||||
for (const wcstring &arg : event_args) {
|
||||
buffer.push_back(L' ');
|
||||
buffer.append(escape_string(arg, ESCAPE_ALL));
|
||||
}
|
||||
auto prev_statuses = parser->get_last_statuses();
|
||||
|
||||
event_t event(event_type_t::generic);
|
||||
event.desc.str_param1 = L"fish_command_not_found";
|
||||
block_t *b = parser->push_block(block_t::event_block(event));
|
||||
parser->eval(buffer, io);
|
||||
parser->pop_block(b);
|
||||
parser->set_last_statuses(std::move(prev_statuses));
|
||||
} else {
|
||||
// If we have no handler, just print it as a normal error.
|
||||
error = _(L"Unknown command:");
|
||||
if (!event_args.empty()) {
|
||||
error.push_back(L' ');
|
||||
error.append(escape_string(event_args[0], ESCAPE_ALL));
|
||||
}
|
||||
}
|
||||
|
||||
// Here we want to report an error (so it shows a backtrace).
|
||||
// If the handler printed text, that's already shown, so error will be empty.
|
||||
return this->report_error(STATUS_CMD_UNKNOWN, statement, error.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user