Найти тему
Nuances of programming

Создание CLI в Rust для исполнения гитарных аккордов

Оглавление

Источник: Nuances of Programming

Играете на гитаре и вынуждены постоянно искать в интернете аккорды для исполнения песен с менее распространенными аккордами?

А как насчет инструмента командной строки (CLI), который принимает на вход название аккорда и выводит аппликатуру, отображающую способ его исполнения?

В статье мы реализуем эту идею и с нуля создадим такой CLI в Rust.

Конечная цель

Итоговый результат работы  —  создание CLI с именем chord. Он принимает на вход одну строку, а именно название аккорда, и выводит его аппликатуру. Пример:

$ chord C
x ◯ ◯
┌─┬─┬─┬─┬─┐
│ │ │ │ ◯ │
├─┼─┼─┼─┼─┤
│ │ ◯ │ │ │
├─┼─┼─┼─┼─┤
│ ◯ │ │ │ │
└─┴─┴─┴─┴─┘

Почему Rust?

Rust выбран не случайно. По результатам опроса Stack Overflow, проведенного в 2021 году, он является самым излюбленным языком программирования:

-2

Rust отлично подходит как для создания бэкенд-сервисов, так и CLI.

К делу!

Установка Rust

Устанавливаем Rust следующим образом:

$ curl --proto '=https' --tlsv1.2 -sSf <https://sh.rustup.rs> | sh

Более подробная информация по установке предоставлена по ссылке.

Создание нового проекта Rust

$ cargo new chord --bin
Created binary (application) `chord` package

Компилируем и запускаем программу, проверяя корректность всех настроек:

$ cd chord
$ cargo run

Hello, world!

Полученный результат:

|-Cargo.toml
|-Cargo.lock
|-src
| |-main.rs

Вывод грифа

У гитары 6 струн. Как правило, для отображения постановки пальцев используется гриф.

На данный момент main.rs выглядит так:

fn main() {
println!("Hello, world!");
}

Внесем в него изменения для вывода пустого грифа:

const FRETBOARD: &str = "◯ ◯ ◯ ◯ ◯ ◯
┌─┬─┬─┬─┬─┐
│ │ │ │ │ │
├─┼─┼─┼─┼─┤
│ │ │ │ │ │
├─┼─┼─┼─┼─┤
│ │ │ │ │ │
└─┴─┴─┴─┴─┘";
fn main() {
println!("{}", FRETBOARD);
}

Выполняем программу и получаем следующий результат:

$ cargo run
◯ ◯ ◯ ◯ ◯ ◯
┌─┬─┬─┬─┬─┐
│ │ │ │ │ │
├─┼─┼─┼─┼─┤
│ │ │ │ │ │
├─┼─┼─┼─┼─┤
│ │ │ │ │ │
└─┴─┴─┴─┴─┘

Clap

Для парсинга аргументов командной строки потребуется библиотека Clap.

Присоединяем к проекту Clap в качестве зависимости:

$ cargo add clap --features derive

Эта команда просто добавляет следующую строку в cargo.toml, где описаны зависимости для Rust:

clap = { version = "3.2.21", features = ["derive"] }

Обновляем main.rs таким образом:

const FRETBOARD: &str = "◯ ◯ ◯ ◯ ◯ ◯
┌─┬─┬─┬─┬─┐
│ │ │ │ │ │
├─┼─┼─┼─┼─┤
│ │ │ │ │ │
├─┼─┼─┼─┼─┤
│ │ │ │ │ │
└─┴─┴─┴─┴─┘";

use clap::Parser;

/// CLI, показывающий, как сыграть гитарный аккорд
#[derive(Parser, Debug)]
#[clap(version, about)]
struct Args {
/// Название аккорда
#[clap()]
name: String,
}

fn main() {
let args = Args::parse();

println!("This is how you play '{}' chord: \n{}", args.name, FRETBOARD);
}

Макросы Rust значительно упрощают для Clap процедуру аннотации Args и обеспечивают бесплатный парсинг аргументов:

/// CLI, показывающий, как сыграть гитарный аккорд
#[derive(Parser, Debug)]
#[clap(version, about)]
struct Args {
/// Название аккорда
#[clap()]
name: String,
}

