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

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

Custom command not echoing anything in the terminal

问题

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

  1. 以下代码允许您在终端中定义自定义命令。每个自定义命令都有一个`key`(触发命令)、一个`description`和一个`shell_command`(实际命令)。
  2. use std::io::{stdin, stdout, Write};
  3. use std::process::Command;
  4. use termion::event::Key;
  5. use termion::input::TermRead;
  6. use termion::raw::IntoRawMode;
  7. struct CustomCommand {
  8. key: char,
  9. description: &'static str,
  10. shell_command: &'static str,
  11. }
  12. impl CustomCommand {
  13. fn execute_shell_command(&self) {
  14. let output = Command::new("sh")
  15. .arg("-c")
  16. .arg(self.shell_command)
  17. .output();
  18. match output {
  19. Ok(output) => {
  20. if output.status.success() {
  21. println!("命令执行成功\r\n");
  22. } else {
  23. println!("命令执行失败\r\n");
  24. }
  25. }
  26. Err(e) => {
  27. println!("执行命令时出错: {:?}\r\n", e);
  28. }
  29. }
  30. }
  31. }
  32. fn main() {
  33. // 打开终端的原始模式
  34. let mut stdout = stdout().into_raw_mode().unwrap();
  35. // 定义可用的命令
  36. let commands = vec![CustomCommand {
  37. key: 'c',
  38. description: "这是一个自定义命令",
  39. shell_command: "echo '自定义命令已执行'",
  40. }];
  41. // 在终端上打印消息
  42. write!(stdout, "请选择一个命令:\r\n").unwrap();
  43. // 列出用户定义的命令
  44. for command in &commands {
  45. write!(stdout, "{} {}\r\n", command.key, command.description).unwrap();
  46. }
  47. stdout.flush().unwrap();
  48. // 从标准输入读取输入
  49. let input = stdin().keys();
  50. // 循环遍历每个按键
  51. for key in input {
  52. // 将按键与可用命令进行匹配
  53. match key.unwrap() {
  54. // 如果按键与命令匹配,则执行它并退出循环
  55. Key::Char(k) if commands.iter().any(|c| c.key == k) => {
  56. let command = commands.iter().find(|c| c.key == k).unwrap();
  57. command.execute_shell_command();
  58. break;
  59. }
  60. // 输出其他字符
  61. Key::Char(c) => {
  62. write!(stdout, "您按下了: {}\r\n", c).unwrap();
  63. stdout.flush().unwrap();
  64. }
  65. // 如果按键是其他任何内容,请忽略
  66. _ => {}
  67. }
  68. }
  69. }

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

英文:

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).

  1. use std::io::{stdin, stdout, Write};
  2. use std::process::Command;
  3. use termion::event::Key;
  4. use termion::input::TermRead;
  5. use termion::raw::IntoRawMode;
  6. struct CustomCommand {
  7. key: char,
  8. description: &'static str,
  9. shell_command: &'static str,
  10. }
  11. impl CustomCommand {
  12. fn execute_shell_command(&self) {
  13. let output = Command::new("sh")
  14. .arg("-c")
  15. .arg(self.shell_command)
  16. .output();
  17. match output {
  18. Ok(output) => {
  19. if output.status.success() {
  20. println!("Command executed successfully\r\n");
  21. } else {
  22. println!("Command execution failed\r\n");
  23. }
  24. }
  25. Err(e) => {
  26. println!("Error executing command: {:?}\r\n", e);
  27. }
  28. }
  29. }
  30. }
  31. fn main() {
  32. // Turn on raw mode for the terminal
  33. let mut stdout = stdout().into_raw_mode().unwrap();
  34. // Define the available commands
  35. let commands = vec![CustomCommand {
  36. key: 'c',
  37. description: "This is a custom command",
  38. shell_command: "echo 'Custom command executed'",
  39. }];
  40. // Print the messages to the terminal
  41. write!(stdout, "Please select a command:\r\n").unwrap();
  42. // List the custom commands for the user
  43. for command in &commands {
  44. write!(stdout, "{} {}\r\n", command.key, command.description).unwrap();
  45. }
  46. stdout.flush().unwrap();
  47. // Read input from stdin
  48. let input = stdin().keys();
  49. // Loop over each key that is pressed
  50. for key in input {
  51. // Match the key against the available commands
  52. match key.unwrap() {
  53. // If the key matches a command, execute it and break the loop
  54. Key::Char(k) if commands.iter().any(|c| c.key == k) => {
  55. let command = commands.iter().find(|c| c.key == k).unwrap();
  56. command.execute_shell_command();
  57. break;
  58. }
  59. // Output other characters
  60. Key::Char(c) => {
  61. write!(stdout, "You pressed: {}\r\n", c).unwrap();
  62. stdout.flush().unwrap();
  63. }
  64. // If the key is anything else, ignore it
  65. _ => {}
  66. }
  67. }
  68. }

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

  1. Please select a command:
  2. c This is a custom command
  3. Command executed successfully
  4. 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.

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

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.

  1. fn execute_shell_command(&self) {
  2. let status = Command::new("sh")
  3. .arg("-c")
  4. .arg(self.shell_command)
  5. .status();
  6. match status {
  7. Ok(status) => {
  8. if status.success() {
  9. println!("Command executed successfully\r\n");
  10. } else {
  11. println!("Command execution failed\r\n");
  12. }
  13. }
  14. Err(e) => {
  15. println!("Error executing command: {:?}\r\n", e);
  16. }
  17. }
  18. }
英文:

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.

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

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.

  1. fn execute_shell_command(&amp;self) {
  2. let status = Command::new(&quot;sh&quot;)
  3. .arg(&quot;-c&quot;)
  4. .arg(self.shell_command)
  5. .status();
  6. match status {
  7. Ok(status) =&gt; {
  8. if status.success() {
  9. println!(&quot;Command executed successfully\r\n&quot;);
  10. } else {
  11. println!(&quot;Command execution failed\r\n&quot;);
  12. }
  13. }
  14. Err(e) =&gt; {
  15. println!(&quot;Error executing command: {:?}\r\n&quot;, e);
  16. }
  17. }
  18. }

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:

确定