📣 Loved reading this? Check it out on the new polished decoupled site! ✨

Write command line applications with JS!

I personally write a lot of command line applications for my own use.

What’s the issue?

For example, Lando WordPress Setup is a complete command-line-based application written in bash. PS: With some Python also just required for templating (now thinking about that, seems like that also could have been avoided).

While it’s very performant and generalized to write code in bash, it might feel “overwhelming” (subjective opinion) in some places to perform some simple tasks. One great example of this might be getting command line arguments.

Also ultimately it’s just a simple program execution. So, you have to deal with all the edge cases, detecting command parameters, etc. Oh and sub-commands! And also lastly worth mentioning, help menus! Look at this custom help menu I wrote on the Lando WordPress setup project 😅 –

echo -e '
========== HELP MENU ==========

Usage: \033[1msetup.sh [name_of_the_project] [path/to/the/folder/to/setup/project] [(optional)ssh_or_https_link_to_clone_wp_content_repo]\033[0m

Arguments:
--wp : WordPress version.
--php: PHP version.
--node: Node version.
--multisite: Whether to create multisite or single site. yes OR no.
--multisitetype: Type of multisite. subdomain OR subdirectory.
--vip: Whether to create VIP template site or not. yes OR no.
--help: Display this help menu.

Example: setup.sh [project_name] ~/wordpress --multisite=yes --vip=yes git@github.com:[repo]

===============================
'

Now just to clarify, I am not saying that writing CLI applications is bash is bad. There might be libraries for making this process, but I am not aware.

What’s the solution?

Let’s welcome Commander!

TLDR; Commander is a JS package that makes writing command-line applications much easier.

Quick Note: The examples given below are directly taken from Commander’s documentation.

So, let’s directly take a look into how you can use Commander. So, let’s write a simple program that takes few arguments (you can put any number with any names you want) –

const { program } = require('commander');

program
  .option('--first')
  .option('-s, --separator <char>');

program.parse();

const options = program.opts();
const limit = options.first ? 1 : undefined;
console.log(program.args[0].split(options.separator, limit));

That’s it! We don’t have to manually parse any argument, all of them will be already parsed and available for our use inside the options variable. Just calling program.parse() does all the magic for you!

Next, let’s see how easily we can write sub-commands using Commander.

const { Command } = require('commander');
const program = new Command();

program
  .name('string-util')
  .description('CLI to some JavaScript string utilities')
  .version('0.8.0');

program.command('split')
  .description('Split a string into substrings and display as an array')
  .argument('<string>', 'string to split')
  .option('--first', 'display just the first substring')
  .option('-s, --separator <char>', 'separator character', ',')
  .action((str, options) => {
    const limit = options.first ? 1 : undefined;
    console.log(str.split(options.separator, limit));
  });

program.parse();

So, in the sub-command named split we can define options that will be parsed by Commander and will be made available to the commands handler function in the options argument.

And some more super cool features of Commander include –

  • Creates help menus automatically – It creates help menus for all commands and sub-commands using all the descriptions, etc. we provide to commands, arguments, options, etc. Which can be used simply like this – node split.js help split.
  • Auto-correct typo – It auto-corrects you when you make some typo while executing the command, for example, if you execute – node split.js -s / --fits a/b/c it throws an error like –
error: unknown option '--fits'
(Did you mean --first?)

Bonus point

And now you can create a npm package for this program and then use it as a full-fledged CLI command.

Conclusion

So, that was a quick little introduction to Commander for creating a command line tool using JS. There may be similar packages in JS, but Commander is one of my personal preferences.


Posted

in

Tags:

Comments

How was the blog?