Skip to content

julienmoumne/hotshell

Repository files navigation

Hotshell Build Status

Interactive single keystroke menus for the shell

Hotshell is a command-line application to efficiently recall and share commands :

demo

Check out the definition and the simulated demo of this menu.

Quick tip : Name your definition file hs.js and hs will pick it up without having to specify a filename.

Content

Installation

Hotshell is currently supported on Linux, OSX and Windows (10+).

Precompiled packages

brew install julienmoumne/hotshell/hs

Install from source

go get github.com/julienmoumne/hotshell/cmd/hs

How to define menus

Menus are defined using a JavaScript DSL.

Building blocks

Menus are first defined with a top-level menu item

var item = require('hotshell').item

item({desc: 'top level menu'}, function () {
    
})

Command items associate bash commands to hot keys

item({desc: 'top level menu'}, function () {
    
  item({key: 's', cmd: 'sudo service apache2 status'})      
  item({key: 'r', cmd: 'sudo service apache2 restart'})      
  
  // a description can be used to clarify the command intent
  item({key: 'a', desc: 'access logs', cmd: 'less +F /var/log/apache2/access.log'})
  item({key: 'e', desc: 'error logs', cmd: 'less +F /var/log/apache2/error.log'})
})

Submenus and Description items can be used to add structure

item({desc: 'top level menu'}, function () {
    
  item({desc: 'this is a description item, you can use it to describe the menu\n'})
  
  // a submenu to manage apache's daemon
  item({key: 'm', desc: 'apache management'}, function () {
    item({key: 'r', cmd: 'sudo service apache2 restart'})      
    item({key: 'h', cmd: 'sudo service apache2 stop'})
  })
  
  // a submenu to access apache's logs
  item({key: 'l', desc: 'apache logs'}, function () {
    item({key: 'a', desc: 'access', cmd: 'less +F /var/log/apache2/access.log'})
    item({key: 'e', desc: 'error', cmd: 'less +F /var/log/apache2/error.log'})
  })      
})

See a simulated demo and the generated markdown documentation of the resulting menu.

Item properties

item({
  key: 'd', // key used to activate the menu item
  desc: 'directory listing', // description displayed when the item is shown in a menu
  cmd: 'ls -al', // command to execute when the item is activated, only used when not defining a menu (a group of items)
  wd: './subproject', // working directory (relative path) set prior to executing a command or 'exec()'
})

Tips & Examples

Check out tips and fully-featured examples.

JavaScript Runtime

exec

The system can be probed when defining menus using exec()

var exec = require('hotshell').exec

// executes the specified command using `bash -c` and returns the stdout if the command returned a non-zero exit code
stdoutString = exec(commandString)

In case of failure, stderr is displayed in the menu without stopping the interpretation of the DSL.

See some examples.

Underscore.js

Underscore.js is embedded by default in Hotshell.

var _ = require('underscore')

JavaScript Interpreter

The JavaScript is interpreted using Otto, an embeddable JavaScript interpreter. See Otto for available JavaScript functions.

DSL Interpreter

For more information on how the DSL is interpreted see Building Trees using a JavaScript DSL.

Configuration

Keybindings for menu actions can be customized in ~/.hsrc.js :

var settings = require('hotshell-settings')
var keys = settings.keys

settings.set({
  keys: {
    back: keys.Space,
    bash: keys.Tab,
    repeat: keys.Return,
    reload: keys.Backspace
  }
})

Supported keys are listed in Keys.go.

Project Motives

Being more productive using the shell

As developers and system admins we sometimes spend too much time finding and typing commands on the shell.

We rely on a variety of methods to recall commands : search engines, reverse-search-history, aliases, auto-completion, ..

While they are effective, they require superfluous lookups and keystrokes.

Hotshell can be used to define menus containing often and not so often used commands :

// file ~/.hs/hs.js  
item({desc: 'useful system commands'}, function () {
  item({key: 'f', desc: 'find text in files', cmd: 'echo -n "[location] [pattern] "; read l p; grep -rnws $l -e $p'})
  item({key: 'o', desc'check local port', cmd: 'echo -n "[port] "; read p; cat < /dev/tcp/127.0.0.1/$p'})
  // other useful commands..
})

Sharing commands

When working in teams we usually go through common steps such as compiling and running tests.

Some of these commands may be available on your IDE, some may not. Team members may not always have the same IDEs.

Most of the time though, IDE task configurations are not committed into the VCS and are therefore not shared.

Hotshell proposes both a way to :

  • spread command-line skills in teams
  • produce executable documentation

As an example, checkout Hotshell's hotshell