Following this article about writing a shell in Rust. Compiler outputs a warning about a variable never being read.
use std::io::stdin;
use std::io::stdout;
use std::io::Write;
use std::process::Command;
use std::path::Path;
fn main(){
let mut input = String::new();
loop {
print!("> ");
stdout().flush().unwrap();
// input = String::from(""); // **<===== HERE**
stdin().read_line(&mut input).unwrap();
let mut parts = input.trim().split_whitespace();
let command = parts.next().unwrap();
let args = parts;
match command {
"cd" => {
let new_dir = args.peekable().peek().map_or("/", |x| *x);
let root = Path::new(new_dir);
if let Err(e) = std::env::set_current_dir(&root) {
eprintln!("{}", e);
}
},
"exit" => return,
command => {
let child = Command::new(command)
.args(args)
.spawn();
// gracefully handle malformed user input
match child {
Ok(mut child) => { child.wait().unwrap(); },
Err(e) => eprintln!("{}", e),
};
}
}
}
}
However, commenting out this line causes program to bug: here is the behavior before and after commenting:
usn@DESKTOP:~/bqy/rust/p2$ cargo run
warning: value assigned to `input` is never read
--> src/main.rs:8:10
|
8 | let mut input = String::new();
| ^^^^^
|
= note: `#[warn(unused_assignments)]` on by default
= help: maybe it is overwritten before being read?
Finished dev [unoptimized + debuginfo] target(s) in 0.02s
Running `target/debug/p2`
> ls
Cargo.lock Cargo.toml src target
> ls
Cargo.lock Cargo.toml src target
> exit
usn@DESKTOP:~/bqy/rust/p2$ vi src/main.rs
usn@DESKTOP:~/bqy/rust/p2$ cargo run
Compiling p2 v0.1.0 (/mnt/d/MMM/projects/bqy/rust/p2)
Finished dev [unoptimized + debuginfo] target(s) in 1.13s
Running `target/debug/p2`
> ls
Cargo.lock Cargo.toml src target
> ls
ls: cannot access 'ls': No such file or directory
> exit
ls: cannot access 'ls': No such file or directory
ls: cannot access 'exit': No such file or directory
> ^C
usn@DESKTOP:~/bqy/rust/p2$ vi src/main.rs
Simple explanation of unwanted behavior is that command line is not resetted. So, why does the compiler complains ?
Thank you for reading.
Without the line to clear the buffer, its content is reused from one iteration to another. This is why your program doesn't work without
input = String::from("");
But this gives you a warning because you gave input
a value when you declared it:
let mut input = String::new();
// ^^^^^^^^^^^^^^^^
and this value is not used, since literally the first use of input
is to override it. So just don't give it a value:
let mut input;
In Rust this is perfectly safe and the compiler won't let you accidentally use input
before you initialize it.
Alternatively, if you goal was to reuse the buffer to save on memory, you should use
input.clear();
because input = String::from("");
creates a completely new string with a new buffer and throws the other one away.