Введение в мир Rust и TUI

Знакома ситуация: пятничный вечер, в голове роится десяток идей для фич, а рабочий стол завален окнами браузера с открытыми Pull Request'ами, тяжелой IDE и тремя вкладками терминала для git-веток? (А потом ты случайно закрываешь не ту вкладку и теряешь всю мысль). Переключение между этим зоопарком утилит незаметно съедает фокус и превращает разработку в рутину. Представьте, что весь этот цирк можно уместить в один компактный терминал, который летает даже на старом ноутбуке. Именно для этого мы сегодня соберём собственный минималистичный TUI-инструмент.

Интерфейсы командной строки (CLI) долгое время оставались стандартом для разработчиков. Однако постоянное переключение между вкладками браузера для проверки Pull Request'ов, терминалом для git-команд и сторонними клиентами отвлекает и снижает продуктивность. Текстовые пользовательские интерфейсы (TUI) предлагают идеальный компромисс: они работают прямо в терминале, потребляют минимум оперативной памяти и обеспечивают наглядную визуализацию данных без графического окружения.

Благодаря строгой системе типов, отсутствию сборщика мусора и высокой производительности, язык Rust стал идеальным выбором для системного программирования. (Хотя первые пару недель компилятор будет методично объяснять вам, почему ваш код — это катастрофа). Написание собственного TUI-инструмента на Rust позволяет кастомизировать рабочий процесс под себя и избавиться от избыточного функционала тяжелых IDE.

В этой статье мы разберем, как спроектировать и написать минималистичный TUI-клиент для GitHub. Мы пройдем путь от инициализации проекта и выбора экосистемы до рендеринга интерфейса и асинхронной обработки событий в реальном времени.

Архитектура проекта и выбор зависимостей

Разобравшись с концепцией, перейдем к практике и заложим надежный фундамент нашего приложения. Чтобы терминал не зависал во время запросов к GitHub, а интерфейс отрисовывался плавно, нам понадобятся проверенные инструменты экосистемы.

Для создания нашего приложения мы задействуем лучшие практики экосистемы Rust. Нам понадобятся библиотеки для отрисовки интерфейса, работы с терминалом, асинхронного выполнения задач и сетевых запросов к GitHub API.

Ключевой стек технологий:

  • ratatui — современный стандарт де-факто для создания TUI-приложений в экосистеме Rust, форк популярного tui-rs.
  • crossterm — кроссплатформенный инструмент для управления терминалом, скрывающий различия между Linux, macOS и Windows.
  • tokio — асинхронный рантайм для обработки сетевых запросов без «фризов» интерфейса.
  • reqwest — удобный HTTP-клиент для взаимодействия с REST API GitHub.
  • serde / serde_json — быстрый парсинг JSON-ответов от сервера.

Инициализируем проект с помощью Cargo:

cargo new gh-tui-minimal
cd gh-tui-minimal

Добавим необходимые зависимости в файл Cargo.toml:

[package]
name = "gh-tui-minimal"
version = "0.1.0"
edition = "2021"

[dependencies]
ratatui = "0.26"
crossterm = "0.27"
tokio = { version = "1.0", features = ["full"] }
reqwest = { version = "0.11", features = ["json"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

Настройка основного цикла приложения и терминала

Имея на руках настроенные зависимости, мы готовы вдохнуть в приложение жизнь: заставить его слушать нажатия клавиш и отрисовывать первый фрейм без сбоев и артефактов.

Любое TUI-приложение строится вокруг цикла отрисовки (render loop) и обработки событий ввода (event loop). Нам нужно перевести терминал в сырой режим (raw mode), инициализировать буфер вывода и корректно вернуть настройки терминала при выходе, даже если произошла паника (ведь падать приложение должно красиво, оставляя чистый терминал вместо сломанной кодировки).

Создадим базовую структуру приложения в файле src/main.rs:

use std::{io, time::Duration};
use crossterm::,
    event::{self, Event, KeyCode},
    execute,
    terminal::{disable_raw_mode, enable