mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-31 03:51:14 -03:00
Add printf!/eprintf! convenience wrappers around fprintf!
We often want to format and print a string to a fd, usually stdout/stderr. In general we can't use "format!", "print!", "eprint!" etc. because they don't know about our use of WString where we encode of invalid Unicode characters in the private use area. Instead we use "wwrite_to_fd()". Since we unfortunately don't have a "wformat!()" yet, we use "sprintf!()" to create a formatted wstring to pass to "wwrite_to_fd()". Add "printf!" and "eprintf!" to stand in for "print!" and "eprint!". For printing to files other than stdout and stderr, keep "fwprintf!" but drop the "w" since our "sprintf!" always produces wide strings. Replace "fputws" with "fprintf" though we could also use "wwrite_to_fd" if performance matters. Unlike std::io::stdout(), we don't use locking yet. Remaining work: - There are more places where we use \be?print(ln)?! Usually we print strings that are guaranteed to be valid UTF-8, but not always. We should probably make all of them respect our WString semantics but preferrably keep using the native Rust format strings (#9948). - I think flog.rs currently uses String so it won't handle invalid Unicode characters. We should probably fix this as well.
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
use crate::tokenizer::tok_command;
|
||||
use crate::wutil::perror;
|
||||
use crate::{env::EnvMode, proc::TtyTransfer};
|
||||
use libc::{STDERR_FILENO, STDIN_FILENO, TCSADRAIN};
|
||||
use libc::{STDIN_FILENO, TCSADRAIN};
|
||||
|
||||
use super::prelude::*;
|
||||
|
||||
@@ -126,11 +126,7 @@ pub fn fg(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> Optio
|
||||
} else {
|
||||
// If we aren't redirecting, send output to real stderr, since stuff in sb_err won't get
|
||||
// printed until the command finishes.
|
||||
fwprintf!(
|
||||
STDERR_FILENO,
|
||||
"%s",
|
||||
wgettext_fmt!(FG_MSG, job.job_id(), job.command())
|
||||
);
|
||||
eprintf!("%s", wgettext_fmt!(FG_MSG, job.job_id(), job.command()));
|
||||
}
|
||||
|
||||
let ft = tok_command(job.command());
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
use crate::wcstringutil::wcs2string_callback;
|
||||
use crate::wildcard::{ANY_CHAR, ANY_STRING, ANY_STRING_RECURSIVE};
|
||||
use crate::wutil::encoding::{mbrtowc, wcrtomb, zero_mbstate, AT_LEAST_MB_LEN_MAX};
|
||||
use crate::wutil::{fish_iswalnum, wwrite_to_fd};
|
||||
use crate::wutil::fish_iswalnum;
|
||||
use bitflags::bitflags;
|
||||
use core::slice;
|
||||
use cxx::{CxxWString, UniquePtr};
|
||||
@@ -2143,16 +2143,31 @@ fn to_cstring(self) -> CString {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
#[deprecated = "use printf!, eprintf! or fprintf"]
|
||||
macro_rules! fwprintf {
|
||||
($args:tt) => {
|
||||
panic!()
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
#[deprecated = "use printf!"]
|
||||
pub fn fputws(_s: &wstr, _fd: RawFd) {
|
||||
panic!()
|
||||
}
|
||||
|
||||
// test-only
|
||||
#[allow(unused_macros)]
|
||||
#[deprecated = "use printf!"]
|
||||
macro_rules! err {
|
||||
($format:expr $(, $args:expr)* $(,)? ) => {
|
||||
println!($format $(, $args )*);
|
||||
printf!($format $(, $args )*);
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! fwprintf {
|
||||
($fd:expr, $format:expr $(, $arg:expr)*) => {
|
||||
macro_rules! fprintf {
|
||||
($fd:expr, $format:expr $(, $arg:expr)* $(,)?) => {
|
||||
{
|
||||
let wide = crate::wutil::sprintf!($format, $( $arg ),*);
|
||||
crate::wutil::wwrite_to_fd(&wide, $fd);
|
||||
@@ -2160,8 +2175,16 @@ macro_rules! fwprintf {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fputws(s: &wstr, fd: RawFd) {
|
||||
wwrite_to_fd(s, fd);
|
||||
macro_rules! printf {
|
||||
($format:expr $(, $arg:expr)* $(,)?) => {
|
||||
fprintf!(libc::STDOUT_FILENO, $format $(, $arg)*)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! eprintf {
|
||||
($format:expr $(, $arg:expr)* $(,)?) => {
|
||||
fprintf!(libc::STDERR_FILENO, $format $(, $arg)*)
|
||||
}
|
||||
}
|
||||
|
||||
#[cxx::bridge]
|
||||
|
||||
@@ -55,7 +55,6 @@
|
||||
wchar::prelude::*,
|
||||
wutil::waccess,
|
||||
};
|
||||
use libc::STDERR_FILENO;
|
||||
use std::env;
|
||||
use std::ffi::{CString, OsStr, OsString};
|
||||
use std::fs::File;
|
||||
@@ -331,7 +330,7 @@ fn run_command_list(parser: &Parser, cmds: &[OsString]) -> i32 {
|
||||
retval = STATUS_CMD_OK;
|
||||
} else {
|
||||
let backtrace = parser.get_backtrace(&cmd_wcs, &errors);
|
||||
fwprintf!(STDERR_FILENO, "%s", backtrace);
|
||||
eprintf!("%s", backtrace);
|
||||
// XXX: Why is this the return for "unknown command"?
|
||||
retval = STATUS_CMD_UNKNOWN;
|
||||
}
|
||||
@@ -436,8 +435,8 @@ fn fish_parse_opt(args: &mut [WString], opts: &mut FishCmdOpts) -> usize {
|
||||
}
|
||||
'P' => opts.enable_private_mode = true,
|
||||
'v' => {
|
||||
print!(
|
||||
"{}",
|
||||
printf!(
|
||||
"%s",
|
||||
wgettext_fmt!("%s, version %s\n", PACKAGE_NAME, crate::BUILD_VERSION)
|
||||
);
|
||||
std::process::exit(0);
|
||||
|
||||
@@ -19,10 +19,7 @@
|
||||
use crate::wutil::{perror, perror_io, wdirname, wstat, wwrite_to_fd};
|
||||
use cxx::CxxWString;
|
||||
use errno::Errno;
|
||||
use libc::{
|
||||
EAGAIN, EEXIST, EINTR, ENOENT, ENOTDIR, EPIPE, EWOULDBLOCK, O_EXCL, STDERR_FILENO,
|
||||
STDOUT_FILENO,
|
||||
};
|
||||
use libc::{EAGAIN, EEXIST, EINTR, ENOENT, ENOTDIR, EPIPE, EWOULDBLOCK, O_EXCL, STDOUT_FILENO};
|
||||
use std::cell::{RefCell, UnsafeCell};
|
||||
use std::os::fd::RawFd;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
@@ -237,7 +234,7 @@ fn source_fd(&self) -> RawFd {
|
||||
-1
|
||||
}
|
||||
fn print(&self) {
|
||||
fwprintf!(STDERR_FILENO, "close %d\n", self.fd)
|
||||
eprintf!("close %d\n", self.fd)
|
||||
}
|
||||
fn as_ptr(&self) -> *const () {
|
||||
(self as *const Self).cast()
|
||||
@@ -266,7 +263,7 @@ fn source_fd(&self) -> RawFd {
|
||||
self.source_fd
|
||||
}
|
||||
fn print(&self) {
|
||||
fwprintf!(STDERR_FILENO, "FD map %d -> %d\n", self.source_fd, self.fd)
|
||||
eprintf!("FD map %d -> %d\n", self.source_fd, self.fd)
|
||||
}
|
||||
fn as_ptr(&self) -> *const () {
|
||||
(self as *const Self).cast()
|
||||
@@ -298,7 +295,7 @@ fn source_fd(&self) -> RawFd {
|
||||
self.file_fd.fd()
|
||||
}
|
||||
fn print(&self) {
|
||||
fwprintf!(STDERR_FILENO, "file %d -> %d\n", self.file_fd.fd(), self.fd)
|
||||
eprintf!("file %d -> %d\n", self.file_fd.fd(), self.fd)
|
||||
}
|
||||
fn as_ptr(&self) -> *const () {
|
||||
(self as *const Self).cast()
|
||||
@@ -334,8 +331,7 @@ fn source_fd(&self) -> RawFd {
|
||||
self.pipe_fd.fd()
|
||||
}
|
||||
fn print(&self) {
|
||||
fwprintf!(
|
||||
STDERR_FILENO,
|
||||
eprintf!(
|
||||
"pipe {%d} (input: %s) -> %d\n",
|
||||
self.source_fd(),
|
||||
if self.is_input { "yes" } else { "no" },
|
||||
@@ -425,12 +421,7 @@ fn source_fd(&self) -> RawFd {
|
||||
self.write_fd.fd()
|
||||
}
|
||||
fn print(&self) {
|
||||
fwprintf!(
|
||||
STDERR_FILENO,
|
||||
"bufferfill %d -> %d\n",
|
||||
self.write_fd.fd(),
|
||||
self.fd()
|
||||
)
|
||||
eprintf!("bufferfill %d -> %d\n", self.write_fd.fd(), self.fd())
|
||||
}
|
||||
fn as_ptr(&self) -> *const () {
|
||||
(self as *const Self).cast()
|
||||
@@ -736,22 +727,20 @@ pub fn append_from_specs(&mut self, specs: &RedirectionSpecList, pwd: &wstr) ->
|
||||
/// Output debugging information to stderr.
|
||||
pub fn print(&self) {
|
||||
if self.0.is_empty() {
|
||||
fwprintf!(
|
||||
STDERR_FILENO,
|
||||
eprintf!(
|
||||
"Empty chain %s\n",
|
||||
format!("{:p}", std::ptr::addr_of!(self))
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
fwprintf!(
|
||||
STDERR_FILENO,
|
||||
eprintf!(
|
||||
"Chain %s (%ld items):\n",
|
||||
format!("{:p}", std::ptr::addr_of!(self)),
|
||||
self.0.len()
|
||||
);
|
||||
for (i, io) in self.0.iter().enumerate() {
|
||||
fwprintf!(STDERR_FILENO, "\t%lu: fd:%d, ", i, io.fd());
|
||||
eprintf!("\t%lu: fd:%d, ", i, io.fd());
|
||||
io.print();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,7 +297,7 @@ fn report_errors(
|
||||
|
||||
// Print it.
|
||||
if !should_suppress_stderr_for_tests() {
|
||||
fwprintf!(STDERR_FILENO, "%ls", backtrace_and_desc);
|
||||
eprintf!("%s", backtrace_and_desc);
|
||||
}
|
||||
|
||||
// Mark status.
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
use crate::wutil::{perror, wgettext, wgettext_fmt};
|
||||
use cxx::{CxxWString, UniquePtr};
|
||||
use libc::c_int;
|
||||
use libc::{O_RDONLY, STDERR_FILENO};
|
||||
use libc::O_RDONLY;
|
||||
use once_cell::sync::Lazy;
|
||||
pub use parser_ffi::{library_data_pod_t, BlockType, LoopStatus};
|
||||
use printf_compat::sprintf;
|
||||
@@ -467,7 +467,7 @@ pub fn eval_with(
|
||||
let backtrace_and_desc = self.get_backtrace(cmd, &error_list);
|
||||
|
||||
// Print it.
|
||||
fwprintf!(STDERR_FILENO, "%ls\n", backtrace_and_desc);
|
||||
eprintf!("%s\n", backtrace_and_desc);
|
||||
|
||||
// Set a valid status.
|
||||
self.set_last_statuses(Statuses::just(STATUS_ILLEGAL_CMD.unwrap()));
|
||||
@@ -962,7 +962,7 @@ pub fn emit_profiling(&self, path: &[u8]) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
fwprintf!(f.as_raw_fd(), "Time\tSum\tCommand\n");
|
||||
fprintf!(f.as_raw_fd(), "Time\tSum\tCommand\n");
|
||||
print_profile(&self.profile_items.borrow(), f.as_raw_fd());
|
||||
}
|
||||
|
||||
@@ -1128,12 +1128,12 @@ fn print_profile(items: &[ProfileItem], out: RawFd) {
|
||||
}
|
||||
}
|
||||
|
||||
fwprintf!(out, "%lld\t%lld\t", self_time, total_time);
|
||||
fprintf!(out, "%lld\t%lld\t", self_time, total_time);
|
||||
for _i in 0..item.level {
|
||||
fwprintf!(out, "-");
|
||||
fprintf!(out, "-");
|
||||
}
|
||||
|
||||
fwprintf!(out, "> %ls\n", item.cmd);
|
||||
fprintf!(out, "> %ls\n", item.cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
use crate::ast;
|
||||
use crate::common::{
|
||||
charptr2wcstring, escape, fputws, redirect_tty_output, scoped_push_replacer, timef, Timepoint,
|
||||
charptr2wcstring, escape, redirect_tty_output, scoped_push_replacer, timef, Timepoint,
|
||||
};
|
||||
use crate::curses::term;
|
||||
use crate::env::Statuses;
|
||||
@@ -25,9 +25,9 @@
|
||||
use crate::wutil::{perror, wbasename, wgettext, wperror};
|
||||
use libc::{
|
||||
EBADF, EINVAL, ENOTTY, EPERM, EXIT_SUCCESS, SIGABRT, SIGBUS, SIGCONT, SIGFPE, SIGHUP, SIGILL,
|
||||
SIGINT, SIGPIPE, SIGQUIT, SIGSEGV, SIGSYS, SIGTTOU, SIG_DFL, SIG_IGN, STDIN_FILENO,
|
||||
STDOUT_FILENO, WCONTINUED, WEXITSTATUS, WIFCONTINUED, WIFEXITED, WIFSIGNALED, WIFSTOPPED,
|
||||
WNOHANG, WTERMSIG, WUNTRACED, _SC_CLK_TCK,
|
||||
SIGINT, SIGPIPE, SIGQUIT, SIGSEGV, SIGSYS, SIGTTOU, SIG_DFL, SIG_IGN, STDIN_FILENO, WCONTINUED,
|
||||
WEXITSTATUS, WIFCONTINUED, WIFEXITED, WIFSIGNALED, WIFSTOPPED, WNOHANG, WTERMSIG, WUNTRACED,
|
||||
_SC_CLK_TCK,
|
||||
};
|
||||
use once_cell::sync::Lazy;
|
||||
use printf_compat::sprintf;
|
||||
@@ -1192,24 +1192,19 @@ pub fn jobs_requiring_warning_on_exit(parser: &Parser) -> JobList {
|
||||
/// jobs_requiring_warning_on_exit().
|
||||
#[widestrs]
|
||||
pub fn print_exit_warning_for_jobs(jobs: &JobList) {
|
||||
fputws(wgettext!("There are still jobs active:\n"), STDOUT_FILENO);
|
||||
fputws(wgettext!("\n PID Command\n"), STDOUT_FILENO);
|
||||
printf!("%s", wgettext!("There are still jobs active:\n"));
|
||||
printf!("%s", wgettext!("\n PID Command\n"));
|
||||
for j in jobs {
|
||||
fwprintf!(
|
||||
STDOUT_FILENO,
|
||||
"%6d %ls\n",
|
||||
j.processes()[0].pid(),
|
||||
j.command()
|
||||
);
|
||||
printf!("%6d %ls\n", j.processes()[0].pid(), j.command());
|
||||
}
|
||||
fputws("\n"L, STDOUT_FILENO);
|
||||
fputws(
|
||||
printf!("\n");
|
||||
printf!(
|
||||
"%s",
|
||||
wgettext!("A second attempt to exit will terminate them.\n"),
|
||||
STDOUT_FILENO,
|
||||
);
|
||||
fputws(
|
||||
printf!(
|
||||
"%s",
|
||||
wgettext!("Use 'disown PID' to remove jobs from the list without terminating them.\n"),
|
||||
STDOUT_FILENO,
|
||||
);
|
||||
reader_schedule_prompt_repaint();
|
||||
}
|
||||
|
||||
@@ -304,20 +304,20 @@ fn test_history_races_pound_on_history(item_count: usize, idx: usize) {
|
||||
// Remove everything from this item on
|
||||
let removed = list.splice(position.., []);
|
||||
for line in removed.into_iter().rev() {
|
||||
err!("Item dropped from history: {line}");
|
||||
println!("Item dropped from history: {line}");
|
||||
}
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if !found {
|
||||
err!(
|
||||
println!(
|
||||
"Line '{}' found in history, but not found in some array",
|
||||
item.str()
|
||||
);
|
||||
for list in &expected_lines {
|
||||
if !list.is_empty() {
|
||||
fwprintf!(STDERR_FILENO, "\tRemaining: %ls\n", list.last().unwrap())
|
||||
printf!("\tRemaining: %ls\n", list.last().unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user