Developing a command-line tool using Node is fun and much easier than other languages. Today yamatsuki has written an article summarizing how to write a friendly and robust CLI tool.
After reading this article, I highly recommend reading the Node CLI Tool Best Practices article on Github. True to its title, the 2000 star Github article is a best practice.
- Front-end engineering series
- Node advanced series
- Handwritten source code series
Command line tools and environment variable PATH
What is a command line tool?
The initial impression is that the system commands such as LS and PWD can be executed in the terminal. There are many such commands, which are called system built-in commands.
If you use “which” to find out where they came from, you can find out what they are like:
# PWD is a built-in command
$ which pwd
pwd: shell built-in command
Copy the code
As I understand and use Linux/Unix systems, I have discovered many non-built-in commands:
- top
- ps
- netstat
- dig
- man
Using which to get to the bottom of it, they actually execute in a bin directory
$ which top
/usr/bin/top
$ which ps
/bin/ps
Copy the code
These bin directories are in the environment variable PATH, and suddenly you see the light. In short: commands for paths in the environment variable PATH can be executed anywhere else.
export PATH=$HOME/bin:/usr/local/bin:$PATH
Copy the code
Speaking of environment variables, you can use env to list all of them.
$ env LANG=zh_CN.UTF-8 USER=root LOGNAME=root HOME=/root PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin Copy the code
What do you seem to be thinking about? Fears of being dominated by environment variables when configuring Java in college?
Yes, executable commands for all languages need to be placed under PATH, but installation tools for other languages do this for you automatically, while Java lets you handle it yourself.
- java
- python
- pip
- node
- npm
The same goes for developing command lines. Place your command-line tool scripts in the PATH under the environment variable PATH. The goal of this article is to:
Use Javascript, a language familiar to front-end developers, to develop a command-line tool with the help of the Node environment.
The principle of
First look at the command line tools for two nodes:
[serve](https://github.com/vercel/serve)
A popular static file server, the work of the Vercel team (the next.js team)markdown
A mountain moon writes its own parse URL to markdow’s command line. Parse the symbolic links to which they point by command
$ ls -lah $(which serve)
lrwxr-xr-x 1 xiange admin 65B 7 12 2020 /usr/local/bin/serve -> .. /.. /.. /Users/shanyue/.config/yarn/global/node_modules/.bin/serve $ ls -lah $(which markdown)
lrwxr-xr-x 1 xiange admin 48B 1 28 20:06 /usr/local/bin/markdown -> .. /lib/node_modules/markdown-read/md-read-cli.jsCopy the code
Here’s how the Node global command line works:
- NPM globally downloads a package to a path
/usr/local/lib/node_modules
Yarn The same path is used~/.config/yarn/global/node_modules
) - According to the library’s package.json
bin
Field to mount the corresponding command line PATH to the PATH PATH by symbolic index - Add x permissions to the corresponding binary script (executable file permissions)
In short, command line tools in the Node environment rely on nothing more than the environment variable Path and a symbolic link
From the package. The json
The bin field in package.json specifies the name of the final command line tool
{
"bin": {
"serve": "./bin/serve.js"}}Copy the code
As shown above, server is the command that is ultimately executed on the terminal, and./bin/serve.js is the script file that is actually executed by the command.
For final executable command-line tools, Node projects tend to place files in the bin directory, as Typescript does with its command-line configuration:
{
"bin": {
"tsc": "./bin/tsc"."tsserver": "./bin/tsserver"}},Copy the code
An execution environment
For files that can be executed directly, specify the execution environment and add the following line at the beginning:
#! /usr/bin/env node
// code down
Copy the code
What does this sentence mean?
#!
Add an interpreter to indicate the use of the file/usr/bin/env node
To perform the/usr/bin/env
Is the absolute PATH to env, used to execute commands in the PATH PATH (node command line location is different in various systems, so useenv node
Find the path and execute)env node
At the human level, it can be understood as executionnode
The command
This script is executed using the Node interpreter, and env node is able to locate the node interpreter correctly
// If not written#! /usr/bin/env node$node serve. // If#! The /usr/bin/env node can be executed directly
$ serve .
Copy the code
Parsing command input
In a server application, you can get user input from request.url. queryString and Request.body.
In the command line tool, user input is available via progress.argv. See the following example:
$ node cmd.js 1 2 3
Copy the code
// Output: [
// '/usr/local/bin/node',
// '/Users/shanyue/cmd.js',
/ / '1',
/ / '2',
/ / '3',
// ]
process.argv
Copy the code
Argv can be customized by parsing process.argv to take a variety of arguments as input to the command line. `
Of course, parsing parameters also follows the basic rules of POSIX compatibility: format, optional, required, shorthand, description, help, and so on. The command line tool naming protocol article is detailed enough.
// A more tidy command line help $node --help
Usage: node [options] [ script.js ] [arguments]
node inspect [options] [ script.js | host:port ] [arguments]
Options:
- script read from stdin (default if no file name is provided,
interactive mode if a tty)
-- indicate the end of node options
--abort-on-uncaught-exception aborting instead of exiting causes a core file to be generated for
analysis
-c, --check syntax check script without executing
--completion-bash print source-able bash completion script
--cpu-prof Start the V8 CPU profiler on start up, and write the CPU profile to
disk before exit. If --cpu-prof-dir is not specified, write the profile
to the current working directory.
Copy the code
Because POSIX is compatible with complex rules, it has derived several libraries about parsing command parameters, standing on the shoulders of giants, in the actual work directly open it!
- Yargs: Star 8.5K, weekly downloads 4900K
- Commander: Star 19.7K, weekly downloads 5300K, works of tJ
Here’s a Demo: Use Commander to parse different input commands
const { program } = require('commander')
// Parse different instruction inputs
program
.option('-d, --debug'.'output extra debugging')
.option('-s, --small'.'small pizza size')
.option('-p, --pizza-type <type>'.'flavour of pizza')
program.parse(process.argv)
const options = program.opts()
console.log(options)
Copy the code
User experience with rich colors
This is standard output from the Next Build command line, with colorful highlighting and rich list displays to provide a richer user experience.
Most terminals already support color output, which is controlled by ANSI coding, and have a mature library for color control. Such as ANSI – styles
import styles from 'ansi-styles';
console.log(`${styles.green.open}Hello world!${styles.green.close}`);
Copy the code
Rich highlighting, like code highlighting, allows users to quickly capture key points. The exception, warning, and success messages are color-coded so that the output of the command line tool is easy to see. Most modern build tools, such as Webpack, also support color output.
The following are two of the more advanced color libraries commonly used in command line tools that support the output of a wide variety of colors, although the basic principle is still ANSI encoding.
- chalk
- colors
The following example is Chalk, where Error and Warning messages are represented in different colors
const chalk = require('chalk')
const error = chalk.bold.red
const warning = chalk.keyword('orange')
console.log(error('Error! '))
console.log(warning('Warning! '))
Copy the code
interoperability
On the Web, Input can be used to present colorful forms such as switches, multiple selections, radio selections, Input fields, and so on.
In command line tools, multiple libraries can be borrowed to achieve strong interactivity.
- enquirer
- ora
- ink
Release and Installation
After the hard work of writing a CLI tool, it’s time to test the results. Publishing to the NPM repository enables everyone to use your command-line tools, which is the most important step
NPM login is required to login to NPM registory before publishing
$ npm publish
Copy the code
After the success of the global download command line tool, began to use, using it to grab my blog home page
$ npm i -g markdown-read
/usr/local/bin/markdown -> /usr/local/lib/node_modules/markdown-read/md-read-cli.js
+ [email protected]
added 102 packages from 72 contributors and updated 10 packages inS $33.15 markdown https://shanyue.tech## [#](# Santsuki's trivial blog entry) Santsuki's trivial blog entryThis blog is a summary of some articles about the problems encountered in front end, back end and operation and maintenance in ordinary work. Later will also do a series of articles for output, such as front-end advanced advanced series, personal server guide series. Personal wechat shanyue94, welcome to add communication## [#](# name origin) Name origin
Copy the code
conclusion
This article explains the following aspects from shallow to deep:
- What is the principle of a globally executable command line tool
- Configuration required to develop a command line tool in Node
- How to parse parameters when developing command-line tools
And according to the practice, developed a small tool to read Markdown from THE URL: Markdown -read, welcome Star, download and use.
In addition, I made a Web version based on this command line, welcome to experience: devtool.tech/html-md