Utilitários CLI em Rust: como escrever sua primeira ferramenta em uma noite

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que Rust é a escolha ideal para ferramentas CLI?

\n\n

Você já se perguntou por que todas as ferramentas DevOps modernas — de bat a ripgrep e fd — são escritas em Rust? Não é só por moda. Utilitários CLI em Rust são incrivelmente rápidos, seguros e, o melhor de tudo, podem ser compilados em um único binário minúsculo sem dependências. Nada de "você tem Java instalado?" ou "espere enquanto o Node.js baixa os node_modules". Basta baixar e pronto.

\n\n

Neste artigo, vamos criar um utilitário CLI em Rust do zero. Não será um "Hello, World!" abstrato, mas uma ferramenta real e útil — um analisador de logs que procura erros, conta a quantidade e exibe os resultados em um formato colorido bonito. E sim, faremos isso em uma noite.

\n\n

O que vamos precisar?

\n\n

Para começar, o mínimo necessário:

\n
    \n
  • Rust (instale via rustup, se ainda não tiver)
  • \n
  • Qualquer editor de código (VS Code com o plugin rust-analyzer é ideal)
  • \n
  • Algumas horas de tempo livre
  • \n
\n\n

Se você já programou em Python ou Go, Rust pode parecer incomum, mas é lógico. O importante é não ter medo do compilador. Ele não é malvado, ele é apenas cuidadoso.

\n\n

Passo 1: Criando o projeto

\n\n

Abra o terminal e digite:

\n
cargo new log-scanner\ncd log-scanner
\n\n

Cargo é o nosso canivete suíço. Ele criou a estrutura básica com Cargo.toml (arquivo de dependências) e src/main.rs (ponto de entrada). Já podemos executar cargo run e ver "Hello, world!". Mas vamos além.

\n\n

Abra o Cargo.toml e adicione as dependências que transformarão nosso código em um verdadeiro utilitário CLI em Rust:

\n
[dependencies]\nclap = { version = "4.5", features = ["derive"] }\ncolored = "2.1"\nanyhow = "1.0"
\n\n
    \n
  • clap — análise de argumentos de linha de comando (indispensável)
  • \n
  • colored — saída colorida no terminal
  • \n
  • anyhow — tratamento conveniente de erros
  • \n
\n\n

Passo 2: Definindo a estrutura de argumentos

\n\n

O mais legal do clap são os macros derive. Você simplesmente descreve a estrutura e a mágica acontece sozinha. Veja como fica:

\n\n
use clap::Parser;\n\n#[derive(Parser)]\n#[command(name = "log-scanner")]\n#[command(about = "Escaneia arquivos de log e procura por erros")]\nstruct Cli {\n    /// Caminho para o arquivo de log\n    file: String,\n\n    /// String a ser procurada (padrão "ERROR")\n    #[arg(short, long, default_value = "ERROR")]\n    pattern: String,\n\n    /// Mostrar apenas a quantidade de linhas encontradas\n    #[arg(short, long)]\n    count: bool,\n}
\n\n

Observe: comentários com três barras /// automaticamente se tornam dicas no --help. Execute cargo run -- --help — e você verá uma ajuda gerada de forma organizada. Esta é uma das razões pelas quais criar CLI em Rust é tão agradável: a documentação se escreve sozinha.

\n\n

Passo 3: Escrevendo a lógica de busca

\n\n

Agora a parte mais interessante — ler o arquivo e procurar correspondências. Rust é famoso por sua manipulação segura de arquivos e memória, mas na prática é simplesmente conveniente:

\n\n
use std::fs::File;\nuse std::io::{BufRead, BufReader};\nuse colored::*;\nuse anyhow::Result;\n\nfn scan_log(file_path: &str, pattern: &str, count_only: bool) -> Result<()> {\n    let file = File::open(file_path)?;\n    let reader = BufReader::new(file);\n    let mut total_matches = 0;\n\n    for (line_num, line) in reader.lines().enumerate() {\n        let line = line?;\n        if line.contains(pattern) {\n            total_matches += 1;\n            if !count_only {\n                println!(\n                    "{}:{} {}",\n                    format!("{:>4}", line_num + 1).blue(),\n                    patt                

Blogs

Book Recommendations