1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

printf: support %q

This commit is contained in:
Zhuoxun Yang 2023-11-09 10:17:44 +08:00
parent 7279bc1741
commit e3ec12233b

View file

@ -10,6 +10,7 @@
//! Subs which have numeric field chars make use of the num_format //! Subs which have numeric field chars make use of the num_format
//! submodule //! submodule
use crate::error::{UError, UResult}; use crate::error::{UError, UResult};
use crate::quoting_style::{escape_name, QuotingStyle};
use itertools::{put_back_n, PutBackN}; use itertools::{put_back_n, PutBackN};
use std::error::Error; use std::error::Error;
use std::fmt::Display; use std::fmt::Display;
@ -91,7 +92,7 @@ impl Sub {
// for more dry printing, field characters are grouped // for more dry printing, field characters are grouped
// in initialization of token. // in initialization of token.
let field_type = match field_char { let field_type = match field_char {
's' | 'b' => FieldType::Strf, 's' | 'b' | 'q' => FieldType::Strf,
'd' | 'i' | 'u' | 'o' | 'x' | 'X' => FieldType::Intf, 'd' | 'i' | 'u' | 'o' | 'x' | 'X' => FieldType::Intf,
'f' | 'F' => FieldType::Floatf, 'f' | 'F' => FieldType::Floatf,
'a' | 'A' => FieldType::CninetyNineHexFloatf, 'a' | 'A' => FieldType::CninetyNineHexFloatf,
@ -189,7 +190,7 @@ impl SubParser {
let mut legal_fields = [ let mut legal_fields = [
// 'a', 'A', //c99 hex float implementation not yet complete // 'a', 'A', //c99 hex float implementation not yet complete
'b', 'c', 'd', 'e', 'E', 'f', 'F', 'g', 'G', 'i', 'o', 's', 'u', 'x', 'X', 'b', 'c', 'd', 'e', 'E', 'f', 'F', 'g', 'G', 'i', 'o', 'q', 's', 'u', 'x', 'X',
]; ];
let mut specifiers = ['h', 'j', 'l', 'L', 't', 'z']; let mut specifiers = ['h', 'j', 'l', 'L', 't', 'z'];
legal_fields.sort_unstable(); legal_fields.sort_unstable();
@ -260,7 +261,6 @@ impl SubParser {
} }
x if legal_fields.binary_search(&x).is_ok() => { x if legal_fields.binary_search(&x).is_ok() => {
self.field_char = Some(ch); self.field_char = Some(ch);
self.text_so_far.push(ch);
break; break;
} }
x if specifiers.binary_search(&x).is_ok() => { x if specifiers.binary_search(&x).is_ok() => {
@ -331,7 +331,7 @@ impl SubParser {
if (field_char == 's' && self.min_width_tmp == Some(String::from("0"))) if (field_char == 's' && self.min_width_tmp == Some(String::from("0")))
|| (field_char == 'c' || (field_char == 'c'
&& (self.min_width_tmp == Some(String::from("0")) || self.past_decimal)) && (self.min_width_tmp == Some(String::from("0")) || self.past_decimal))
|| (field_char == 'b' || ((field_char == 'b' || field_char == 'q')
&& (self.min_width_tmp.is_some() && (self.min_width_tmp.is_some()
|| self.past_decimal || self.past_decimal
|| self.second_field_tmp.is_some())) || self.second_field_tmp.is_some()))
@ -391,6 +391,7 @@ impl Sub {
// if %s just return arg // if %s just return arg
// if %b use UnescapedText module's unescape-fn // if %b use UnescapedText module's unescape-fn
// if %c return first char of arg // if %c return first char of arg
// if %q return arg which non-printable characters are escaped
FieldType::Strf | FieldType::Charf => { FieldType::Strf | FieldType::Charf => {
match pf_arg { match pf_arg {
Some(arg_string) => { Some(arg_string) => {
@ -404,11 +405,18 @@ impl Sub {
UnescapedText::from_it_core(writer, &mut a_it, true); UnescapedText::from_it_core(writer, &mut a_it, true);
None None
} }
// for 'c': get iter of string vals, 'q' => Some(escape_name(
arg_string.as_ref(),
&QuotingStyle::Shell {
escape: true,
always_quote: false,
show_control: false,
},
)),
// get opt<char> of first val // get opt<char> of first val
// and map it to opt<String> // and map it to opt<String>
/* 'c' | */ 'c' => arg_string.chars().next().map(|x| x.to_string()),
_ => arg_string.chars().next().map(|x| x.to_string()), _ => unreachable!(),
} }
} }
None => None, None => None,