mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 21:33:09 +00:00
Port builtin count to rust (#9963)
* Port builtin count to rust * Explicitly use wstring
This commit is contained in:
parent
a29aa44183
commit
566123edc6
5 changed files with 40 additions and 37 deletions
33
fish-rust/src/builtins/count.rs
Normal file
33
fish-rust/src/builtins/count.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
use super::prelude::*;
|
||||
|
||||
// How many bytes we read() at once.
|
||||
// Since this is just for counting, it can be massive.
|
||||
const COUNT_CHUNK_SIZE: usize = 512 * 256;
|
||||
|
||||
/// Implementation of the builtin count command, used to count the number of arguments sent to it.
|
||||
pub fn count(
|
||||
_parser: &mut parser_t,
|
||||
streams: &mut io_streams_t,
|
||||
argv: &mut [&wstr],
|
||||
) -> Option<c_int> {
|
||||
// Always add the size of argv (minus 0, which is "count").
|
||||
// That means if you call `something | count a b c`, you'll get the count of something _plus 3_.
|
||||
let mut numargs = argv.len() - 1;
|
||||
|
||||
// (silly variable for Arguments to do nothing with)
|
||||
let mut zero = 0;
|
||||
|
||||
// Count the newlines coming in via stdin like `wc -l`.
|
||||
// This means excluding lines that don't end in a newline!
|
||||
numargs += Arguments::new(&[] as _, &mut zero, streams, COUNT_CHUNK_SIZE)
|
||||
// second is "want_newline" - whether the line ended in a newline
|
||||
.filter(|x| x.1)
|
||||
.count();
|
||||
|
||||
streams.out.appendln(numargs.to_wstring());
|
||||
|
||||
if numargs == 0 {
|
||||
return STATUS_CMD_ERROR;
|
||||
}
|
||||
STATUS_CMD_OK
|
||||
}
|
|
@ -8,6 +8,7 @@ pub mod builtin;
|
|||
pub mod cd;
|
||||
pub mod command;
|
||||
pub mod contains;
|
||||
pub mod count;
|
||||
pub mod echo;
|
||||
pub mod emit;
|
||||
pub mod exit;
|
||||
|
|
|
@ -240,6 +240,7 @@ pub fn run_builtin(
|
|||
RustBuiltin::Cd => super::cd::cd(parser, streams, args),
|
||||
RustBuiltin::Contains => super::contains::contains(parser, streams, args),
|
||||
RustBuiltin::Command => super::command::command(parser, streams, args),
|
||||
RustBuiltin::Count => super::count::count(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),
|
||||
|
|
|
@ -210,42 +210,6 @@ static maybe_t<int> implemented_in_rust(parser_t &, io_streams_t &, const wchar_
|
|||
DIE("builtin is implemented in Rust, this should not be called");
|
||||
}
|
||||
|
||||
// How many bytes we read() at once.
|
||||
// Since this is just for counting, it can be massive.
|
||||
#define COUNT_CHUNK_SIZE (512 * 256)
|
||||
/// Implementation of the builtin count command, used to count the number of arguments sent to it.
|
||||
static maybe_t<int> builtin_count(parser_t &parser, io_streams_t &streams, const wchar_t **argv) {
|
||||
UNUSED(parser);
|
||||
int argc = 0;
|
||||
|
||||
// Count the newlines coming in via stdin like `wc -l`.
|
||||
if (streams.stdin_is_directly_redirected) {
|
||||
assert(streams.stdin_fd >= 0 &&
|
||||
"Should have a valid fd since stdin is directly redirected");
|
||||
char buf[COUNT_CHUNK_SIZE];
|
||||
while (true) {
|
||||
long n = read_blocked(streams.stdin_fd, buf, COUNT_CHUNK_SIZE);
|
||||
if (n == 0) {
|
||||
break;
|
||||
} else if (n < 0) {
|
||||
wperror(L"read");
|
||||
return STATUS_CMD_ERROR;
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (buf[i] == '\n') {
|
||||
argc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Always add the size of argv.
|
||||
// That means if you call `something | count a b c`, you'll get the count of something _plus 3_.
|
||||
argc += builtin_count_args(argv) - 1;
|
||||
streams.out.append_format(L"%d\n", argc);
|
||||
return argc == 0 ? STATUS_CMD_ERROR : STATUS_CMD_OK;
|
||||
}
|
||||
|
||||
/// This function handles both the 'continue' and the 'break' builtins that are used for loop
|
||||
/// control.
|
||||
static maybe_t<int> builtin_break_continue(parser_t &parser, io_streams_t &streams,
|
||||
|
@ -359,7 +323,7 @@ static constexpr builtin_data_t builtin_datas[] = {
|
|||
{L"complete", &builtin_complete, N_(L"Edit command specific completions")},
|
||||
{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"count", &implemented_in_rust, N_(L"Count the number of arguments")},
|
||||
{L"disown", &builtin_disown, N_(L"Remove job from job list")},
|
||||
{L"echo", &implemented_in_rust, N_(L"Print arguments")},
|
||||
{L"else", &builtin_generic, N_(L"Evaluate block if condition is false")},
|
||||
|
@ -539,6 +503,9 @@ static maybe_t<RustBuiltin> try_get_rust_builtin(const wcstring &cmd) {
|
|||
if (cmd == L"command") {
|
||||
return RustBuiltin::Command;
|
||||
}
|
||||
if (cmd == L"count") {
|
||||
return RustBuiltin::Count;
|
||||
}
|
||||
if (cmd == L"echo") {
|
||||
return RustBuiltin::Echo;
|
||||
}
|
||||
|
|
|
@ -120,6 +120,7 @@ enum class RustBuiltin : int32_t {
|
|||
Cd,
|
||||
Contains,
|
||||
Command,
|
||||
Count,
|
||||
Echo,
|
||||
Emit,
|
||||
Exit,
|
||||
|
|
Loading…
Reference in a new issue