command_error/
utf8_program_and_args.rs1use std::borrow::Cow;
2use std::fmt::Display;
3use std::process::Command;
4
5use crate::CommandDisplay;
6
7#[derive(Debug, Clone)]
36pub struct Utf8ProgramAndArgs {
37 current_dir: Option<String>,
38 envs: Vec<(String, Option<String>)>,
39 program: String,
40 args: Vec<String>,
41}
42
43impl Display for Utf8ProgramAndArgs {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 if let Some(current_dir) = &self.current_dir {
46 write!(f, "cd {} && ", shell_words::quote(current_dir))?;
47 }
48
49 for (key, value) in self.envs.iter() {
50 write!(
52 f,
53 "{key}={} ",
54 value
55 .as_deref()
56 .map(|value| shell_words::quote(value))
57 .unwrap_or_default()
58 )?;
59 }
60
61 write!(f, "{}", shell_words::quote(&self.program))?;
62 if !self.args.is_empty() {
63 write!(f, " {}", shell_words::join(&self.args))?;
64 }
65 Ok(())
66 }
67}
68
69impl CommandDisplay for Utf8ProgramAndArgs {
70 fn program(&self) -> std::borrow::Cow<'_, str> {
71 Cow::Borrowed(&self.program)
72 }
73
74 fn program_quoted(&self) -> Cow<'_, str> {
75 shell_words::quote(&self.program)
76 }
77
78 fn args(&self) -> Box<(dyn Iterator<Item = Cow<'_, str>> + '_)> {
79 Box::new(self.args.iter().map(|arg| Cow::Borrowed(arg.as_str())))
80 }
81}
82
83impl<'a> From<&'a Command> for Utf8ProgramAndArgs {
84 fn from(command: &'a Command) -> Self {
85 Utf8ProgramAndArgs {
86 current_dir: command
87 .get_current_dir()
88 .map(|path| path.to_string_lossy().into_owned()),
89 envs: command
90 .get_envs()
91 .map(|(key, value)| {
92 (
93 key.to_string_lossy().into_owned(),
94 value.map(|value| value.to_string_lossy().into_owned()),
95 )
96 })
97 .collect(),
98 program: command.get_program().to_string_lossy().into_owned(),
99 args: command
100 .get_args()
101 .map(|arg| arg.to_string_lossy().into_owned())
102 .collect(),
103 }
104 }
105}