From fef358fc74baf2b435747027198aca0d4aee8b5a Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Sat, 11 Oct 2025 09:32:05 +0200 Subject: [PATCH] Move remaining builtin implementations to dedicated files This makes them a bit easier to find I guess. --- src/builtins/break.rs | 5 +++ src/builtins/breakpoint.rs | 44 ++++++++++++++++++++ src/builtins/continue.rs | 5 +++ src/builtins/false.rs | 5 +++ src/builtins/gettext.rs | 14 +++++++ src/builtins/mod.rs | 6 +++ src/builtins/shared.rs | 85 ++++---------------------------------- src/builtins/true.rs | 5 +++ 8 files changed, 93 insertions(+), 76 deletions(-) create mode 100644 src/builtins/break.rs create mode 100644 src/builtins/breakpoint.rs create mode 100644 src/builtins/continue.rs create mode 100644 src/builtins/false.rs create mode 100644 src/builtins/gettext.rs create mode 100644 src/builtins/true.rs diff --git a/src/builtins/break.rs b/src/builtins/break.rs new file mode 100644 index 000000000..67bf721c2 --- /dev/null +++ b/src/builtins/break.rs @@ -0,0 +1,5 @@ +use super::prelude::*; + +pub fn r#break(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> BuiltinResult { + builtin_break_continue(parser, streams, argv) +} diff --git a/src/builtins/breakpoint.rs b/src/builtins/breakpoint.rs new file mode 100644 index 000000000..1e411158a --- /dev/null +++ b/src/builtins/breakpoint.rs @@ -0,0 +1,44 @@ +use super::prelude::*; +use crate::parser::{Block, BlockType}; +use crate::reader::reader_read; +use libc::STDIN_FILENO; + +/// Implementation of the builtin breakpoint command, used to launch the interactive debugger. +pub fn breakpoint(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> BuiltinResult { + let cmd = argv[0]; + if argv.len() != 1 { + streams.err.append(wgettext_fmt!( + BUILTIN_ERR_ARG_COUNT1, + cmd, + 0, + argv.len() - 1 + )); + return Err(STATUS_INVALID_ARGS); + } + + // If we're not interactive then we can't enter the debugger. So treat this command as a no-op. + if !parser.is_interactive() { + return Err(STATUS_CMD_ERROR); + } + + // Ensure we don't allow creating a breakpoint at an interactive prompt. There may be a simpler + // or clearer way to do this but this works. + { + if parser + .block_at_index(1) + .map_or(true, |b| b.typ() == BlockType::breakpoint) + { + streams.err.append(wgettext_fmt!( + "%s: Command not valid at an interactive prompt\n", + cmd, + )); + return Err(STATUS_ILLEGAL_CMD); + } + } + + let bpb = parser.push_block(Block::breakpoint_block()); + let io_chain = &streams.io_chain; + reader_read(parser, STDIN_FILENO, io_chain)?; + parser.pop_block(bpb); + BuiltinResult::from_dynamic(parser.get_last_status()) +} diff --git a/src/builtins/continue.rs b/src/builtins/continue.rs new file mode 100644 index 000000000..d318fb1e3 --- /dev/null +++ b/src/builtins/continue.rs @@ -0,0 +1,5 @@ +use super::prelude::*; + +pub fn r#continue(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> BuiltinResult { + builtin_break_continue(parser, streams, argv) +} diff --git a/src/builtins/false.rs b/src/builtins/false.rs new file mode 100644 index 000000000..f6ed68014 --- /dev/null +++ b/src/builtins/false.rs @@ -0,0 +1,5 @@ +use super::prelude::*; + +pub fn r#false(_parser: &Parser, _streams: &mut IoStreams, _argv: &mut [&wstr]) -> BuiltinResult { + Err(STATUS_CMD_ERROR) +} diff --git a/src/builtins/gettext.rs b/src/builtins/gettext.rs new file mode 100644 index 000000000..6e73269e3 --- /dev/null +++ b/src/builtins/gettext.rs @@ -0,0 +1,14 @@ +use super::prelude::*; + +/// Used for the fish `_` builtin for requesting translations. +/// For scripts in `share/`, the corresponding strings are extracted from the scripts using +/// `build_tools/fish_xgettext.fish`. +/// Strings not present in our repo would require a custom MO file for translation to be possible. +pub fn gettext(_parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> BuiltinResult { + for arg in &argv[1..] { + streams.out.append( + crate::wutil::LocalizableString::from_external_source((*arg).to_owned()).localize(), + ); + } + Ok(SUCCESS) +} diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index 6aa270097..d95d758f7 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -5,23 +5,28 @@ pub mod bg; pub mod bind; pub mod block; +pub mod r#break; +pub mod breakpoint; pub mod builtin; pub mod cd; pub mod command; pub mod commandline; pub mod complete; pub mod contains; +pub mod r#continue; pub mod count; pub mod disown; pub mod echo; pub mod emit; pub mod eval; pub mod exit; +pub mod r#false; pub mod fg; pub mod fish_indent; pub mod fish_key_reader; pub mod function; pub mod functions; +pub mod r#gettext; pub mod history; pub mod jobs; pub mod math; @@ -38,6 +43,7 @@ pub mod status; pub mod string; pub mod test; +pub mod r#true; pub mod r#type; pub mod ulimit; pub mod wait; diff --git a/src/builtins/shared.rs b/src/builtins/shared.rs index c48e02d30..f0eedbc95 100644 --- a/src/builtins/shared.rs +++ b/src/builtins/shared.rs @@ -4,12 +4,10 @@ use crate::io::OutputStream; use crate::parse_constants::UNKNOWN_BUILTIN_ERR_MSG; use crate::parse_util::parse_util_argument_is_help; -use crate::parser::{Block, BlockType, LoopStatus}; +use crate::parser::{BlockType, LoopStatus}; use crate::proc::{no_exec, ProcStatus}; -use crate::reader::reader_read; use crate::wchar::L; use errno::errno; -use libc::STDIN_FILENO; use std::fs::File; use std::io::{BufRead, BufReader, Read}; @@ -193,7 +191,7 @@ struct BuiltinData { }, BuiltinData { name: L!(":"), - func: builtin_true, + func: r#true::r#true, }, BuiltinData { name: L!("["), // ] @@ -201,7 +199,7 @@ struct BuiltinData { }, BuiltinData { name: L!("_"), - func: builtin_gettext, + func: gettext::gettext, }, BuiltinData { name: L!("abbr"), @@ -233,11 +231,11 @@ struct BuiltinData { }, BuiltinData { name: L!("break"), - func: builtin_break_continue, + func: r#break::r#break, }, BuiltinData { name: L!("breakpoint"), - func: builtin_breakpoint, + func: breakpoint::breakpoint, }, BuiltinData { name: L!("builtin"), @@ -269,7 +267,7 @@ struct BuiltinData { }, BuiltinData { name: L!("continue"), - func: builtin_break_continue, + func: r#continue::r#continue, }, BuiltinData { name: L!("count"), @@ -309,7 +307,7 @@ struct BuiltinData { }, BuiltinData { name: L!("false"), - func: builtin_false, + func: r#false::r#false, }, BuiltinData { name: L!("fg"), @@ -421,7 +419,7 @@ struct BuiltinData { }, BuiltinData { name: L!("true"), - func: builtin_true, + func: r#true::r#true, }, BuiltinData { name: L!("type"), @@ -954,7 +952,7 @@ fn builtin_generic(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) /// This function handles both the 'continue' and the 'break' builtins that are used for loop /// control. -fn builtin_break_continue( +pub fn builtin_break_continue( parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr], @@ -1003,68 +1001,3 @@ fn builtin_break_continue( }; Ok(SUCCESS) } - -/// Implementation of the builtin breakpoint command, used to launch the interactive debugger. -fn builtin_breakpoint( - parser: &Parser, - streams: &mut IoStreams, - argv: &mut [&wstr], -) -> BuiltinResult { - let cmd = argv[0]; - if argv.len() != 1 { - streams.err.append(wgettext_fmt!( - BUILTIN_ERR_ARG_COUNT1, - cmd, - 0, - argv.len() - 1 - )); - return Err(STATUS_INVALID_ARGS); - } - - // If we're not interactive then we can't enter the debugger. So treat this command as a no-op. - if !parser.is_interactive() { - return Err(STATUS_CMD_ERROR); - } - - // Ensure we don't allow creating a breakpoint at an interactive prompt. There may be a simpler - // or clearer way to do this but this works. - { - if parser - .block_at_index(1) - .map_or(true, |b| b.typ() == BlockType::breakpoint) - { - streams.err.append(wgettext_fmt!( - "%s: Command not valid at an interactive prompt\n", - cmd, - )); - return Err(STATUS_ILLEGAL_CMD); - } - } - - let bpb = parser.push_block(Block::breakpoint_block()); - let io_chain = &streams.io_chain; - reader_read(parser, STDIN_FILENO, io_chain)?; - parser.pop_block(bpb); - BuiltinResult::from_dynamic(parser.get_last_status()) -} - -fn builtin_true(_parser: &Parser, _streams: &mut IoStreams, _argv: &mut [&wstr]) -> BuiltinResult { - Ok(SUCCESS) -} - -fn builtin_false(_parser: &Parser, _streams: &mut IoStreams, _argv: &mut [&wstr]) -> BuiltinResult { - Err(STATUS_CMD_ERROR) -} - -/// Used for the fish `_` builtin for requesting translations. -/// For scripts in `share/`, the corresponding strings are extracted from the scripts using -/// `build_tools/fish_xgettext.fish`. -/// Strings not present in our repo would require a custom MO file for translation to be possible. -fn builtin_gettext(_parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> BuiltinResult { - for arg in &argv[1..] { - streams.out.append( - crate::wutil::LocalizableString::from_external_source((*arg).to_owned()).localize(), - ); - } - Ok(SUCCESS) -} diff --git a/src/builtins/true.rs b/src/builtins/true.rs new file mode 100644 index 000000000..fbaa6dfd0 --- /dev/null +++ b/src/builtins/true.rs @@ -0,0 +1,5 @@ +use super::prelude::*; + +pub fn r#true(_parser: &Parser, _streams: &mut IoStreams, _argv: &mut [&wstr]) -> BuiltinResult { + Ok(SUCCESS) +}