Проверяем:

$ cargo run -- --help
chord 0.1.0
A CLI to show you how to play a guitar chord

USAGE:
chord <NAME>

ARGS:
<NAME> Name of the chord

OPTIONS:
-h, --help Print help information
-V, --version Print version information

$ cargo run -- C
This is how you play 'C' chord:
◯ ◯ ◯ ◯ ◯ ◯
┌─┬─┬─┬─┬─┐
│ │ │ │ │ │
├─┼─┼─┼─┼─┤
│ │ │ │ │ │
├─┼─┼─┼─┼─┤
│ │ │ │ │ │
└─┴─┴─┴─┴─┘

Двойное тире --  —  это общепринятый способ указать на окончание параметров для cargo, а остальное передается программе CLI. Такой принцип действия характерен не только для cargo, но и многих других shell-команд.

Есть еще одна скрытая особенность, на которую стоит обратить внимание. Заметили, что A CLI to show you how to play a guitar chord (CLI, показывающий, как сыграть гитарный аккорд) и Name of the chord (Название аккорда) являются комментариями в исходном коде? Они также включены в справочное сообщение.

Из исходного кода:

/// A CLI to show you how to play a guitar chord
#[derive(Parser, Debug)]
#[clap(version, about)]
struct Args {
/// Name of the chord
#[clap()]
name: String,
}

Из вывода:

chord 0.1.0
A CLI to show you how to play a guitar chord
USAGE:
chord <NAME>

ARGS:
<NAME>
Name of the chord

Это вся необходимая информация, которую нужно знать о Clap. Переходим непосредственно к самому CLI.

CLI

Обновляем функцию main следующим образом:

fn main() {
let args = Args::parse();

let chords: HashMap<&str, &str> =
HashMap::from([("C", "x32010"), ("G", "320003"), ("D", "xx0232")]);

match chords.get(&args.name[..]) {
None => println!("Unknown chord '{}'", args.name),
Some(pattern) => {
let mut board: Vec<char> = FRETBOARD.chars().collect();
for (i, ch) in pattern.chars().enumerate() {
let idx: usize = i * 2;
if ch == 'x' {
board[idx] = ch
} else {
let value: usize = ch.to_digit(10).unwrap() as usize;
board[idx] = ' ';
board[idx + 24 * value] = '◯'
}
}
println!(
"This is how you play '{}' chord: \n{}",
args.name,
board.iter().collect::<String>()
)
}
}
}

Если название входного аккорда неизвестно, то выводится сообщение об ошибке Unknown chord. В противном случае мы накладываем постановку пальцев поверх пустого грифа, представленного ранее.

Тестируем код:

$ cargo run -- C

This is how you play 'C' chord:
x ◯ ◯
┌─┬─┬─┬─┬─┐
│ │ │ │ ◯ │
├─┼─┼─┼─┼─┤
│ │ ◯ │ │ │
├─┼─┼─┼─┼─┤
│ ◯ │ │ │ │
└─┴─┴─┴─┴─┘

$ cargo run -- Asus4
Unknown chord 'Asus4'

Отличный результат! Быстро и просто!

Установка

До сих пор мы компилировали и запускали CLI. cargo занимается не только сборкой, выполнением, управлением зависимостями библиотек, но и установкой.

Устанавливаем CLI chord:

cargo install --path .

И работаем с данным CLI напрямую:

$ chord G

This is how you play 'G' chord:
◯ ◯ ◯
┌─┬─┬─┬─┬─┐
│ │ │ │ │ │
├─┼─┼─┼─┼─┤
│ ◯ │ │ │ │
├─┼─┼─┼─┼─┤
◯ │ │ │ │ ◯
└─┴─┴─┴─┴─┘

Теперь вы знаете, как создать CLI в Rust.

Заключение

Забыли, как сыграть аккорд? Не беда  —  у вас под рукой отличный инструмент.

Переходите по ссылке в ветку blog-post-checkpoint, где предоставлен код для данной статьи. С новейшей версией CLI можно ознакомиться по ссылке на ветке master.

Читайте также:

Читайте нас в Telegram, VK

Перевод статьи Yuchen Z.: Build a Command Line Tool With Rust to Play Guitar Chords