Code Review Basic Shell

Hi! First time posting here. It’s taken me a long time to attempt to do projects in Rust. My first real one is here. It’s very simple. A simple ‘shell’ implementing cd, help, and exit and then passes other arguments to Command. I was hoping I could get some feedback on things I could do to make it more Rust-like?

Also, I attempted to implement piping but couldn’t understand how it would fit with my current program.

Thanks!

I guess you tried the usual suspects already—rustfmt, clippy?

one approach to implement piping would be

  • run the commands in threads
  • commands would read from a passed-in pipe, and write to a passed-in pipe
  • when a | is used pass the same pipe as output of the preceding process, and the input pipe of the next one (the first process will get stdin, the last stdout)

howeverr Rust doesn't expose a pipe type except internally in std::process but this is not useful for this case as the commands don't run as separate processes—there is a os_pipe crate apparently—though I think the more rusty approach is using std::sync::mpsc::{Sender,Receiver} pair as a "pipe"

another approach if you're only emulating multiple processes but don't want threads could do cooperative "multitasking" by having commands take an iter for input and yield an iter for output

1 Like

Clippy already gives some good hints:

warning: redundant field names in struct initialization
  --> src/main.rs:14:17
   |
14 |         Funcs { args: args }
   |                 ^^^^^^^^^^ help: replace it with: `args`
warning: length comparison to zero
  --> src/main.rs:18:12
   |
18 |         if self.args.len() == 0 {
   |            ^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is more concise: `self.args.is_empty()`
warning: this argument is passed by value, but not consumed in the function body
  --> src/main.rs:45:20
   |
45 | fn tokenize(input: String) -> Vec<String> {
   |                    ^^^^^^ help: consider changing the type to: `&str`

I would advise, that you use the lock function on stdin and stdout to increase your performance.

fn exit(&self) -> i32 {
        process::exit(1);
}

You propably want exit(0) because your program terminates correctly.

1 Like