Texto resumido pela IA durumis
- O Rust é uma linguagem muito adequada para escrever CLIs, e implementamos um simples programa CLI com funcionalidades de login e logout usando as bibliotecas clap e ratatui.
- Usamos o clap para definir várias opções e subcomandos, e o ratatui para implementar uma janela de entrada interativa, melhorando a conveniência e a segurança.
- Em 18 de abril de 2024, o autor apresentou uma maneira conveniente de escrever programas CLI em Rust.
Minhas experiências com Rust me mostraram que esta linguagem é a melhor e mais conveniente para criar CLIs. Ao oferecer recursos avançados de macros, o Rust permite que os desenvolvedores definam todas as restrições e verificações em nível de estrutura, garantindo total controle sobre o tipo de dados e as restrições aplicadas.
Neste artigo, criaremos um exemplo simples de CLI que manipule login e logout usando clap e ratatui. Isso nos ajudará a entender os fundamentos da criação de CLIs e como elas podem ser aplicadas.
Configuração Básica do Clap
Primeiramente, adicione as quatro dependências a seguir:
```javascript atty = { version = "0.2.14", optional = true } structopt = { version = "0.3.18", optional = true } clap = { version = "4.4.18", features = ["derive"] } serde = { version = "1", features = ["derive"] }
As duas primeiras dependências são para mapeamento de comandos cargo, e as duas últimas são para análise de comando clap.
Agora, vamos adicionar o código passo a passo.
Primeiro, vamos definir o tipo de comando de nível superior e inserir um enum de subcomando dentro dele.
O enum SubCommand incluirá os comandos de login e logout que serão definidos em breve.
Ao inicializar o comando como mostrado acima, concluímos a estrutura básica.
Um programa criado dessa forma pode ser executado por meio de cargo run ou
instalado usando cargo install e, em seguida, executado.
Definindo Subcomandos
Agora, vamos definir os subcomandos um por um.
Login e Logout serão separados em subcomandos distintos.
Criamos um arquivo separado para definir o comando login primeiro.
Os elementos de flag são definidos por meio do objeto Option interno.
`short` especifica se um atalho como -i deve ser criado, e `long` especifica se um texto completo como --id deve ser criado. `help` é obviamente ajuda.
Para tornar essas flags elementos opcionais, você precisa definir o tipo como Option ou fornecer o atributo `default_value`.
Em seguida, adicione isso como uma variante ao objeto de comando de nível superior.
Agora é a vez do comando logout. Isso é mais fácil.
Não há muitas opções para fornecer.
Da mesma forma, registre-o como um subcomando do comando de nível superior.
No ponto de entrada, a ação também é ramificada como um enum, então manipule-a adequadamente usando correspondência de padrões.
Então, ao executar
você pode ver que foi adicionado à lista de subcomandos.
A execução também é bem-sucedida. Ele reclama se a flag obrigatória for omitida.
Ele funcionará bem se você fornecê-lo. No entanto, ele ainda não executa nenhuma ação.
Separação e Implementação de Ações
Vamos adicionar a lógica agora. Pessoalmente, prefiro separar a lógica por arquivo nessas situações. Fica muito confuso e sujo se for mesclado.
Criei um módulo de ação e separei um arquivo para cada ação de subcomando.
As funções de ação individuais recebem os valores de opção de cada subcomando como argumentos.
E delegue a execução no ponto de entrada para "run".
Parece bem organizado, não é?
Agora que estamos quase prontos, vamos implementar alguma lógica plausível.
O login foi configurado para enviar um arquivo de credenciais com base nas flags passadas.
O logout exclui o arquivo de credenciais gerado.
Então, ao tentar fazer login,
ele será gerado conforme digitado
e ao tentar fazer logout,
ele será excluído como esperado.
Implementação de Comandos Interativos com TUI
No entanto, se você tiver apenas um ou dois flags obrigatórios, tudo bem, mas se você tiver muitos, encontrar e inserir todos eles pode ser bastante trabalhso.
Alternativamente, expor a senha na tela pode ser um risco de segurança.
Nesses casos, pode ser desejável fornecer uma TUI para conveniência ou segurança.
Vamos implementar uma caixa de entrada interativa com mascaramento de senha usando ratatui, um ambiente TUI bastante útil para Rust.
Primeiro, adicione as duas dependências abaixo:
```javascript crossterm = "0.27.0" ratatui = "0.26.0"
E adicionei a opção de execução interativa ao flag de login.
Se essa opção for passada, o controle será movido para o contexto interativo.
Aqui começa a diversão.
Aqui está o código base.
Pode parecer um pouco complicado à primeira vista, mas o ponto principal é simples.
Ele está apenas em um loop infinito, renderizando continuamente o texto.
E sai do loop quando a entrada de tecla q é recebida.
Ao executar corretamente,
ele muda para um contexto de comando bastante chamativo.
Ele terminará se você inserir q.
Vamos implementar o processo de entrada agora.
Na verdade, não há muito a fazer.
Defina o processo como um tipo e defina o contexto de processo atual e as variáveis de entrada.
No início de cada loop, renderize o texto de orientação e o status de entrada atual de acordo com o passo atual.
Quando o status muda para concluído, todas as entradas são consideradas preenchidas, então o run é chamado novamente para reutilizar a lógica existente.
O tratamento de eventos é um pouco mais detalhado.
Habilitei a modificação da variável de entrada ou a transição para o próximo passo de acordo com cada etapa e entrada.
Ele apaga quando o backspace é pressionado, anexa quando um caractere é pressionado, termina o programa quando Esc é pressionado e move para o próximo passo quando Enter é pressionado.
Agora vamos executar novamente.
Ele é inserido corretamente como digitado
e a senha também é inserida mascarada.
Se você inserir tudo e pressionar Enter,
o programa será encerrado e o valor inserido também será liberado.
Você pode usá-lo assim.
Não é muito difícil, embora seja um pouco trabalhoso.
O código completo está disponível no link abaixo.