How to Write Command-Line Applications in Ruby with GLI
I use many different command-line tools on a daily basis, e.g. git to track changes in projects, autojump to navigate faster between directories, brew to install software and so on. Some time ago I started watching my workflow. What I noticed is that some commands appeared more frequently than the others and they contained more typos. I decided to simplify usage of tools to have less problems with typing all options properly. Here is the short tutorial how to do that easily.
Motivation
In our internal server infrastructure at Lunar we deploy demo and production applications to different containers on different servers.
Let”s assume that to access container with deployed application we need to execute one of the commands below:
ssh user@app.demo.domain # demo
ssh user@app.domain # production
After some time I”ve noticed that I was repeating most of these steps:
- Make an SSH connection (every single time)
- Go into application”s directory
- Run rails console
- Run tail on application”s logs
- etc…
Gems for command-line apps
Writing applications with manual arguments parsing didn”t appeal to me so I”ve done research on existing gems. One of first results was Ruby Gems for Command-Line Apps page written by David Bryant Copeland. I browsed through the list and decided to give GLI gem a try.
Design
Let”s design a tool that solves or simplifies executing the steps mentioned earlier. Let”s call it blink.
Usage of blink may look like this:
blink shell app environment # connect an app"s directory
blink rails console app environment # connect an rails console
blink logs app environment # connect anapp"s logs
Implementation
You can follow the steps below or clone the blink-demo repository.
We need to install GLI first:
gem install gli
Then we create a scaffold project:
gli init blink shell rails logs
We focus only on bin and lib directories and following files in the structure:
.
├── bin
│ └── blink
└── lib
├── blink.rb
└── commands
├── base.rb
├── logs.rb
├── rails
│ └── console.rb
└── shell.rb
We create missing files and directories:
mkdir lib/commands
touch lib/commands/base.rb
touch lib/commands/logs.rb
mkdir lib/commands/rails
touch lib/commands/rails/console.rb
touch lib/commands/shell.rb
bin/blink
lib/blink.rb
lib/commands/base.rb
lib/commands/logs.rb
lib/commands/rails/console.rb
lib/commands/shell.rb
Further improvements
Our application is ready to use but we can still:
- install application (e.g. add bin directory to PATH environment variable)
- add more commands
- use configuration files and remove environment-dependent code