mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-28 22:03:12 +00:00
Rewrite "builtin" builtin in Rust
This is very simple and basically a subset of type.
This commit is contained in:
parent
b65a53a2a6
commit
72a32f1a12
8 changed files with 16 additions and 122 deletions
|
@ -100,7 +100,7 @@ endif()
|
||||||
# List of sources for builtin functions.
|
# List of sources for builtin functions.
|
||||||
set(FISH_BUILTIN_SRCS
|
set(FISH_BUILTIN_SRCS
|
||||||
src/builtin.cpp src/builtins/argparse.cpp src/builtins/bind.cpp
|
src/builtin.cpp src/builtins/argparse.cpp src/builtins/bind.cpp
|
||||||
src/builtins/builtin.cpp src/builtins/cd.cpp
|
src/builtins/cd.cpp
|
||||||
src/builtins/commandline.cpp src/builtins/complete.cpp
|
src/builtins/commandline.cpp src/builtins/complete.cpp
|
||||||
src/builtins/disown.cpp
|
src/builtins/disown.cpp
|
||||||
src/builtins/eval.cpp src/builtins/fg.cpp
|
src/builtins/eval.cpp src/builtins/fg.cpp
|
||||||
|
|
|
@ -3,6 +3,7 @@ pub mod shared;
|
||||||
pub mod abbr;
|
pub mod abbr;
|
||||||
pub mod bg;
|
pub mod bg;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
|
pub mod builtin;
|
||||||
pub mod command;
|
pub mod command;
|
||||||
pub mod contains;
|
pub mod contains;
|
||||||
pub mod echo;
|
pub mod echo;
|
||||||
|
|
|
@ -39,6 +39,7 @@ pub const BUILTIN_ERR_NOT_NUMBER: &str = "%ls: %ls: invalid integer\n";
|
||||||
pub const BUILTIN_ERR_ARG_COUNT1: &str = "%ls: expected %d arguments; got %d\n";
|
pub const BUILTIN_ERR_ARG_COUNT1: &str = "%ls: expected %d arguments; got %d\n";
|
||||||
|
|
||||||
pub const BUILTIN_ERR_COMBO: &str = "%ls: invalid option combination\n";
|
pub const BUILTIN_ERR_COMBO: &str = "%ls: invalid option combination\n";
|
||||||
|
pub const BUILTIN_ERR_COMBO2: &str = "%ls: invalid option combination, %ls\n";
|
||||||
|
|
||||||
// Return values (`$status` values for fish scripts) for various situations.
|
// Return values (`$status` values for fish scripts) for various situations.
|
||||||
|
|
||||||
|
@ -147,6 +148,7 @@ pub fn run_builtin(
|
||||||
RustBuiltin::Abbr => super::abbr::abbr(parser, streams, args),
|
RustBuiltin::Abbr => super::abbr::abbr(parser, streams, args),
|
||||||
RustBuiltin::Bg => super::bg::bg(parser, streams, args),
|
RustBuiltin::Bg => super::bg::bg(parser, streams, args),
|
||||||
RustBuiltin::Block => super::block::block(parser, streams, args),
|
RustBuiltin::Block => super::block::block(parser, streams, args),
|
||||||
|
RustBuiltin::Builtin => super::builtin::builtin(parser, streams, args),
|
||||||
RustBuiltin::Contains => super::contains::contains(parser, streams, args),
|
RustBuiltin::Contains => super::contains::contains(parser, streams, args),
|
||||||
RustBuiltin::Command => super::command::command(parser, streams, args),
|
RustBuiltin::Command => super::command::command(parser, streams, args),
|
||||||
RustBuiltin::Echo => super::echo::echo(parser, streams, args),
|
RustBuiltin::Echo => super::echo::echo(parser, streams, args),
|
||||||
|
|
|
@ -87,6 +87,7 @@ include_cpp! {
|
||||||
generate!("builtin_unknown_option")
|
generate!("builtin_unknown_option")
|
||||||
generate!("builtin_print_help")
|
generate!("builtin_print_help")
|
||||||
generate!("builtin_print_error_trailer")
|
generate!("builtin_print_error_trailer")
|
||||||
|
generate!("builtin_get_names_ffi")
|
||||||
|
|
||||||
generate!("escape_string")
|
generate!("escape_string")
|
||||||
generate!("sig2wcs")
|
generate!("sig2wcs")
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
|
|
||||||
#include "builtins/argparse.h"
|
#include "builtins/argparse.h"
|
||||||
#include "builtins/bind.h"
|
#include "builtins/bind.h"
|
||||||
#include "builtins/builtin.h"
|
|
||||||
#include "builtins/cd.h"
|
#include "builtins/cd.h"
|
||||||
#include "builtins/commandline.h"
|
#include "builtins/commandline.h"
|
||||||
#include "builtins/complete.h"
|
#include "builtins/complete.h"
|
||||||
|
@ -361,7 +360,7 @@ static constexpr builtin_data_t builtin_datas[] = {
|
||||||
{L"block", &implemented_in_rust, N_(L"Temporarily block delivery of events")},
|
{L"block", &implemented_in_rust, N_(L"Temporarily block delivery of events")},
|
||||||
{L"break", &builtin_break_continue, N_(L"Stop the innermost loop")},
|
{L"break", &builtin_break_continue, N_(L"Stop the innermost loop")},
|
||||||
{L"breakpoint", &builtin_breakpoint, N_(L"Halt execution and start debug prompt")},
|
{L"breakpoint", &builtin_breakpoint, N_(L"Halt execution and start debug prompt")},
|
||||||
{L"builtin", &builtin_builtin, N_(L"Run a builtin specifically")},
|
{L"builtin", &implemented_in_rust, N_(L"Run a builtin specifically")},
|
||||||
{L"case", &builtin_generic, N_(L"Block of code to run conditionally")},
|
{L"case", &builtin_generic, N_(L"Block of code to run conditionally")},
|
||||||
{L"cd", &builtin_cd, N_(L"Change working directory")},
|
{L"cd", &builtin_cd, N_(L"Change working directory")},
|
||||||
{L"command", &implemented_in_rust, N_(L"Run a command specifically")},
|
{L"command", &implemented_in_rust, N_(L"Run a command specifically")},
|
||||||
|
@ -502,6 +501,10 @@ wcstring_list_t builtin_get_names() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wcstring_list_ffi_t builtin_get_names_ffi() {
|
||||||
|
return builtin_get_names();
|
||||||
|
}
|
||||||
|
|
||||||
/// Insert all builtin names into list.
|
/// Insert all builtin names into list.
|
||||||
void builtin_get_names(completion_list_t *list) {
|
void builtin_get_names(completion_list_t *list) {
|
||||||
assert(list != nullptr);
|
assert(list != nullptr);
|
||||||
|
@ -531,6 +534,9 @@ static maybe_t<RustBuiltin> try_get_rust_builtin(const wcstring &cmd) {
|
||||||
if (cmd == L"block") {
|
if (cmd == L"block") {
|
||||||
return RustBuiltin::Block;
|
return RustBuiltin::Block;
|
||||||
}
|
}
|
||||||
|
if (cmd == L"builtin") {
|
||||||
|
return RustBuiltin::Builtin;
|
||||||
|
}
|
||||||
if (cmd == L"contains") {
|
if (cmd == L"contains") {
|
||||||
return RustBuiltin::Contains;
|
return RustBuiltin::Contains;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "complete.h"
|
#include "complete.h"
|
||||||
#include "maybe.h"
|
#include "maybe.h"
|
||||||
|
#include "wutil.h"
|
||||||
|
|
||||||
class parser_t;
|
class parser_t;
|
||||||
class proc_status_t;
|
class proc_status_t;
|
||||||
|
@ -82,6 +83,7 @@ bool builtin_exists(const wcstring &cmd);
|
||||||
proc_status_t builtin_run(parser_t &parser, const wcstring_list_t &argv, io_streams_t &streams);
|
proc_status_t builtin_run(parser_t &parser, const wcstring_list_t &argv, io_streams_t &streams);
|
||||||
|
|
||||||
wcstring_list_t builtin_get_names();
|
wcstring_list_t builtin_get_names();
|
||||||
|
wcstring_list_ffi_t builtin_get_names_ffi();
|
||||||
void builtin_get_names(completion_list_t *list);
|
void builtin_get_names(completion_list_t *list);
|
||||||
const wchar_t *builtin_get_desc(const wcstring &name);
|
const wchar_t *builtin_get_desc(const wcstring &name);
|
||||||
|
|
||||||
|
@ -112,6 +114,7 @@ enum RustBuiltin : int32_t {
|
||||||
Abbr,
|
Abbr,
|
||||||
Bg,
|
Bg,
|
||||||
Block,
|
Block,
|
||||||
|
Builtin,
|
||||||
Contains,
|
Contains,
|
||||||
Command,
|
Command,
|
||||||
Echo,
|
Echo,
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
// Implementation of the builtin builtin.
|
|
||||||
#include "config.h" // IWYU pragma: keep
|
|
||||||
|
|
||||||
#include "builtin.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "../builtin.h"
|
|
||||||
#include "../common.h"
|
|
||||||
#include "../fallback.h" // IWYU pragma: keep
|
|
||||||
#include "../io.h"
|
|
||||||
#include "../maybe.h"
|
|
||||||
#include "../wgetopt.h"
|
|
||||||
#include "../wutil.h" // IWYU pragma: keep
|
|
||||||
|
|
||||||
struct builtin_cmd_opts_t {
|
|
||||||
bool print_help = false;
|
|
||||||
bool list_names = false;
|
|
||||||
bool query = false;
|
|
||||||
};
|
|
||||||
static const wchar_t *const short_options = L":hnq";
|
|
||||||
static const struct woption long_options[] = {
|
|
||||||
{L"help", no_argument, 'h'}, {L"names", no_argument, 'n'}, {L"query", no_argument, 'q'}, {}};
|
|
||||||
|
|
||||||
static int parse_cmd_opts(builtin_cmd_opts_t &opts, int *optind, int argc, const wchar_t **argv,
|
|
||||||
parser_t &parser, io_streams_t &streams) {
|
|
||||||
const wchar_t *cmd = argv[0];
|
|
||||||
int opt;
|
|
||||||
wgetopter_t w;
|
|
||||||
while ((opt = w.wgetopt_long(argc, argv, short_options, long_options, nullptr)) != -1) {
|
|
||||||
switch (opt) {
|
|
||||||
case 'h': {
|
|
||||||
opts.print_help = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'n': {
|
|
||||||
opts.list_names = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'q': {
|
|
||||||
opts.query = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ':': {
|
|
||||||
builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]);
|
|
||||||
return STATUS_INVALID_ARGS;
|
|
||||||
}
|
|
||||||
case '?': {
|
|
||||||
builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]);
|
|
||||||
return STATUS_INVALID_ARGS;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
DIE("unexpected retval from wgetopt_long");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*optind = w.woptind;
|
|
||||||
return STATUS_CMD_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The builtin builtin, used for giving builtins precedence over functions. Mostly handled by the
|
|
||||||
/// parser. All this code does is some additional operational modes, such as printing a list of all
|
|
||||||
/// builtins, printing help, etc.
|
|
||||||
maybe_t<int> builtin_builtin(parser_t &parser, io_streams_t &streams, const wchar_t **argv) {
|
|
||||||
const wchar_t *cmd = argv[0];
|
|
||||||
int argc = builtin_count_args(argv);
|
|
||||||
builtin_cmd_opts_t opts;
|
|
||||||
|
|
||||||
int optind;
|
|
||||||
int retval = parse_cmd_opts(opts, &optind, argc, argv, parser, streams);
|
|
||||||
if (retval != STATUS_CMD_OK) return retval;
|
|
||||||
|
|
||||||
if (opts.print_help) {
|
|
||||||
builtin_print_help(parser, streams, cmd);
|
|
||||||
return STATUS_CMD_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.query && opts.list_names) {
|
|
||||||
streams.err.append_format(BUILTIN_ERR_COMBO2, cmd,
|
|
||||||
_(L"--query and --names are mutually exclusive"));
|
|
||||||
return STATUS_INVALID_ARGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.query) {
|
|
||||||
wcstring_list_t names = builtin_get_names();
|
|
||||||
retval = STATUS_CMD_ERROR;
|
|
||||||
for (int i = optind; i < argc; i++) {
|
|
||||||
if (contains(names, argv[i])) {
|
|
||||||
retval = STATUS_CMD_OK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.list_names) {
|
|
||||||
wcstring_list_t names = builtin_get_names();
|
|
||||||
std::sort(names.begin(), names.end());
|
|
||||||
|
|
||||||
for (auto &name : names) {
|
|
||||||
streams.out.append(name + L"\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_CMD_OK;
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
// Prototypes for executing builtin_builtin function.
|
|
||||||
#ifndef FISH_BUILTIN_BUILTIN_H
|
|
||||||
#define FISH_BUILTIN_BUILTIN_H
|
|
||||||
|
|
||||||
#include "../maybe.h"
|
|
||||||
|
|
||||||
class parser_t;
|
|
||||||
struct io_streams_t;
|
|
||||||
|
|
||||||
maybe_t<int> builtin_builtin(parser_t &parser, io_streams_t &streams, const wchar_t **argv);
|
|
||||||
#endif
|
|
Loading…
Reference in a new issue