[![npm (scoped)](https://img.shields.io/npm/v/@ilg/cli-start-options.svg)](https://www.npmjs.com/package/@ilg/cli-start-options)
[![license](https://img.shields.io/github/license/xpack/cli-start-options-js.svg)](https://github.com/xpack/cli-start-options-js/blob/xpack/LICENSE)
[![Standard](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com/)
[![Travis](https://img.shields.io/travis/xpack/cli-start-options-js.svg?label=linux)](https://travis-ci.org/xpack/cli-start-options-js)
[![AppVeyor](https://ci.appveyor.com/api/projects/status/rydiijfkxr11essq?svg=true)](https://ci.appveyor.com/project/ilg-ul/cli-start-options-js)
[![GitHub issues](https://img.shields.io/github/issues/xpack/cli-start-options-js.svg)](https://github.com/xpack/cli-start-options-js/issues/)
[![GitHub pulls](https://img.shields.io/github/issues-pr/xpack/cli-start-options-js.svg)](https://github.com/xpack/cli-start-options-js/pulls)

## CLI startup and options processing

A Node.js module with classes to implement a command line Node.js application.

The module exports several classes (like CliApplication, CliCommand, ...)
that can be used as base classes for CLI applications.

## Prerequisites

A recent [Node.js](https://nodejs.org) (>=8.x), since the ECMAScript 6 class
syntax is used.

## Easy install

The module is available as
[`@ilg/cli-start-options`](https://www.npmjs.com/package/@ilg/cli-start-options)
from the public repository, use `npm` to install it inside the module where
it is needed:

```sh
npm install @ilg/cli-start-options --save
```

The module does not provide any executables, and generally there are few
reasons to install it globally.

The development repository is available from the GitHub
[xpack/cli-start-options-js](https://github.com/xpack/cli-start-options-js)
project.

## User info

The module can be included in CLI applications and the classes can be used
to derive application classes.

```javascript
// Equivalent of import { CliApplication, CliCommand, CliHelp, CliOptions } from 'cli-start-options'

const { CliApplication, CliCommand, CliHelp, CliOptions,
  CliError, CliExitCodes } = require('@ilg/cli-start-options')
```

## Developer info

### Git repo

```sh
git clone https://github.com/xpack/cli-start-options-js.git cli-start-options-js.git
cd cli-start-options-js.git
npm install
sudo npm link
ls -l /usr/local/lib/node_modules/@ilg
```

A link to the development folder should be present in the system
`node_modules` folder.

In projects that use this module under development, link back from the
global location:

```sh
npm link @ilg/cli-start-options
```

### Tests

The tests use the [`node-tap`](http://www.node-tap.org) framework
(_A Test-Anything-Protocol library for Node.js_, written by Isaac Schlueter).

As for any `npm` package, the standard way to run the project tests is via
`npm test`:

```sh
cd cli-start-options-js.git
npm install
npm test
```

A typical test result looks like:

```console
$ npm run test

> @ilg/cli-start-options@0.8.2 test /Users/ilg/My Files/MacBookPro Projects/xPack/npm-modules/cli-start-options-js.git
> standard && npm run test-tap -s

test/tap/020-errors.js .............................. 18/18
test/tap/030-options-common.js .................... 117/117
test/tap/040-module-invocation.js ..................... 9/9
test/tap/050-interactive.js ......................... 14/14
test/tap/060-cmd-copy.js ............................ 21/21
test/tap/070-author.js ................................ 8/8
total ............................................. 187/187

  187 passing (12s)

  ok
```

To run a specific test with more verbose output, use `npm run tap`:

```console
% npm run tap test/tap/060-cmd-copy.js -s

test/tap/060-cmd-copy.js
  xtest copy
    ✓ exit code is syntax
    ✓ has two errors
    ✓ has --file error
    ✓ has --output error
    ✓ has Usage

  xtest copy -h
    ✓ exit code is success
    ✓ has enough output
    ✓ has title
    ✓ has Usage
    ✓ has copy options
    ✓ has --file
    ✓ has --output
    ✓ stderr is empty

  xtest cop -h
    ✓ exit code is success
    ✓ has enough output
    ✓ has title
    ✓ has Usage
    ✓ stderr is empty

  xtest cop --file xxx --output yyy -q
    ✓ exit code is input
    ✓ stdout is empty
    ✓ strerr is ENOENT


  21 passing (2s)
```

### Coverage tests

Coverage tests are a good indication on how much of the source files is
exercised by the tests. Ideally all source files should be covered 100%,
for all 4 criteria (statements, branches, functions, lines).

To run the coverage tests, use `npm run test-coverage`:

```console
% npm run test-coverage

> @ilg/cli-start-options@0.9.0-pre test-coverage
> tap --coverage --reporter=classic --timeout 600 "test/tap/*.js"

test/tap/020-errors.js .............................. 18/18
test/tap/030-options-common.js .................... 117/117
test/tap/040-module-invocation.js ..................... 9/9
test/tap/050-interactive.js ......................... 14/14
test/tap/060-cmd-copy.js ............................ 21/21
test/tap/070-author.js ................................ 8/8
total ............................................. 187/187

  187 passing (12s)

  ok
ERROR: Coverage for lines (88.93%) does not meet global threshold (100%)
ERROR: Coverage for functions (89.07%) does not meet global threshold (100%)
ERROR: Coverage for branches (75.29%) does not meet global threshold (100%)
ERROR: Coverage for statements (88.93%) does not meet global threshold (100%)
------------------------------|---------|----------|---------|---------|-----------------------------------------------------------------------
File                          | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s                                                     
------------------------------|---------|----------|---------|---------|-----------------------------------------------------------------------
All files                     |   88.93 |    75.29 |   89.07 |   88.93 |                                                                       
 cli-start-options-js.git     |     100 |      100 |     100 |     100 |                                                                       
  index.js                    |     100 |      100 |     100 |     100 |                                                                       
 cli-start-options-js.git/lib |   88.91 |    75.29 |   89.07 |   88.91 |                                                                       
  cli-application.js          |   81.93 |    52.77 |   87.75 |   81.93 | ...156,185-189,453,812-815,823-841,861-865,879-928,993,1016,1024-1028 
  cli-command.js              |   83.75 |     62.5 |   83.33 |   83.75 | 115,124-125,199-218,235                                               
  cli-error.js                |   88.46 |      100 |      50 |   88.46 | 149-187                                                               
  cli-help.js                 |   99.47 |     88.8 |     100 |   99.47 | 91                                                                    
  cli-options.js              |   91.66 |    87.01 |      92 |   91.66 | 220-222,491,534-536,590-600                                           
------------------------------|---------|----------|---------|---------|-----------------------------------------------------------------------
```

### Continuous Integration (CI)

TBD

### Standard compliance

The module uses ECMAScript 6 class definitions.

As style, it uses the [JavaScript Standard Style](https://standardjs.com/),
automatically checked at each commit via Travis CI.

Known and accepted exceptions:

- `// eslint-disable-line node/no-deprecated-api` to continue using the
deprecated `domain` module

To manually fix compliance with the style guide (where possible):

```console
$ npm run fix

> @ilg/cli-start-options@0.9.0-pre fix
> standard --fix --verbose

```

### Documentation metadata

The documentation metadata follows the [JSdoc](http://usejsdoc.org) tags.

To enforce checking at file level, add the following comments right after
the `use strict`:

```js
'use strict'
/* eslint valid-jsdoc: "error" */
/* eslint max-len: [ "error", 80, { "ignoreUrls": true } ] */
```

Note: be sure C style comments are used, C++ styles are not parsed by
[ESLint](http://eslint.org).

### Publish to npmjs.com

- `npm run fix`
- commit all changes
- `npm run test-coverage` (not 100% yet)
- check the latest commits `npm run git-log`
- update `CHANGELOG.md`; commit with a message like __CHANGELOG: prepare v0.8.1
- `npm version patch` (bug fixes), `npm version minor` (compatible API
  additions), `npm version major` (incompatible API changes)
- `npm pack` and check the content
- push all changes to GitHub; this should trigger CI
- **wait for CI tests to complete** (not yet)
- `npm publish --tag next` (use `--access public` when publishing for the first time)

Check if the version is present at
[@ilg/cli-start-options Versions](https://www.npmjs.com/package/@ilg/cli-start-options?activeTab=versions).

### Change tag to latest

When stable:

- `npm dist-tag ls @ilg/cli-start-options`
- `npm dist-tag add @ilg/cli-start-options@0.8.2 latest`
- `npm dist-tag ls @ilg/cli-start-options`

## License

The original content is released under the
[MIT License](https://opensource.org/licenses/MIT), with all rights
reserved to [Liviu Ionescu](https://github.com/ilg-ul/).
