Command-Line Interfaces

29 ноември 2018

Hangman

Demo

Пълния код: rust-hangman

Откъде вземаме данни за играта?

Вграждане в binary-то

Лесен начин, и доста удобен за разнообразни други неща. Макроса include_str! чете файл и го набива в кода по време на компилация, все едно си е бил там, ограден с кавички. Така може да вграждате всякакви текстови ресурси в binary-то (а със include_bin!, може да вграждате и примерно картинки, аудио…). Пътищата са релативни на текущия файл.

Пример от друг проект (rust-quickmd):

1 2 3
const MAIN_JS:    &'static str = include_str!("../res/js/main.js");
const MAIN_CSS:   &'static str = include_str!("../res/style/main.css");
const GITHUB_CSS: &'static str = include_str!("../res/style/github.css");

Локално инсталиране на пакет

Debug-ване

ENV vars

1 2 3 4 5 6 7 8
pub fn clear_screen() {
    if env::var("DEBUG").is_ok() {
        return;
    }

    print!("{}[2J", 27 as char);
    print!("{}[1;1H", 27 as char);
}
1 2
$ DEBUG=1 cargo run some-file.txt
$ DEBUG=1 hangman some-file.txt

Debug-ване

ENV Logger

Удобен проект за по-сериозно log-ване: https://docs.rs/env_logger

Пример от друг проект (rust-quickmd):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
fn init_logging() {
    // Release logging:
    // - Warnings and errors
    // - No timestamps
    // - No module info
    //
    #[cfg(not(debug_assertions))]
    env_logger::builder().
        default_format_module_path(false).
        default_format_timestamp(false).
        filter_level(log::LevelFilter::Warn).
        init();

    // Debug logging:
    // - All logs
    // - Full info
    //
    #[cfg(debug_assertions)]
    env_logger::builder().
        filter_level(log::LevelFilter::Debug).
        init();
}

Примерна употреба:

1 2 3
debug!("Building HTML:");
debug!(" > home_path  = {}", home_path);
debug!(" > scroll_top = {}", scroll_top);

При пускане на програмата в release mode, премахваме много допълнителна информация като модули и timestamp, и показваме всичко от "warning" нагоре.

При пускане в debug mode (стандарното при cargo run):

1 2 3 4 5 6
[2019-11-29T08:57:33Z DEBUG quickmd::assets] Building HTML:
[2019-11-29T08:57:33Z DEBUG quickmd::assets]  > home_path  = /home/andrew
[2019-11-29T08:57:33Z DEBUG quickmd::assets]  > scroll_top = 0
[2019-11-29T08:57:33Z DEBUG quickmd::ui] Loading HTML:
[2019-11-29T08:57:33Z DEBUG quickmd::ui]  > output_path = /tmp/.tmpWq7EYh/output.html
[2019-11-29T08:57:33Z DEBUG quickmd::background] Watching ~/.quickmd.css

По-сложна обработка на аргументи чрез structopt

1 2 3 4
[dependencies]
rand = "*"
structopt = "*"
structopt-derive = "*"

По-сложна обработка на аргументи чрез structopt

1 2 3 4
$ hangman --wordlist=words.txt --attempts=10 --debug
$ hangman -w words.txt -a 10 -d
$ hangman --help
$ hangman --version

По-сложна обработка на аргументи чрез structopt

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
extern crate structopt;
#[macro_use]
extern crate structopt_derive;
use structopt::StructOpt;

#[derive(StructOpt, Debug)]
#[structopt(name="hangman", about="A game of Hangman")]
pub struct Options {
    #[structopt(short="w", long="wordlist", help="The path to a word list")]
    wordlist_path: Option<String>,

    #[structopt(short="a", long="attempts", help="The number of attempts to guess the word", default_value="10")]
    attempts: u32,

    #[structopt(short="d", long="debug", help="Show debug info")]
    debug: bool,
}

Ограничения на structopt

Features

Може да си намалите малко броя dependencies, като премахнете default features:

1 2 3 4
[dependencies]
rand = "*"
structopt = { version = "*", default-features = false }
structopt-derive = "*"

Документацията е в clap: https://docs.rs/clap/*/clap/#features-enabled-by-default

Версии

Окей е да използваме * за версия, когато си пишем кода -- конкретните версии се фиксират в Cargo.lock. Ако искаме да го публикуваме като пакет в crates.io, използвайки cargo publish, трябва да фиксираме конкретни версии, примерно:

1 2 3 4 5
[dependencies]
dirs = "2.0.2"
rand = "0.7.2"
structopt = { version = "0.3.5", default-features = false }
structopt-derive = "0.3.5"

Може да намерите плъгини за редакторите си, които да ви помогнат с избора на версии:

Още полезни пакети

Въпроси