mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-07 18:21:16 -03:00
contains: port contains builtin to rust
This commit is contained in:
committed by
Johannes Altmanninger
parent
a601babcf0
commit
3b60bc1de0
@@ -102,7 +102,7 @@ set(FISH_BUILTIN_SRCS
|
||||
src/builtin.cpp src/builtins/abbr.cpp src/builtins/argparse.cpp
|
||||
src/builtins/bg.cpp src/builtins/bind.cpp src/builtins/block.cpp
|
||||
src/builtins/builtin.cpp src/builtins/cd.cpp src/builtins/command.cpp
|
||||
src/builtins/commandline.cpp src/builtins/complete.cpp src/builtins/contains.cpp
|
||||
src/builtins/commandline.cpp src/builtins/complete.cpp
|
||||
src/builtins/disown.cpp
|
||||
src/builtins/eval.cpp src/builtins/fg.cpp
|
||||
src/builtins/function.cpp src/builtins/functions.cpp src/builtins/history.cpp
|
||||
|
||||
93
fish-rust/src/builtins/contains.rs
Normal file
93
fish-rust/src/builtins/contains.rs
Normal file
@@ -0,0 +1,93 @@
|
||||
// Implementation of the contains builtin.
|
||||
use super::shared::{
|
||||
builtin_missing_argument, builtin_print_help, io_streams_t, STATUS_CMD_ERROR, STATUS_CMD_OK,
|
||||
STATUS_INVALID_ARGS,
|
||||
};
|
||||
use crate::builtins::shared::builtin_unknown_option;
|
||||
use crate::ffi::parser_t;
|
||||
use crate::wchar::{wstr, L};
|
||||
use crate::wgetopt::{wgetopter_t, wopt, woption, woption_argument_t};
|
||||
use crate::wutil::wgettext_fmt;
|
||||
use libc::c_int;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
struct Options {
|
||||
print_help: bool,
|
||||
print_index: bool,
|
||||
}
|
||||
|
||||
fn parse_options(
|
||||
args: &mut [&wstr],
|
||||
parser: &mut parser_t,
|
||||
streams: &mut io_streams_t,
|
||||
) -> Result<(Options, usize), Option<c_int>> {
|
||||
let cmd = args[0];
|
||||
|
||||
const SHORT_OPTS: &wstr = L!("+:hi");
|
||||
const LONG_OPTS: &[woption] = &[
|
||||
wopt(L!("help"), woption_argument_t::no_argument, 'h'),
|
||||
wopt(L!("index"), woption_argument_t::no_argument, 'i'),
|
||||
];
|
||||
|
||||
let mut opts = Options::default();
|
||||
|
||||
let mut w = wgetopter_t::new(SHORT_OPTS, LONG_OPTS, args);
|
||||
while let Some(c) = w.wgetopt_long() {
|
||||
match c {
|
||||
'h' => opts.print_help = true,
|
||||
'i' => opts.print_index = true,
|
||||
':' => {
|
||||
builtin_missing_argument(parser, streams, cmd, args[w.woptind - 1], false);
|
||||
return Err(STATUS_INVALID_ARGS);
|
||||
}
|
||||
'?' => {
|
||||
builtin_unknown_option(parser, streams, cmd, args[w.woptind - 1], false);
|
||||
return Err(STATUS_INVALID_ARGS);
|
||||
}
|
||||
_ => {
|
||||
panic!("unexpected retval from wgetopt_long");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok((opts, w.woptind))
|
||||
}
|
||||
|
||||
/// Implementation of the builtin contains command, used to check if a specified string is part of
|
||||
/// a list.
|
||||
pub fn contains(
|
||||
parser: &mut parser_t,
|
||||
streams: &mut io_streams_t,
|
||||
args: &mut [&wstr],
|
||||
) -> Option<c_int> {
|
||||
let cmd = args[0];
|
||||
|
||||
let (opts, optind) = match parse_options(args, parser, streams) {
|
||||
Ok((opts, optind)) => (opts, optind),
|
||||
Err(err @ Some(_)) if err != STATUS_CMD_OK => return err,
|
||||
Err(err) => panic!("Illogical exit code from parse_options(): {err:?}"),
|
||||
};
|
||||
|
||||
if opts.print_help {
|
||||
builtin_print_help(parser, streams, cmd);
|
||||
return STATUS_CMD_OK;
|
||||
}
|
||||
|
||||
let needle = args.get(optind);
|
||||
if let Some(needle) = needle {
|
||||
for (i, arg) in args[optind..].iter().enumerate().skip(1) {
|
||||
if needle == arg {
|
||||
if opts.print_index {
|
||||
streams.out.append(wgettext_fmt!("%d\n", i));
|
||||
}
|
||||
return STATUS_CMD_OK;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
streams
|
||||
.err
|
||||
.append(wgettext_fmt!("%ls: Key not specified\n", cmd));
|
||||
}
|
||||
|
||||
return STATUS_CMD_ERROR;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod shared;
|
||||
|
||||
pub mod contains;
|
||||
pub mod echo;
|
||||
pub mod emit;
|
||||
pub mod exit;
|
||||
|
||||
@@ -40,6 +40,9 @@ impl Vec<wcharz_t> {}
|
||||
/// A handy return value for successful builtins.
|
||||
pub const STATUS_CMD_OK: Option<c_int> = Some(0);
|
||||
|
||||
/// The status code used for failure exit in a command (but not if the args were invalid).
|
||||
pub const STATUS_CMD_ERROR: Option<c_int> = Some(1);
|
||||
|
||||
/// A handy return value for invalid args.
|
||||
pub const STATUS_INVALID_ARGS: Option<c_int> = Some(2);
|
||||
|
||||
@@ -115,6 +118,7 @@ pub fn run_builtin(
|
||||
builtin: RustBuiltin,
|
||||
) -> Option<c_int> {
|
||||
match builtin {
|
||||
RustBuiltin::Contains => super::contains::contains(parser, streams, args),
|
||||
RustBuiltin::Echo => super::echo::echo(parser, streams, args),
|
||||
RustBuiltin::Emit => super::emit::emit(parser, streams, args),
|
||||
RustBuiltin::Exit => super::exit::exit(parser, streams, args),
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include "builtins/command.h"
|
||||
#include "builtins/commandline.h"
|
||||
#include "builtins/complete.h"
|
||||
#include "builtins/contains.h"
|
||||
#include "builtins/disown.h"
|
||||
#include "builtins/eval.h"
|
||||
#include "builtins/fg.h"
|
||||
@@ -375,7 +374,7 @@ static constexpr builtin_data_t builtin_datas[] = {
|
||||
{L"command", &builtin_command, N_(L"Run a command specifically")},
|
||||
{L"commandline", &builtin_commandline, N_(L"Set or get the commandline")},
|
||||
{L"complete", &builtin_complete, N_(L"Edit command specific completions")},
|
||||
{L"contains", &builtin_contains, N_(L"Search for a specified string in a list")},
|
||||
{L"contains", &implemented_in_rust, N_(L"Search for a specified string in a list")},
|
||||
{L"continue", &builtin_break_continue, N_(L"Skip over remaining innermost loop")},
|
||||
{L"count", &builtin_count, N_(L"Count the number of arguments")},
|
||||
{L"disown", &builtin_disown, N_(L"Remove job from job list")},
|
||||
@@ -524,6 +523,9 @@ const wchar_t *builtin_get_desc(const wcstring &name) {
|
||||
}
|
||||
|
||||
static maybe_t<RustBuiltin> try_get_rust_builtin(const wcstring &cmd) {
|
||||
if (cmd == L"contains") {
|
||||
return RustBuiltin::Contains;
|
||||
}
|
||||
if (cmd == L"echo") {
|
||||
return RustBuiltin::Echo;
|
||||
}
|
||||
|
||||
@@ -109,6 +109,7 @@ int parse_help_only_cmd_opts(help_only_cmd_opts_t &opts, int *optind, int argc,
|
||||
|
||||
/// An enum of the builtins implemented in Rust.
|
||||
enum RustBuiltin : int32_t {
|
||||
Contains,
|
||||
Echo,
|
||||
Emit,
|
||||
Exit,
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
// Implementation of the contains builtin.
|
||||
#include "config.h" // IWYU pragma: keep
|
||||
|
||||
#include "contains.h"
|
||||
|
||||
#include <cwchar>
|
||||
|
||||
#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 contains_cmd_opts_t {
|
||||
bool print_help = false;
|
||||
bool print_index = false;
|
||||
};
|
||||
static const wchar_t *const short_options = L"+:hi";
|
||||
static const struct woption long_options[] = {
|
||||
{L"help", no_argument, 'h'}, {L"index", no_argument, 'i'}, {}};
|
||||
|
||||
static int parse_cmd_opts(contains_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 'i': {
|
||||
opts.print_index = 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;
|
||||
}
|
||||
|
||||
/// Implementation of the builtin contains command, used to check if a specified string is part of
|
||||
/// a list.
|
||||
maybe_t<int> builtin_contains(parser_t &parser, io_streams_t &streams, const wchar_t **argv) {
|
||||
const wchar_t *cmd = argv[0];
|
||||
int argc = builtin_count_args(argv);
|
||||
contains_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;
|
||||
}
|
||||
|
||||
const wchar_t *needle = argv[optind];
|
||||
if (!needle) {
|
||||
streams.err.append_format(_(L"%ls: Key not specified\n"), cmd);
|
||||
} else {
|
||||
for (int i = optind + 1; i < argc; i++) {
|
||||
if (!std::wcscmp(needle, argv[i])) {
|
||||
if (opts.print_index) streams.out.append_format(L"%d\n", i - optind);
|
||||
return STATUS_CMD_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_CMD_ERROR;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
// Prototypes for executing builtin_contains function.
|
||||
#ifndef FISH_BUILTIN_CONTAINS_H
|
||||
#define FISH_BUILTIN_CONTAINS_H
|
||||
|
||||
#include "../maybe.h"
|
||||
|
||||
class parser_t;
|
||||
struct io_streams_t;
|
||||
|
||||
maybe_t<int> builtin_contains(parser_t &parser, io_streams_t &streams, const wchar_t **argv);
|
||||
#endif
|
||||
Reference in New Issue
Block a user