What is the best way to write cli apps in rust? [SOLVED]

Hi rustceans!
As you might know writing console based apps in rust can be verbose. compared to rust competitors like c++ or even c.
Consider this code in c++:

#include <iostream>
using namespace std;

int main() {
	cout << "Inser your first number :";
	int a,b;
	cin >> a;
	cout << "Insert the second one:";
	cin >> b;
}

now if we wanted to write that in rust :

use std::io;
use std::io::Write;

fn main() {
    print!("Insert your first number: ");
    io::stdout().flush();

    let mut a = String::new();
    io::stdin().read_line(&mut a);
    let mut a: i32 = a.trim().parse().unwrap();

    print!("Insert your second number: ");
    io::stdout().flush();

    let mut b = String::new();
    io::stdin().read_line(&mut b);
    let mut b: i32 = b.trim().parse().unwrap();
}

personally I don't hate doing things by myself. I know rust does the same things that c++ does in final binary. but again: this can become very verbose.
Is there any crate or better way to write terminal apps that supports followings:

  • Colourful outputs

  • keyboard events

  • and is not verbose

second question : what library does rust compiler use to show us warnings and errors?

2 Likes

Clap is my favourite library for CLI apps but not for the kind of apps you describe in your post though. For styling output, I like term-painter since it is easy to use and cross-platform.

2 Likes

Apart from toy programs you write for yourself, I've found that most command line programs will take their input uniquely from their the command line arguments or be meant to work with pipes. That is, not many command line programs are designed to be interactive like you are showing above.

That said, it's not overly difficult to create a couple wrapper functions so you don't need to explicitly flush stdout or lock stdin.

use std::io;

fn input(prompt: &str) -> String {
  print!("{}", prompt);
  io::stdout().flush();

  let mut reply = String::new;
  io::stdin().read_line(&mut reply);
  a.trim()
}

Otherwise you may want to look into something like rustyline (a Rust readline implementation) for handling input similar to how a typical terminal does. There's also term for doing pretty output.

2 Likes

Thanks for the solution.

But I knew I could write afew functions to make this easier but I wanted to know what is the realworld and professional way to do it, which Im begining to realize that such way doesn't exist.

Anyway, There are plenty of command line iteractive programs out there. thats why we have a library in C-language called ncurses.
I just asked for the rust way :slight_smile:

I think the Rust way just feels cumbersome because Rust makes you deal with the possibility of errors, whereas in a Python or C++ program it'd throw an exception at runtime.

2 Likes

I would argue that creating a few functions to make things easier is the real-world and professional way to do it.

4 Likes

Wecome to Rust!

Here are some real world command line programms to learn from:

https://github.com/BurntSushi/ripgrep

https://github.com/mmstick/parallel

https://github.com/lotabout/skim

And some libraries that help with writing TUIs (text user interface like ncurses):

https://crates.io/search?q=ncurses

To answer your second question:
If I'm not mistaken Rust uses a copy of the term crate:

https://github.com/rust-lang/rust/blob/master/src/libterm/lib.rs

As mentioned above.

2 Likes