Rewrite "builtin" builtin in Rust

This is very simple and basically a subset of type.
This commit is contained in:
Fabian Boehm 2023-04-16 11:29:26 +02:00
parent b65a53a2a6
commit 72a32f1a12
8 changed files with 16 additions and 122 deletions

View file

@ -100,7 +100,7 @@ endif()
# List of sources for builtin functions.
set(FISH_BUILTIN_SRCS
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/disown.cpp
src/builtins/eval.cpp src/builtins/fg.cpp

View file

@ -3,6 +3,7 @@ pub mod shared;
pub mod abbr;
pub mod bg;
pub mod block;
pub mod builtin;
pub mod command;
pub mod contains;
pub mod echo;

View file

@ -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_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.
@ -147,6 +148,7 @@ pub fn run_builtin(
RustBuiltin::Abbr => super::abbr::abbr(parser, streams, args),
RustBuiltin::Bg => super::bg::bg(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::Command => super::command::command(parser, streams, args),
RustBuiltin::Echo => super::echo::echo(parser, streams, args),

View file

@ -87,6 +87,7 @@ include_cpp! {
generate!("builtin_unknown_option")
generate!("builtin_print_help")
generate!("builtin_print_error_trailer")
generate!("builtin_get_names_ffi")
generate!("escape_string")
generate!("sig2wcs")

View file

@ -31,7 +31,6 @@
#include "builtins/argparse.h"
#include "builtins/bind.h"
#include "builtins/builtin.h"
#include "builtins/cd.h"
#include "builtins/commandline.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"break", &builtin_break_continue, N_(L"Stop the innermost loop")},
{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"cd", &builtin_cd, N_(L"Change working directory")},
{L"command", &implemented_in_rust, N_(L"Run a command specifically")},
@ -502,6 +501,10 @@ wcstring_list_t builtin_get_names() {
return result;
}
wcstring_list_ffi_t builtin_get_names_ffi() {
return builtin_get_names();
}
/// Insert all builtin names into list.
void builtin_get_names(completion_list_t *list) {
assert(list != nullptr);
@ -531,6 +534,9 @@ static maybe_t<RustBuiltin> try_get_rust_builtin(const wcstring &cmd) {
if (cmd == L"block") {
return RustBuiltin::Block;
}
if (cmd == L"builtin") {
return RustBuiltin::Builtin;
}
if (cmd == L"contains") {
return RustBuiltin::Contains;
}

View file

@ -7,6 +7,7 @@
#include "common.h"
#include "complete.h"
#include "maybe.h"
#include "wutil.h"
class parser_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);
wcstring_list_t builtin_get_names();
wcstring_list_ffi_t builtin_get_names_ffi();
void builtin_get_names(completion_list_t *list);
const wchar_t *builtin_get_desc(const wcstring &name);
@ -112,6 +114,7 @@ enum RustBuiltin : int32_t {
Abbr,
Bg,
Block,
Builtin,
Contains,
Command,
Echo,

View file

@ -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;
}

View file

@ -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