From 2f37eda9d92bc2d54a995711c7b1cbb6b55775d6 Mon Sep 17 00:00:00 2001 From: Daniel Rainer Date: Wed, 17 Dec 2025 23:45:35 +0100 Subject: [PATCH] wchar: extract logic into separate crate Another reduction in size of the main crate. Also allows other crates to depend on the new wchar crate. The original `src/wchar.rs` file is kept around for now to keep the prelude imports working. Part of #12182 --- Cargo.lock | 9 ++++ Cargo.toml | 2 + crates/wchar/Cargo.toml | 14 +++++ src/wchar_ext.rs => crates/wchar/src/lib.rs | 55 ++++++++++++++++--- src/autoload.rs | 3 +- src/builtins/disown.rs | 3 +- src/builtins/echo.rs | 2 +- src/builtins/jobs.rs | 7 +-- src/builtins/printf.rs | 2 +- src/builtins/shared.rs | 2 +- src/common.rs | 10 ++-- src/complete.rs | 25 +++++---- src/env/var.rs | 2 +- src/env_universal_common.rs | 3 +- src/exec.rs | 2 +- src/highlight/file_tester.rs | 3 +- src/highlight/highlight.rs | 3 +- src/input_common.rs | 3 +- src/key.rs | 3 +- src/lib.rs | 1 - src/parse_execution.rs | 2 +- src/parser.rs | 2 +- src/proc.rs | 2 +- src/topic_monitor.rs | 2 +- src/tty_handoff.rs | 2 +- src/universal_notifier/inotify.rs | 6 +-- src/universal_notifier/kqueue.rs | 6 +-- src/wchar.rs | 59 ++------------------- src/wcstringutil.rs | 3 +- src/wutil/dir_iter.rs | 7 +-- src/wutil/mod.rs | 7 ++- src/wutil/wcstod.rs | 2 +- 32 files changed, 128 insertions(+), 126 deletions(-) create mode 100644 crates/wchar/Cargo.toml rename src/wchar_ext.rs => crates/wchar/src/lib.rs (87%) diff --git a/Cargo.lock b/Cargo.lock index 1425d029d..28c80273d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -166,6 +166,7 @@ dependencies = [ "fish-gettext-mo-file-parser", "fish-printf", "fish-tempfile", + "fish-wchar", "fish-widecharwidth", "libc", "lru", @@ -256,6 +257,14 @@ dependencies = [ "rand 0.9.2", ] +[[package]] +name = "fish-wchar" +version = "0.0.0" +dependencies = [ + "fish-common", + "widestring", +] + [[package]] name = "fish-widecharwidth" version = "0.0.0" diff --git a/Cargo.toml b/Cargo.toml index 7285b5aac..f87bfa170 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ fish-gettext-maps = { path = "crates/gettext-maps" } fish-gettext-mo-file-parser = { path = "crates/gettext-mo-file-parser" } fish-printf = { path = "crates/printf", features = ["widestring"] } fish-tempfile = { path = "crates/tempfile" } +fish-wchar = { path = "crates/wchar" } fish-widecharwidth = { path = "crates/widecharwidth" } libc = "0.2.177" # lru pulls in hashbrown by default, which uses a faster (though less DoS resistant) hashing algo. @@ -96,6 +97,7 @@ fish-gettext = { workspace = true, optional = true } fish-gettext-extraction = { workspace = true, optional = true } fish-printf.workspace = true fish-tempfile.workspace = true +fish-wchar.workspace = true fish-widecharwidth.workspace = true libc.workspace = true lru.workspace = true diff --git a/crates/wchar/Cargo.toml b/crates/wchar/Cargo.toml new file mode 100644 index 000000000..1525719fe --- /dev/null +++ b/crates/wchar/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "fish-wchar" +edition.workspace = true +rust-version.workspace = true +version = "0.0.0" +repository.workspace = true +license.workspace = true + +[dependencies] +fish-common.workspace = true +widestring.workspace = true + +[lints] +workspace = true diff --git a/src/wchar_ext.rs b/crates/wchar/src/lib.rs similarity index 87% rename from src/wchar_ext.rs rename to crates/wchar/src/lib.rs index f2cbe11cf..1df1e5279 100644 --- a/src/wchar_ext.rs +++ b/crates/wchar/src/lib.rs @@ -1,11 +1,51 @@ -use std::{iter, slice}; +//! Support for wide strings. +//! +//! There are two wide string types that are commonly used: +//! - wstr: a string slice without a nul terminator. Like `&str` but wide chars. +//! - WString: an owning string without a nul terminator. Like `String` but wide chars. -use crate::{ - L, - wchar::{WString, wstr}, -}; -use fish_common::subslice_position; -use widestring::utfstr::CharsUtf32; +use fish_common::{ENCODE_DIRECT_BASE, ENCODE_DIRECT_END, subslice_position}; +use std::{iter, slice}; +pub use widestring::{Utf32Str as wstr, Utf32String as WString, utfstr::CharsUtf32}; + +pub mod prelude { + pub use crate::{IntoCharIter, L, ToWString, WExt, WString, wstr}; +} + +/// Creates a wstr string slice, like the "L" prefix of C++. +/// The result is of type wstr. +/// It is NOT nul-terminated. +#[macro_export] +macro_rules! L { + ($string:expr) => { + widestring::utf32str!($string) + }; +} + +/// Encode a literal byte in a UTF-32 character. This is required for e.g. the echo builtin, whose +/// escape sequences can be used to construct raw byte sequences which are then interpreted as e.g. +/// UTF-8 by the terminal. If we were to interpret each of those bytes as a codepoint and encode it +/// as a UTF-32 character, printing them would result in several characters instead of one UTF-8 +/// character. +/// +/// See . +pub fn encode_byte_to_char(byte: u8) -> char { + char::from_u32(u32::from(ENCODE_DIRECT_BASE) + u32::from(byte)) + .expect("private-use codepoint should be valid char") +} + +/// Decode a literal byte from a UTF-32 character. +pub fn decode_byte_from_char(c: char) -> Option { + if c >= ENCODE_DIRECT_BASE && c < ENCODE_DIRECT_END { + Some( + (u32::from(c) - u32::from(ENCODE_DIRECT_BASE)) + .try_into() + .unwrap(), + ) + } else { + None + } +} /// Helpers to convert things to widestring. /// This is like std::string::ToString. @@ -303,7 +343,6 @@ fn as_char_slice(&self) -> &[char] { #[cfg(test)] mod tests { use super::*; - use crate::wchar::L; #[test] fn test_to_wstring() { diff --git a/src/autoload.rs b/src/autoload.rs index 1a4980fed..b223573df 100644 --- a/src/autoload.rs +++ b/src/autoload.rs @@ -6,9 +6,8 @@ use crate::flogf; use crate::io::IoChain; use crate::parser::Parser; -use crate::wchar::{L, WString, wstr}; -use crate::wchar_ext::WExt; use crate::wutil::{FileId, INVALID_FILE_ID, file_id_for_path}; +use fish_wchar::{L, WExt, WString, wstr}; use lru::LruCache; use rust_embed::RustEmbed; use std::collections::{HashMap, HashSet}; diff --git a/src/builtins/disown.rs b/src/builtins/disown.rs index 996b3f90d..05513571b 100644 --- a/src/builtins/disown.rs +++ b/src/builtins/disown.rs @@ -4,7 +4,8 @@ use crate::io::IoStreams; use crate::parser::Parser; use crate::proc::{Job, add_disowned_job}; -use crate::{builtins::shared::HelpOnlyCmdOpts, wchar::wstr, wutil::wgettext_fmt}; +use crate::{builtins::shared::HelpOnlyCmdOpts, wutil::wgettext_fmt}; +use fish_wchar::wstr; use libc::SIGCONT; /// Helper for builtin_disown. diff --git a/src/builtins/echo.rs b/src/builtins/echo.rs index 069e266b3..42865d39f 100644 --- a/src/builtins/echo.rs +++ b/src/builtins/echo.rs @@ -1,7 +1,7 @@ //! Implementation of the echo builtin. use super::prelude::*; -use crate::wchar::encode_byte_to_char; +use fish_wchar::encode_byte_to_char; #[derive(Debug, Clone, Copy)] struct Options { diff --git a/src/builtins/jobs.rs b/src/builtins/jobs.rs index d43d0a704..096a7217d 100644 --- a/src/builtins/jobs.rs +++ b/src/builtins/jobs.rs @@ -6,13 +6,10 @@ use crate::job_group::{JobId, MaybeJobId}; use crate::parser::Parser; use crate::proc::{Job, clock_ticks_to_seconds, have_proc_stat, proc_get_jiffies}; -use crate::wchar_ext::WExt; use crate::wgetopt::{ArgType, WGetopter, WOption, wopt}; use crate::wutil::wgettext; -use crate::{ - wchar::{L, WString, wstr}, - wutil::{fish_wcstoi, wgettext_fmt}, -}; +use crate::wutil::{fish_wcstoi, wgettext_fmt}; +use fish_wchar::{L, WExt, WString, wstr}; use std::num::NonZeroU32; /// Print modes for the jobs builtin. diff --git a/src/builtins/printf.rs b/src/builtins/printf.rs index 53f6b1be3..0a454f481 100644 --- a/src/builtins/printf.rs +++ b/src/builtins/printf.rs @@ -50,7 +50,6 @@ use super::prelude::*; use crate::locale::{Locale, get_numeric_locale}; -use crate::wchar::{decode_byte_from_char, encode_byte_to_char}; use crate::wutil::{ errors::Error, wcstod::wcstod, @@ -58,6 +57,7 @@ wstr_offset_in, }; use fish_printf::{ToArg, sprintf_locale}; +use fish_wchar::{decode_byte_from_char, encode_byte_to_char}; /// Return true if `c` is an octal digit. fn is_octal_digit(c: char) -> bool { diff --git a/src/builtins/shared.rs b/src/builtins/shared.rs index 8c6c268b1..7c9b37471 100644 --- a/src/builtins/shared.rs +++ b/src/builtins/shared.rs @@ -5,9 +5,9 @@ use crate::parse_util::parse_util_argument_is_help; use crate::parser::{BlockType, LoopStatus}; use crate::proc::{Pid, ProcStatus, no_exec}; -use crate::wchar::L; use crate::{builtins::*, wutil}; use errno::errno; +use fish_wchar::L; use std::fs::File; use std::io::{BufRead, BufReader, Read}; diff --git a/src/common.rs b/src/common.rs index 915d8d213..0d25100d7 100644 --- a/src/common.rs +++ b/src/common.rs @@ -12,12 +12,13 @@ use crate::parse_util::parse_util_escape_string_with_quote; use crate::terminal::Output; use crate::termsize::Termsize; -use crate::wchar::{decode_byte_from_char, encode_byte_to_char, prelude::*}; +use crate::wchar::prelude::*; use crate::wcstringutil::wcs2bytes_callback; use crate::wildcard::{ANY_CHAR, ANY_STRING, ANY_STRING_RECURSIVE}; use crate::wutil::fish_iswalnum; use bitflags::bitflags; use fish_common::{ENCODE_DIRECT_END, char_offset, subslice_position}; +use fish_wchar::{decode_byte_from_char, encode_byte_to_char}; use libc::{SIG_IGN, SIGTTOU, STDIN_FILENO}; use once_cell::sync::OnceCell; use std::cell::{Cell, RefCell}; @@ -1995,16 +1996,15 @@ macro_rules! env_stack_set_from_env { #[cfg(test)] mod tests { + use super::{ ENCODE_DIRECT_END, ESCAPE_TEST_CHAR, EscapeFlags, EscapeStringStyle, ScopeGuard, ScopedCell, ScopedRefCell, UnescapeStringStyle, bytes2wcstring, escape_string, truncate_at_nul, unescape_string, wcs2bytes, }; - use crate::{ - util::get_seeded_rng, - wchar::{L, WString, wstr}, - }; + use crate::util::get_seeded_rng; use fish_common::ENCODE_DIRECT_BASE; + use fish_wchar::{L, WString, wstr}; use rand::{Rng, RngCore}; #[test] diff --git a/src/complete.rs b/src/complete.rs index 4efff53fb..2af74badf 100644 --- a/src/complete.rs +++ b/src/complete.rs @@ -10,18 +10,6 @@ time::{Duration, Instant}, }; -use crate::{ - ast::unescape_keyword, - autoload::AutoloadResult, - common::charptr2wcstring, - reader::{get_quote, is_backslashed}, - util::wcsfilecmp, - wcstringutil::{string_suffixes_string_case_insensitive, strip_executable_suffix}, - wutil::{LocalizableString, localizable_string}, -}; -use bitflags::bitflags; -use once_cell::sync::Lazy; - use crate::{ abbrs::with_abbrs, autoload::Autoload, @@ -49,7 +37,6 @@ path::{path_get_path, path_try_get_path}, tokenizer::{Tok, TokFlags, TokenType, Tokenizer, variable_assignment_equals_pos}, wchar::prelude::*, - wchar_ext::WExt, wcstringutil::{ StringFuzzyMatch, string_fuzzy_match_string, string_prefixes_string, string_prefixes_string_case_insensitive, @@ -57,6 +44,18 @@ wildcard::{wildcard_complete, wildcard_has, wildcard_match}, wutil::wrealpath, }; +use crate::{ + ast::unescape_keyword, + autoload::AutoloadResult, + common::charptr2wcstring, + reader::{get_quote, is_backslashed}, + util::wcsfilecmp, + wcstringutil::{string_suffixes_string_case_insensitive, strip_executable_suffix}, + wutil::{LocalizableString, localizable_string}, +}; +use bitflags::bitflags; +use fish_wchar::WExt; +use once_cell::sync::Lazy; // Completion description strings, mostly for different types of files, such as sockets, block // devices, etc. diff --git a/src/env/var.rs b/src/env/var.rs index ebece93f1..07e4b7f66 100644 --- a/src/env/var.rs +++ b/src/env/var.rs @@ -1,7 +1,7 @@ use crate::signal::Signal; -use crate::wchar::{L, WString, wstr}; use crate::wcstringutil::join_strings; use bitflags::bitflags; +use fish_wchar::{L, WString, wstr}; use libc::c_int; use std::collections::HashMap; use std::sync::Arc; diff --git a/src/env_universal_common.rs b/src/env_universal_common.rs index 94cb747bc..dfec32906 100644 --- a/src/env_universal_common.rs +++ b/src/env_universal_common.rs @@ -5,9 +5,10 @@ use crate::flog::{flog, flogf}; use crate::fs::{PotentialUpdate, lock_and_load, rewrite_via_temporary_file}; use crate::path::path_get_config; -use crate::wchar::{decode_byte_from_char, prelude::*}; +use crate::wchar::prelude::*; use crate::wcstringutil::{LineIterator, join_strings}; use crate::wutil::{FileId, INVALID_FILE_ID, file_id_for_file, file_id_for_path_narrow, wrealpath}; +use fish_wchar::decode_byte_from_char; use std::collections::HashSet; use std::collections::hash_map::Entry; use std::ffi::CString; diff --git a/src/exec.rs b/src/exec.rs index da2bd0a61..7b540baed 100644 --- a/src/exec.rs +++ b/src/exec.rs @@ -44,9 +44,9 @@ use crate::trace::trace_if_enabled_with_args; use crate::tty_handoff::TtyHandoff; use crate::wchar::prelude::*; -use crate::wchar_ext::ToWString; use crate::wutil::{fish_wcstol, perror}; use errno::{errno, set_errno}; +use fish_wchar::ToWString; use libc::{ EACCES, ENOENT, ENOEXEC, ENOTDIR, EPIPE, EXIT_FAILURE, EXIT_SUCCESS, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO, diff --git a/src/highlight/file_tester.rs b/src/highlight/file_tester.rs index 100c91761..3621881a6 100644 --- a/src/highlight/file_tester.rs +++ b/src/highlight/file_tester.rs @@ -12,8 +12,6 @@ use crate::path::path_apply_working_directory; use crate::redirection::RedirectionMode; use crate::threads::assert_is_background_thread; -use crate::wchar::{L, WString, wstr}; -use crate::wchar_ext::WExt; use crate::wcstringutil::{ string_prefixes_string, string_prefixes_string_case_insensitive, string_suffixes_string, }; @@ -21,6 +19,7 @@ use crate::wutil::{ dir_iter::DirIter, fish_wcstoi, normalize_path, waccess, wbasename, wdirname, wstat, }; +use fish_wchar::{L, WExt, WString, wstr}; use libc::PATH_MAX; use std::collections::{HashMap, HashSet}; use std::os::fd::RawFd; diff --git a/src/highlight/highlight.rs b/src/highlight/highlight.rs index 9fe6eedc6..b8431b726 100644 --- a/src/highlight/highlight.rs +++ b/src/highlight/highlight.rs @@ -30,9 +30,8 @@ use crate::text_face::{SpecifiedTextFace, TextFace, UnderlineStyle, parse_text_face}; use crate::threads::assert_is_background_thread; use crate::tokenizer::{PipeOrRedir, variable_assignment_equals_pos}; -use crate::wchar::{L, WString, wstr}; -use crate::wchar_ext::WExt; use crate::wcstringutil::string_prefixes_string; +use fish_wchar::{L, WExt, WString, wstr}; use std::collections::HashMap; use std::collections::hash_map::Entry; diff --git a/src/input_common.rs b/src/input_common.rs index 89b51def4..ce4fe935a 100644 --- a/src/input_common.rs +++ b/src/input_common.rs @@ -16,8 +16,9 @@ maybe_set_kitty_keyboard_capability, maybe_set_scroll_content_up_capability, }; use crate::universal_notifier::default_notifier; -use crate::wchar::{encode_byte_to_char, prelude::*}; +use crate::wchar::prelude::*; use crate::wutil::{fish_is_pua, fish_wcstol}; +use fish_wchar::encode_byte_to_char; use std::cell::{RefCell, RefMut}; use std::collections::VecDeque; use std::mem::MaybeUninit; diff --git a/src/key.rs b/src/key.rs index fa19faf39..1e4e3224c 100644 --- a/src/key.rs +++ b/src/key.rs @@ -6,9 +6,10 @@ flog::FloggableDebug, future_feature_flags::{FeatureFlag, test as feature_test}, reader::safe_get_terminal_mode_on_startup, - wchar::{decode_byte_from_char, prelude::*}, + wchar::prelude::*, wutil::fish_wcstoul, }; +use fish_wchar::decode_byte_from_char; pub(crate) const Backspace: char = '\u{F500}'; // below ENCODE_DIRECT_BASE pub(crate) const Delete: char = '\u{F501}'; diff --git a/src/lib.rs b/src/lib.rs index bd4f41d82..95579d29d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,7 +75,6 @@ pub mod util; pub mod wait_handle; pub mod wchar; -pub mod wchar_ext; pub mod wcstringutil; pub mod wgetopt; pub mod wildcard; diff --git a/src/parse_execution.rs b/src/parse_execution.rs index 9e759540e..ca02274c3 100644 --- a/src/parse_execution.rs +++ b/src/parse_execution.rs @@ -49,8 +49,8 @@ use crate::tokenizer::{PipeOrRedir, TokenType, variable_assignment_equals_pos}; use crate::trace::{trace_if_enabled, trace_if_enabled_with_args}; use crate::wchar::prelude::*; -use crate::wchar_ext::WExt; use crate::wildcard::wildcard_match; +use fish_wchar::WExt; use libc::{ENOTDIR, EXIT_SUCCESS, STDERR_FILENO, STDOUT_FILENO, c_int}; use std::io::ErrorKind; use std::rc::Rc; diff --git a/src/parser.rs b/src/parser.rs index c22dff982..378563603 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -32,9 +32,9 @@ use crate::util::get_time; use crate::wait_handle::WaitHandleStore; use crate::wchar::prelude::*; -use crate::wchar_ext::WExt; use crate::wutil::perror; use crate::{flog, flogf, function}; +use fish_wchar::WExt; use libc::c_int; #[cfg(not(target_has_atomic = "64"))] use portable_atomic::AtomicU64; diff --git a/src/proc.rs b/src/proc.rs index 22fdaf244..d7dadcd7a 100644 --- a/src/proc.rs +++ b/src/proc.rs @@ -20,9 +20,9 @@ use crate::topic_monitor::{GenerationsList, Topic, topic_monitor_principal}; use crate::wait_handle::{InternalJobId, WaitHandle, WaitHandleRef, WaitHandleStore}; use crate::wchar::prelude::*; -use crate::wchar_ext::ToWString; use crate::wutil::{wbasename, wperror}; use cfg_if::cfg_if; +use fish_wchar::ToWString; use libc::{ _SC_CLK_TCK, EXIT_SUCCESS, SIG_DFL, SIG_IGN, SIGABRT, SIGBUS, SIGCONT, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGKILL, SIGPIPE, SIGQUIT, SIGSEGV, SIGSYS, SIGTTOU, WCONTINUED, WEXITSTATUS, diff --git a/src/topic_monitor.rs b/src/topic_monitor.rs index 2bb776fe4..5f8b9b6b1 100644 --- a/src/topic_monitor.rs +++ b/src/topic_monitor.rs @@ -23,8 +23,8 @@ use crate::fd_readable_set::{FdReadableSet, Timeout}; use crate::fds::{self, AutoClosePipes, make_fd_nonblocking}; use crate::flog::{FloggableDebug, flog}; -use crate::wchar::WString; use crate::wutil::perror; +use fish_wchar::WString; use nix::errno::Errno; use nix::unistd; use std::cell::Cell; diff --git a/src/tty_handoff.rs b/src/tty_handoff.rs index dd4d4ed03..50c2b27c2 100644 --- a/src/tty_handoff.rs +++ b/src/tty_handoff.rs @@ -17,8 +17,8 @@ use crate::terminal::{Output, Outputter}; use crate::threads::assert_is_main_thread; use crate::wchar::prelude::*; -use crate::wchar_ext::ToWString; use crate::wutil::{perror, wcstoi}; +use fish_wchar::ToWString; use libc::{EINVAL, ENOTTY, EPERM, STDIN_FILENO, WNOHANG}; use once_cell::sync::OnceCell; use std::mem::MaybeUninit; diff --git a/src/universal_notifier/inotify.rs b/src/universal_notifier/inotify.rs index 4a40df344..e3e60fcf2 100644 --- a/src/universal_notifier/inotify.rs +++ b/src/universal_notifier/inotify.rs @@ -68,10 +68,8 @@ fn notification_fd_became_readable(&self, fd: RawFd) -> bool { #[cfg(test)] mod tests { use super::InotifyNotifier; - use crate::{ - universal_notifier::{UniversalNotifier, test_helpers::test_notifiers}, - wchar::WString, - }; + use crate::universal_notifier::{UniversalNotifier, test_helpers::test_notifiers}; + use fish_wchar::WString; #[test] fn test_inotify_notifiers() { diff --git a/src/universal_notifier/kqueue.rs b/src/universal_notifier/kqueue.rs index 2f76b3668..39998a894 100644 --- a/src/universal_notifier/kqueue.rs +++ b/src/universal_notifier/kqueue.rs @@ -181,10 +181,8 @@ fn notification_fd_became_readable(&self, fd: RawFd) -> bool { #[cfg(test)] mod tests { use super::KqueueNotifier; - use crate::{ - universal_notifier::{UniversalNotifier, test_helpers::test_notifiers}, - wchar::WString, - }; + use crate::universal_notifier::{UniversalNotifier, test_helpers::test_notifiers}; + use fish_wchar::WString; #[test] fn test_kqueue_notifiers() { diff --git a/src/wchar.rs b/src/wchar.rs index 56b29d720..bebe9c13d 100644 --- a/src/wchar.rs +++ b/src/wchar.rs @@ -1,58 +1,7 @@ -//! Support for wide strings. -//! -//! There are two wide string types that are commonly used: -//! - wstr: a string slice without a nul terminator. Like `&str` but wide chars. -//! - WString: an owning string without a nul terminator. Like `String` but wide chars. - -use fish_common::{ENCODE_DIRECT_BASE, ENCODE_DIRECT_END}; -pub use widestring::{Utf32Str as wstr, Utf32String as WString}; - -/// Pull in our extensions. -pub use crate::wchar_ext::IntoCharIter; - pub mod prelude { - pub use crate::{ - wchar::{IntoCharIter, L, WString, wstr}, - wchar_ext::{ToWString, WExt}, - wutil::{ - LocalizableString, eprintf, localizable_consts, localizable_string, sprintf, wgettext, - wgettext_fmt, - }, + pub use crate::wutil::{ + LocalizableString, eprintf, localizable_consts, localizable_string, sprintf, wgettext, + wgettext_fmt, }; -} - -/// Creates a wstr string slice, like the "L" prefix of C++. -/// The result is of type wstr. -/// It is NOT nul-terminated. -#[macro_export] -macro_rules! L { - ($string:expr) => { - widestring::utf32str!($string) - }; -} -pub use L; - -/// Encode a literal byte in a UTF-32 character. This is required for e.g. the echo builtin, whose -/// escape sequences can be used to construct raw byte sequences which are then interpreted as e.g. -/// UTF-8 by the terminal. If we were to interpret each of those bytes as a codepoint and encode it -/// as a UTF-32 character, printing them would result in several characters instead of one UTF-8 -/// character. -/// -/// See . -pub fn encode_byte_to_char(byte: u8) -> char { - char::from_u32(u32::from(ENCODE_DIRECT_BASE) + u32::from(byte)) - .expect("private-use codepoint should be valid char") -} - -/// Decode a literal byte from a UTF-32 character. -pub fn decode_byte_from_char(c: char) -> Option { - if c >= ENCODE_DIRECT_BASE && c < ENCODE_DIRECT_END { - Some( - (u32::from(c) - u32::from(ENCODE_DIRECT_BASE)) - .try_into() - .unwrap(), - ) - } else { - None - } + pub use fish_wchar::prelude::*; } diff --git a/src/wcstringutil.rs b/src/wcstringutil.rs index 3f8bff515..d4077d693 100644 --- a/src/wcstringutil.rs +++ b/src/wcstringutil.rs @@ -2,7 +2,8 @@ use crate::common::{get_ellipsis_char, get_ellipsis_str}; use crate::fallback::{fish_wcwidth, wcscasecmp, wcscasecmp_fuzzy}; -use crate::wchar::{decode_byte_from_char, prelude::*}; +use crate::wchar::prelude::*; +use fish_wchar::decode_byte_from_char; /// Return the number of newlines in a string. pub fn count_newlines(s: &wstr) -> usize { diff --git a/src/wutil/dir_iter.rs b/src/wutil/dir_iter.rs index d020169ed..545ed5aae 100644 --- a/src/wutil/dir_iter.rs +++ b/src/wutil/dir_iter.rs @@ -1,8 +1,8 @@ use super::wopendir; use crate::common::{bytes2wcstring, wcs2zstring}; -use crate::wchar::{WString, wstr}; use crate::wutil::DevInode; use cfg_if::cfg_if; +use fish_wchar::{WString, wstr}; use libc::{ DT_BLK, DT_CHR, DT_DIR, DT_FIFO, DT_LNK, DT_REG, DT_SOCK, EACCES, EIO, ELOOP, ENAMETOOLONG, ENODEV, ENOENT, ENOTDIR, S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, @@ -329,6 +329,7 @@ fn next(&mut self) -> Option { mod tests { use super::{DirEntryType, DirIter}; use crate::wchar::prelude::*; + use fish_wchar::L; use nix::sys::stat::Mode; use std::fs::File; use std::path::PathBuf; @@ -336,14 +337,12 @@ mod tests { #[test] fn test_dir_iter_bad_path() { // Regression test: DirIter does not crash given a bad path. - use crate::wchar::L; let dir = DirIter::new(L!("/a/bogus/path/which/does/notexist")); assert!(dir.is_err()); } #[test] fn test_no_dots() { - use crate::wchar::L; // DirIter does not return . or .. by default. let dir = DirIter::new(L!(".")).expect("Should be able to open CWD"); for entry in dir { @@ -355,7 +354,6 @@ fn test_no_dots() { #[test] fn test_dots() { - use crate::wchar::L; // DirIter returns . or .. if you ask nicely. let dir = DirIter::new_with_dots(L!(".")).expect("Should be able to open CWD"); let mut seen_dot = false; @@ -375,7 +373,6 @@ fn test_dots() { #[test] #[allow(clippy::if_same_then_else)] fn test_dir_iter() { - use crate::wchar::L; use libc::{EACCES, ENOENT}; let baditer = DirIter::new(L!("/definitely/not/a/valid/directory/for/sure")); diff --git a/src/wutil/mod.rs b/src/wutil/mod.rs index 5eceee0ff..58e40e18e 100644 --- a/src/wutil/mod.rs +++ b/src/wutil/mod.rs @@ -11,11 +11,10 @@ use crate::common::{ bytes2wcstring, fish_reserved_codepoint, wcs2bytes, wcs2osstring, wcs2zstring, }; -use crate::wchar::{L, WString, wstr}; -use crate::wchar_ext::WExt; use crate::wcstringutil::{join_strings, wcs2bytes_callback}; use crate::{fallback, flog}; use errno::errno; +use fish_wchar::{L, WExt, WString, wstr}; pub use gettext::{ LocalizableString, localizable_consts, localizable_string, wgettext, wgettext_fmt, }; @@ -484,7 +483,7 @@ mod tests { mod test_path_normalize_for_cd { use super::super::path_normalize_for_cd; - use crate::wchar::L; + use fish_wchar::L; #[test] fn relative_path() { @@ -694,7 +693,7 @@ fn test_wwrite_to_fd() { #[test] fn test_wstr_offset_in() { - use crate::wchar::L; + use fish_wchar::L; let base = L!("hello world"); assert_eq!(wstr_offset_in(&base[6..], base), 6); assert_eq!(wstr_offset_in(&base[0..], base), 0); diff --git a/src/wutil/wcstod.rs b/src/wutil/wcstod.rs index 7c52a8a2f..e8be49254 100644 --- a/src/wutil/wcstod.rs +++ b/src/wutil/wcstod.rs @@ -1,6 +1,6 @@ use super::errors::Error; use super::hex_float; -use crate::wchar::IntoCharIter; +use fish_wchar::IntoCharIter; // Parse a decimal float from a sequence of characters. // Return the parsed float, and (on success) the number of characters consumed.