Fix printing when using multiple command instances.

This commit is contained in:
ilmari-h 2022-08-02 20:35:40 +03:00
parent 4b6fca7536
commit bc564b8f2d
3 changed files with 119 additions and 67 deletions

View File

@ -58,6 +58,13 @@ pub fn execute_commands<I: Iterator<Item = io::Result<Command>>>(
cmd_display_result: Option<String>,
) -> ExitCode {
let mut output_buffer = OutputBuffer::new(out_perm);
if let Some(ref d) = cmd_display_result {
// Print command.
let cmd_bytes: Vec<u8> = d.clone().as_bytes().to_vec();
output_buffer.push(cmd_bytes, vec![]);
}
for result in cmds {
let mut cmd = match result {
Ok(cmd) => cmd,
@ -73,11 +80,6 @@ pub fn execute_commands<I: Iterator<Item = io::Result<Command>>>(
cmd.spawn().and_then(|c| c.wait_with_output())
};
if let Some(ref d) = cmd_display_result {
let cmd_bytes: Vec<u8> = d.clone().as_bytes().to_vec();
output_buffer.push(cmd_bytes, vec![]);
}
// Then wait for the command to exit, if it was spawned.
match output {
Ok(output) => {

View File

@ -68,7 +68,10 @@ impl<'a> CommandSetDisplay<'a> {
impl CommandSetDisplay<'_> {
fn get_command_string(&self, path_separator: Option<&str>) -> Option<String> {
let mut res = String::new();
for c in self.command_set.commands.iter() {
for (i, c) in self.command_set.commands.iter().enumerate() {
if i > 0 {
res.push_str(&"; ");
}
let cmd_hl = c.generate_highlighted_string(self.entry, self.config, path_separator);
match cmd_hl {
None => return None,
@ -78,50 +81,6 @@ impl CommandSetDisplay<'_> {
res.push('\n');
Some(res)
}
fn print_entry_string(
entry: &DirEntry,
argt: &ArgumentTemplate,
config: &Config,
path_separator: Option<&str>,
) -> Result<(), std::io::Error> {
let stdout = io::stdout();
let mut stdout = stdout.lock();
if let Some(argt_str) = argt
.generate_with_highlight(entry, path_separator, config)
.to_str()
{
write!(stdout, "{} ", argt_str)?;
}
stdout.flush()
}
fn print_pre_args(args: &[OsString]) -> std::io::Result<()> {
let stdout = io::stdout();
let mut stdout = stdout.lock();
// Print pre-args; arguments before entry templates.
for arg in args {
if let Some(arg_str) = arg.to_str() {
write!(stdout, "{} ", arg_str)?;
}
}
stdout.flush()
}
fn print_post_args(args: &[OsString]) -> std::io::Result<()> {
let stdout = io::stdout();
let mut stdout = stdout.lock();
// Print post-args, arguments after entry templates.
for arg in args {
if let Some(arg_str) = arg.to_str() {
write!(stdout, "{} ", arg_str)?;
}
}
writeln!(stdout)?;
stdout.flush()
}
}
impl CommandSet {
@ -223,14 +182,7 @@ impl CommandSet {
// If provided print config, print command arguments.
if let Some(config) = print_with_config {
if let Err(e) = CommandSetDisplay::print_entry_string(
&entry,
&builder.path_arg,
config,
path_separator,
) {
return handle_cmd_error(Some(&builder.cmd), e);
}
builder.push_display_entry(&entry, config, path_separator)
}
}
}
@ -258,6 +210,7 @@ struct CommandBuilder {
count: usize,
limit: usize,
print: bool,
entries_to_print: OsString,
}
impl CommandBuilder {
@ -286,6 +239,7 @@ impl CommandBuilder {
count: 0,
limit,
print,
entries_to_print: OsString::new(),
})
}
@ -298,6 +252,20 @@ impl CommandBuilder {
Ok(cmd)
}
fn push_display_entry(
&mut self,
entry: &DirEntry,
config: &Config,
path_separator: Option<&str>,
) {
self.entries_to_print
.push(
self.path_arg
.generate_with_highlight(entry, path_separator, config),
);
self.entries_to_print.push(" ");
}
fn push(&mut self, path: &Path, separator: Option<&str>) -> io::Result<()> {
if self.limit > 0 && self.count >= self.limit {
self.finish()?;
@ -311,21 +279,40 @@ impl CommandBuilder {
self.finish()?;
}
// If started a new command, print the arguments before printing entry templates.
if self.count == 0 && self.print {
CommandSetDisplay::print_pre_args(&self.pre_args)?;
}
self.cmd.try_arg(arg)?;
self.count += 1;
Ok(())
}
fn finish(&mut self) -> io::Result<()> {
if self.count > 0 {
if self.print {
CommandSetDisplay::print_post_args(&self.post_args)?;
if self.print {
let mut to_print = OsString::new();
for arg in &self.pre_args {
to_print.push(arg);
to_print.push(" ");
}
to_print.push(&self.entries_to_print);
for (i, arg) in self.post_args.iter().enumerate() {
if i > 0 {
to_print.push(" ");
}
to_print.push(arg);
}
let stdout = io::stdout();
let mut stdout = stdout.lock();
if let Some(to_print_str) = to_print.to_str() {
writeln!(stdout, "{}", to_print_str)?;
}
stdout.flush()?;
self.entries_to_print = OsString::new();
}
if self.count > 0 {
self.cmd.try_args(&self.post_args)?;
self.cmd.status()?;

View File

@ -1,7 +1,7 @@
mod testenv;
use std::fs;
use std::io::Write;
use std::io::{stdout, Write};
use std::path::Path;
use std::time::{Duration, SystemTime};
use test_case::test_case;
@ -1740,6 +1740,69 @@ fn test_print_exec() {
"echo beginarg ./a.foo ./one/b.foo ./one/two/C.Foo2 ./one/two/c.foo ./one/two/three/d.foo ./one/two/three/directory_foo endarg
beginarg ./a.foo ./one/b.foo ./one/two/C.Foo2 ./one/two/c.foo ./one/two/three/d.foo ./one/two/three/directory_foo endarg",
);
te.assert_output(
&[
"--absolute-path",
"foo",
"--print-exec",
"--exec",
"echo",
";",
"--exec",
"echo",
"test",
"{/}",
],
&format!(
"echo {abs_path}/a.foo; echo test a.foo
echo {abs_path}/one/b.foo; echo test b.foo
echo {abs_path}/one/two/C.Foo2; echo test C.Foo2
echo {abs_path}/one/two/c.foo; echo test c.foo
echo {abs_path}/one/two/three/d.foo; echo test d.foo
echo {abs_path}/one/two/three/directory_foo; echo test directory_foo
{abs_path}/a.foo
{abs_path}/one/b.foo
{abs_path}/one/two/C.Foo2
{abs_path}/one/two/c.foo
{abs_path}/one/two/three/d.foo
{abs_path}/one/two/three/directory_foo
test a.foo
test b.foo
test C.Foo2
test c.foo
test d.foo
test directory_foo",
abs_path = &abs_path
),
);
te.assert_output(
&[
"foo",
"--print-exec",
"--exec",
"echo",
"-n",
"{/}: ",
";",
"--exec",
"echo",
"{//}",
],
"echo -n a.foo: ; echo .
echo -n b.foo: ; echo ./one
echo -n C.Foo2: ; echo ./one/two
echo -n c.foo: ; echo ./one/two
echo -n d.foo: ; echo ./one/two/three
echo -n directory_foo: ; echo ./one/two/three
a.foo: .
b.foo: ./one
C.Foo2: ./one/two
c.foo: ./one/two
d.foo: ./one/two/three
directory_foo: ./one/two/three",
);
}
}