自定义命令在终端中没有输出任何内容。

huangapple go评论73阅读模式
英文:

Custom command not echoing anything in the terminal

问题

以下是代码的翻译部分,不包括问题的回答:

以下代码允许您在终端中定义自定义命令。每个自定义命令都有一个`key`(触发命令)、一个`description`和一个`shell_command`(实际命令)。

use std::io::{stdin, stdout, Write};
use std::process::Command;
use termion::event::Key;
use termion::input::TermRead;
use termion::raw::IntoRawMode;

struct CustomCommand {
    key: char,
    description: &'static str,
    shell_command: &'static str,
}

impl CustomCommand {
    fn execute_shell_command(&self) {
        let output = Command::new("sh")
            .arg("-c")
            .arg(self.shell_command)
            .output();

        match output {
            Ok(output) => {
                if output.status.success() {
                    println!("命令执行成功\r\n");
                } else {
                    println!("命令执行失败\r\n");
                }
            }
            Err(e) => {
                println!("执行命令时出错: {:?}\r\n", e);
            }
        }
    }
}

fn main() {
    // 打开终端的原始模式
    let mut stdout = stdout().into_raw_mode().unwrap();

    // 定义可用的命令

    let commands = vec![CustomCommand {
        key: 'c',
        description: "这是一个自定义命令",
        shell_command: "echo '自定义命令已执行'",
    }];

    // 在终端上打印消息
    write!(stdout, "请选择一个命令:\r\n").unwrap();

    // 列出用户定义的命令
    for command in &commands {
        write!(stdout, "{}  {}\r\n", command.key, command.description).unwrap();
    }

    stdout.flush().unwrap();

    // 从标准输入读取输入
    let input = stdin().keys();

    // 循环遍历每个按键
    for key in input {
        // 将按键与可用命令进行匹配
        match key.unwrap() {
            // 如果按键与命令匹配,则执行它并退出循环
            Key::Char(k) if commands.iter().any(|c| c.key == k) => {
                let command = commands.iter().find(|c| c.key == k).unwrap();
                command.execute_shell_command();
                break;
            }
            // 输出其他字符
            Key::Char(c) => {
                write!(stdout, "您按下了: {}\r\n", c).unwrap();
                stdout.flush().unwrap();
            }
            // 如果按键是其他任何内容,请忽略
            _ => {}
        }
    }
}

请注意,代码中的问题部分没有翻译。如果您有关于代码的问题,可以随时提出,我将尽力提供帮助。

英文:

The following code lets you define custom commands in the terminal. Each custom command has a key (which triggers the command), a description, and a shell_command (the actual command).

use std::io::{stdin, stdout, Write};
use std::process::Command;
use termion::event::Key;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
struct CustomCommand {
key: char,
description: &'static str,
shell_command: &'static str,
}
impl CustomCommand {
fn execute_shell_command(&self) {
let output = Command::new("sh")
.arg("-c")
.arg(self.shell_command)
.output();
match output {
Ok(output) => {
if output.status.success() {
println!("Command executed successfully\r\n");
} else {
println!("Command execution failed\r\n");
}
}
Err(e) => {
println!("Error executing command: {:?}\r\n", e);
}
}
}
}
fn main() {
// Turn on raw mode for the terminal
let mut stdout = stdout().into_raw_mode().unwrap();
// Define the available commands
let commands = vec![CustomCommand {
key: 'c',
description: "This is a custom command",
shell_command: "echo 'Custom command executed'",
}];
// Print the messages to the terminal
write!(stdout, "Please select a command:\r\n").unwrap();
// List the custom commands for the user
for command in &commands {
write!(stdout, "{}  {}\r\n", command.key, command.description).unwrap();
}
stdout.flush().unwrap();
// Read input from stdin
let input = stdin().keys();
// Loop over each key that is pressed
for key in input {
// Match the key against the available commands
match key.unwrap() {
// If the key matches a command, execute it and break the loop
Key::Char(k) if commands.iter().any(|c| c.key == k) => {
let command = commands.iter().find(|c| c.key == k).unwrap();
command.execute_shell_command();
break;
}
// Output other characters
Key::Char(c) => {
write!(stdout, "You pressed: {}\r\n", c).unwrap();
stdout.flush().unwrap();
}
// If the key is anything else, ignore it
_ => {}
}
}
}

The command is being executed successfully, but is not echoing anything in the terminal:

Please select a command:
c  This is a custom command
Command executed successfully
alex@alex-M52AD-M12AD-A-F-K31AD:~/rust/cc$ 

Why is this, and how to fix it?

Rust Playground

答案1

得分: 2

On success, output contains a Vec<u8> in its stdout member.
You can eventually convert it to a string and display it as some text.

if output.status.success() {
    println!("Command executed successfully\r\n");
    println!("bytes: {:?}", output.stdout);
    let text = String::from_utf8_lossy(&output.stdout);
    println!("text: {:?}", text);
}

If you are not interested in capturing the outputs of the command, you can simply use spawn(); then the outputs of the command will naturally appear in the terminal.

Thanks to @JonasFassbender remark, .status() is even easier (it waits for the process to terminate, we don't have to).
Here is your code slightly modified.

fn execute_shell_command(&self) {
    let status = Command::new("sh")
        .arg("-c")
        .arg(self.shell_command)
        .status();
    match status {
        Ok(status) => {
            if status.success() {
                println!("Command executed successfully\r\n");
            } else {
                println!("Command execution failed\r\n");
            }
        }
        Err(e) => {
            println!("Error executing command: {:?}\r\n", e);
        }
    }
}
英文:

On success, output contains a Vec&lt;u8&gt; in its stdout member.
You can eventually convert it to a string and display it as some text.

if output.status.success() {
    println!(&quot;Command executed successfully\r\n&quot;);
    println!(&quot;bytes: {:?}&quot;, output.stdout);
    let text = String::from_utf8_lossy(&amp;output.stdout);
    println!(&quot;text: {:?}&quot;, text);
}

If you are not interested in capturing the outputs of the command, you can simply use spawn(); then the outputs of the command will naturally appear in the terminal.

Thanks to @JonasFassbender remark, .status() is even easier (it waits for the process to terminate, we don't have to).
Here is your code slightly modified.

    fn execute_shell_command(&amp;self) {
        let status = Command::new(&quot;sh&quot;)
            .arg(&quot;-c&quot;)
            .arg(self.shell_command)
            .status();
        match status {
            Ok(status) =&gt; {
                if status.success() {
                    println!(&quot;Command executed successfully\r\n&quot;);
                } else {
                    println!(&quot;Command execution failed\r\n&quot;);
                }
            }
            Err(e) =&gt; {
                println!(&quot;Error executing command: {:?}\r\n&quot;, e);
            }
        }
    }

huangapple
  • 本文由 发表于 2023年3月7日 22:55:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/75663583.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定