Coder Social home page Coder Social logo

meow's Introduction

meow

CLI app helper

I would recommend reading this guide on how to make user-friendly command-line tools.

Features

  • Parses arguments
  • Converts flags to camelCase
  • Negates flags when using the --no- prefix
  • Outputs version when --version
  • Outputs description and supplied help text when --help
  • Sets the process title to the binary name defined in package.json
  • No dependencies!

Install

npm install meow

Usage

./foo-app.js unicorns --rainbow
#!/usr/bin/env node
import meow from 'meow';
import foo from './lib/index.js';

const cli = meow(`
	Usage
	  $ foo <input>

	Options
	  --rainbow, -r  Include a rainbow

	Examples
	  $ foo unicorns --rainbow
	  🌈 unicorns 🌈
`, {
	importMeta: import.meta, // This is required
	flags: {
		rainbow: {
			type: 'boolean',
			shortFlag: 'r'
		}
	}
});
/*
{
	input: ['unicorns'],
	flags: {rainbow: true},
	...
}
*/

foo(cli.input.at(0), cli.flags);

API

meow(helpText, options)

meow(options)

Returns an object with:

  • input (Array) - Non-flag arguments
  • flags (Object) - Flags converted to camelCase excluding aliases
  • unnormalizedFlags (Object) - Flags converted to camelCase including aliases
  • pkg (Object) - The package.json object
  • help (string) - The help text used with --help
  • showHelp([exitCode=2]) (Function) - Show the help text and exit with exitCode
  • showVersion() (Function) - Show the version text and exit

helpText

Type: string

Shortcut for the help option.

options

Type: object

importMeta

Required
Type: object

Pass in import.meta. This is used to find the correct package.json file.

flags

Type: object

Define argument flags.

The key is the flag name in camel-case and the value is an object with any of:

  • type: Type of value. (Possible values: string boolean number)
  • choices: Limit valid values to a predefined set of choices.
  • default: Default value when the flag is not specified.
  • shortFlag: A short flag alias.
  • aliases: Other names for the flag.
  • isMultiple: Indicates a flag can be set multiple times. Values are turned into an array. (Default: false)
    • Multiple values are provided by specifying the flag multiple times, for example, $ foo -u rainbow -u cat. Space- or comma-separated values are currently not supported.
  • isRequired: Determine if the flag is required. (Default: false)
    • If it's only known at runtime whether the flag is required or not, you can pass a Function instead of a boolean, which based on the given flags and other non-flag arguments, should decide if the flag is required. Two arguments are passed to the function:
    • The first argument is the flags object, which contains the flags converted to camel-case excluding aliases.
    • The second argument is the input string array, which contains the non-flag arguments.
    • The function should return a boolean, true if the flag is required, otherwise false.

Note that flags are always defined using a camel-case key (myKey), but will match arguments in kebab-case (--my-key).

Example:

flags: {
	unicorn: {
		type: 'string',
		choices: ['rainbow', 'cat', 'unicorn'],
		default: ['rainbow', 'cat'],
		shortFlag: 'u',
		aliases: ['unicorns'],
		isMultiple: true,
		isRequired: (flags, input) => {
			if (flags.otherFlag) {
				return true;
			}

			return false;
		}
	}
}
description

Type: string | false
Default: The package.json "description" property

Description to show above the help text.

Set it to false to disable it altogether.

help

Type: string | false

The help text you want shown.

The input is reindented and starting/ending newlines are trimmed which means you can use a template literal without having to care about using the correct amount of indent.

The description will be shown above your help text automatically.

Set it to false to disable it altogether.

version

Type: string
Default: The package.json "version" property

Set a custom version output.

autoHelp

Type: boolean
Default: true

Automatically show the help text when the --help flag is present. Useful to set this value to false when a CLI manages child CLIs with their own help text.

This option is only considered when there is only one argument in process.argv.

autoVersion

Type: boolean
Default: true

Automatically show the version text when the --version flag is present. Useful to set this value to false when a CLI manages child CLIs with their own version text.

This option is only considered when there is only one argument in process.argv.

pkg

Type: object
Default: Closest package.json upwards

package.json as an object.

Note: Setting this stops meow from finding a package.json.

You most likely don't need this option.

argv

Type: string[]
Default: process.argv.slice(2)

Custom arguments object.

inferType

Type: boolean
Default: false

Infer the argument type.

By default, the argument 5 in $ foo 5 becomes a string. Enabling this would infer it as a number.

booleanDefault

Type: boolean | undefined
Default: false

Value of boolean flags not defined in argv.

If set to undefined, the flags not defined in argv will be excluded from the result. The default value set in boolean flags take precedence over booleanDefault.

Note: If used in conjunction with isMultiple, the default flag value is set to [].

Caution: Explicitly specifying undefined for booleanDefault has different meaning from omitting key itself.

Example:

import meow from 'meow';

const cli = meow(`
	Usage
	  $ foo

	Options
	  --rainbow, -r  Include a rainbow
	  --unicorn, -u  Include a unicorn
	  --no-sparkles  Exclude sparkles

	Examples
	  $ foo
	  🌈 unicorns✨🌈
`, {
	importMeta: import.meta,
	booleanDefault: undefined,
	flags: {
		rainbow: {
			type: 'boolean',
			default: true,
			shortFlag: 'r'
		},
		unicorn: {
			type: 'boolean',
			default: false,
			shortFlag: 'u'
		},
		cake: {
			type: 'boolean',
			shortFlag: 'c'
		},
		sparkles: {
			type: 'boolean',
			default: true
		}
	}
});
/*
{
	flags: {
		rainbow: true,
		unicorn: false,
		sparkles: true
	},
	unnormalizedFlags: {
		rainbow: true,
		r: true,
		unicorn: false,
		u: false,
		sparkles: true
	},
	…
}
*/
allowUnknownFlags

Type boolean
Default: true

Whether to allow unknown flags or not.

helpIndent

Type number
Default: 2

The number of spaces to use for indenting the help text.

Tips

See chalk if you want to colorize the terminal output.

See get-stdin if you want to accept input from stdin.

See conf if you need to persist some data.

More useful CLI utilities…

meow's People

Contributors

alexmcmanus avatar bartaz avatar bendingbender avatar callumlocke avatar chinanf-boy avatar idered avatar jamestalmage avatar jamiebuilds avatar jimthedev avatar kevva avatar litomore avatar macklinu avatar picchikevin avatar pvdlg avatar realityking avatar resynthesize avatar robertsasak avatar ryanrhee avatar samverschueren avatar shinnn avatar simenb avatar sindresorhus avatar thiagodp avatar tommy-mitchell avatar ulken avatar voxpelli avatar weareoutman avatar yash-singh1 avatar ybiquitous avatar ycmjason avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

meow's Issues

Doesn't Play Nice with Chalk Tagged Template Literal

It would seem that when using chalk tagged template literals (I haven't tested using chalk straight up in template literals) the formatting for meow's help goes awry.

Test snippet:

const cli = meow(chalk`
{underline Usage}
  $ mocha-chrome <file.html> [options]\n

{underline Options}
  --mocha      A JSON string representing a config object to pass to Mocha
  --log-level  Specify a log level; trace, debug, info, warn, error
  --no-colors  Disable colors in Mocha's output
  --reporter   Specify the Mocha reporter to use
  --timeout    Specify the test startup timeout to use

{underline Examples}
  $ mocha-chrome test.html --no-colors
  $ mocha-chrome test.html --reporter dot
  $ mocha-chrome test.html --mocha '\{"ui":"tdd"\}'
`);

Results in:

β†’ bin/mocha-chrome --help

  β˜•  Run Mocha tests using Google Chrome in Node.js

  Usage
    $ mocha-chrome <file.html> [options]n
  Options
    --mocha      A JSON string representing a config object to pass to Mocha
    --log-level  Specify a log level; trace, debug, info, warn, error
    --no-colors  Disable colors in Mocha's output
    --reporter   Specify the Mocha reporter to use
    --timeout    Specify the test startup timeout to usenn
  Examples
    $ mocha-chrome test.html --no-colors
    $ mocha-chrome test.html --reporter dot
    $ mocha-chrome test.html --mocha '{"ui":"tdd"}'

Notice the lack of spacing between sections, which is present in the template literal passed to meow. If I double the spaces between the sections in the string, then I get the expected one space between sections in the output.

Now, if I go with this plain, non-chalk string:

const cli = meow(`
Usage
  $ mocha-chrome <file.html> [options]\n

Options
  --mocha      A JSON string representing a config object to pass to Mocha
  --log-level  Specify a log level; trace, debug, info, warn, error
  --no-colors  Disable colors in Mocha's output
  --reporter   Specify the Mocha reporter to use
  --timeout    Specify the test startup timeout to use

Examples
  $ mocha-chrome test.html --no-colors
  $ mocha-chrome test.html --reporter dot
  $ mocha-chrome test.html --mocha '\{"ui":"tdd"\}'
`);

I get the output I would expect:

β†’ bin/mocha-chrome --help logLevel   

  β˜•  Run Mocha tests using Google Chrome in Node.js

  Usage
    $ mocha-chrome <file.html> [options]

  Options
    --mocha      A JSON string representing a config object to pass to Mocha
    --log-level  Specify a log level; trace, debug, info, warn, error
    --no-colors  Disable colors in Mocha's output
    --reporter   Specify the Mocha reporter to use
    --timeout    Specify the test startup timeout to use

  Example
    $ mocha-chrome test.html --no-colors
    $ mocha-chrome test.html --reporter dot
    $ mocha-chrome test.html --mocha '{"ui":"tdd"}'

I haven't had a chance to look at the code, but my guess is that it's not considering color/formatting codes when doing it's thing on the whitespace.

Automatic alias parsing

meow could automatically parse aliases from the help text, e.g.:

...
Options
  -d, --dir        Directory
  -r, --recursive  Recursive
...

Results in effective configuration:

{
  alias: {
    d: 'dir',
    r: 'recursive'
  }
}

We could enable/disable this behavior with another option, disabled by default for backwards compatibility.

The implementation could start as a simple regular expression.

Let me know if you'd be open to a pull request.

Allow users to specify their minimist parser and/or swap out minimist for substack

I'd like to create a project like subarg except move the options outside of the arg (e.g. $ foo --plugin autoprefixer [browsers: "last 2", remove: "false"]).

In lieu of letting us pass our own parsers, could we simply swap out minimist for subarg? It'd be the same thing except users would gain the ability to get arg specific args.

Browserify uses this so you're able to pass options within options. For instance: browserify -t [ foo --bar=555 ] main.js

Asking because we're working on the PostCSS CLI syntax postcss/postcss-cli#1 and I'm trying to use Meow.

Single-letter flags are turned lowercase

I'd like to have an option -R, but this get turned into {'r': true} because of camelcase-keys.

meow({ boolean: 'R' }).flags
=> { 'r': true }

This is useful for having v as --version and V as --verbose.

Autogenerate flag help when no helpMessage is given

I'm coming from commander, which autogenerates documentation on flags, and was surprised to see that meow's autoHelp feature doesn't do the same.

// in index.js
const cli = require('meow')({
  flags: {
    'initial-indent': {
      type: 'string',
      alias: 'n',
      description: 'Initial indentation level'
      default: '0'
    },
    indent: {
      type: 'string',
      alias: 'i',
      description: 'YAML indentation level'
      default: '2'
    }
  }
})
cli.showHelp()

should generate output something like

$ ./index.js

  My cool tool description

  Options:
    -n, --initial-indent  [value]  Initial indentation spaces.  Optional; default 0.
    -i, --indent          [value]  YAML indentation spaces.  Optional; default 2.

Noob

Hey,

I'm new to CLI's and how to use node to create them. I stumbled upon this repo and I read the features that meow provides and I really want to use it. Looking at the README.md I'm not exactly sure where to start or how to use meow.

I tried the example and I get the correct output but I'm a bit confused as to how this would be used to provide messages based on input to the CLI and how to act on input to the CLI.

I'm a noob when it comes to this and if I asked a dumb question above I'm sorry. Just want to be pointed in a better direction to understand how this all works and what role it plays when building a CLI.

πŸ™‚

Tests

Needs more tests.

Help much appreciated :)

Ava could return promise?

I realise that test.serial() is available but this could be a nice alternative because it makes test dependencies more explicit:

import test from 'ava';
import fn from './';

test('title', t =>
  fn('foo').then((data) => t.ok(data))
).then(() =>
  test('title2', t =>
    fn('bar').then((data) => t.ok(data))
  )
);

can not install with npm v3.8.9 (NodeJS v4.4.4)

npm install shows errors:

PS C:\> npm install -g meow
npm ERR! Windows_NT 6.1.7601
npm ERR! argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Users\\admin7\\AppData\\Roaming\\npm\\node_modules\\npm\\bin\\n
pm-cli.js" "install" "-g" "meow"
npm ERR! node v4.4.4
npm ERR! npm  v3.8.9
npm ERR! file C:\Users\admin7\AppData\Roaming\npm-cache\meow\3.7.0\package\package.json
npm ERR! code EJSONPARSE

npm ERR! Failed to parse json
npm ERR! No data, empty input at 1:1
npm ERR!
npm ERR! ^
npm ERR! File: C:\Users\admin7\AppData\Roaming\npm-cache\meow\3.7.0\package\package.json
npm ERR! Failed to parse package.json data.
npm ERR! package.json must be actual JSON, not just JavaScript.
npm ERR!
npm ERR! This is not a bug in npm.
npm ERR! Tell the package author to fix their package.json file. JSON.parse

npm ERR! Please include the following file with any support request:
npm ERR!     C:\npm-debug.log

here is the npm-debug.log:

0 info it worked if it ends with ok
1 verbose cli [ 'C:\\Program Files\\nodejs\\node.exe',
1 verbose cli   'C:\\Users\\admin7\\AppData\\Roaming\\npm\\node_modules\\npm\\bin\\npm-cli.js',
1 verbose cli   'install',
1 verbose cli   '-g',
1 verbose cli   'meow' ]
2 info using [email protected]
3 info using [email protected]
4 silly loadCurrentTree Starting
5 silly install loadCurrentTree
6 silly install readGlobalPackageData
7 silly fetchPackageMetaData meow
8 silly fetchNamedPackageData meow
9 silly mapToRegistry name meow
10 silly mapToRegistry using default registry
11 silly mapToRegistry registry https://registry.npmjs.org/
12 silly mapToRegistry data Result {
12 silly mapToRegistry   raw: 'meow',
12 silly mapToRegistry   scope: null,
12 silly mapToRegistry   name: 'meow',
12 silly mapToRegistry   rawSpec: '',
12 silly mapToRegistry   spec: 'latest',
12 silly mapToRegistry   type: 'tag' }
13 silly mapToRegistry uri https://registry.npmjs.org/meow
14 verbose request uri https://registry.npmjs.org/meow
15 verbose request no auth needed
16 info attempt registry request try #1 at 3:40:07 PM
17 verbose request id eea792ea4a83a85c
18 verbose etag "5EAEC0HULK1YO4DEWF66VEVH6"
19 http request GET https://registry.npmjs.org/meow
20 http 304 https://registry.npmjs.org/meow
21 verbose headers { date: 'Fri, 06 May 2016 19:40:10 GMT',
21 verbose headers   via: '1.1 varnish',
21 verbose headers   'cache-control': 'max-age=300',
21 verbose headers   etag: '"5EAEC0HULK1YO4DEWF66VEVH6"',
21 verbose headers   age: '242',
21 verbose headers   connection: 'keep-alive',
21 verbose headers   'x-served-by': 'cache-dfw1831-DFW',
21 verbose headers   'x-cache': 'HIT',
21 verbose headers   'x-cache-hits': '7',
21 verbose headers   'x-timer': 'S1462563610.276427,VS0,VE0',
21 verbose headers   vary: 'Accept-Encoding' }
22 silly get cb [ 304,
22 silly get   { date: 'Fri, 06 May 2016 19:40:10 GMT',
22 silly get     via: '1.1 varnish',
22 silly get     'cache-control': 'max-age=300',
22 silly get     etag: '"5EAEC0HULK1YO4DEWF66VEVH6"',
22 silly get     age: '242',
22 silly get     connection: 'keep-alive',
22 silly get     'x-served-by': 'cache-dfw1831-DFW',
22 silly get     'x-cache': 'HIT',
22 silly get     'x-cache-hits': '7',
22 silly get     'x-timer': 'S1462563610.276427,VS0,VE0',
22 silly get     vary: 'Accept-Encoding' } ]
23 verbose etag https://registry.npmjs.org/meow from cache
24 verbose get saving meow to C:\Users\admin7\AppData\Roaming\npm-cache\registry.npmjs.org\meow\.cache.json
25 verbose correctMkdir C:\Users\admin7\AppData\Roaming\npm-cache correctMkdir not in flight; initializing
26 silly install normalizeTree
27 silly loadCurrentTree Finishing
28 silly loadIdealTree Starting
29 silly install loadIdealTree
30 silly cloneCurrentTree Starting
31 silly install cloneCurrentTreeToIdealTree
32 silly cloneCurrentTree Finishing
33 silly loadShrinkwrap Starting
34 silly install loadShrinkwrap
35 silly loadShrinkwrap Finishing
36 silly loadAllDepsIntoIdealTree Starting
37 silly install loadAllDepsIntoIdealTree
38 silly resolveWithNewModule [email protected] checking installable status
39 silly cache add args [ 'meow', null ]
40 verbose cache add spec meow
41 silly cache add parsed spec Result {
41 silly cache add   raw: 'meow',
41 silly cache add   scope: null,
41 silly cache add   name: 'meow',
41 silly cache add   rawSpec: '',
41 silly cache add   spec: 'latest',
41 silly cache add   type: 'tag' }
42 silly addNamed meow@latest
43 verbose addNamed "latest" is being treated as a dist-tag for meow
44 info addNameTag [ 'meow', 'latest' ]
45 silly mapToRegistry name meow
46 silly mapToRegistry using default registry
47 silly mapToRegistry registry https://registry.npmjs.org/
48 silly mapToRegistry data Result {
48 silly mapToRegistry   raw: 'meow',
48 silly mapToRegistry   scope: null,
48 silly mapToRegistry   name: 'meow',
48 silly mapToRegistry   rawSpec: '',
48 silly mapToRegistry   spec: 'latest',
48 silly mapToRegistry   type: 'tag' }
49 silly mapToRegistry uri https://registry.npmjs.org/meow
50 verbose addNameTag registry:https://registry.npmjs.org/meow not in flight; fetching
51 verbose get https://registry.npmjs.org/meow not expired, no request
52 silly addNameTag next cb for meow with tag latest
53 silly addNamed [email protected]
54 verbose addNamed "3.7.0" is a plain semver version for meow
55 silly rollbackFailedOptional Starting
56 silly rollbackFailedOptional Finishing
57 silly runTopLevelLifecycles Starting
58 silly runTopLevelLifecycles Finishing
59 silly install printInstalled
60 verbose stack Error: Failed to parse json
60 verbose stack No data, empty input at 1:1
60 verbose stack
60 verbose stack ^
60 verbose stack     at parseError (C:\Users\admin7\AppData\Roaming\npm\node_modules\npm\node_modules\read-package-json\read-json.js:390:11)
60 verbose stack     at parseJson (C:\Users\admin7\AppData\Roaming\npm\node_modules\npm\node_modules\read-package-json\read-json.js:79:23)
60 verbose stack     at C:\Users\admin7\AppData\Roaming\npm\node_modules\npm\node_modules\read-package-json\read-json.js:48:5
60 verbose stack     at C:\Users\admin7\AppData\Roaming\npm\node_modules\npm\node_modules\graceful-fs\graceful-fs.js:78:16
60 verbose stack     at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:380:3)
61 verbose cwd C:\
62 error Windows_NT 6.1.7601
63 error argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Users\\admin7\\AppData\\Roaming\\npm\\node_modules\\npm\\bin\\npm-cli.js" "install" "-g" "meow"
64 error node v4.4.4
65 error npm  v3.8.9
66 error file C:\Users\admin7\AppData\Roaming\npm-cache\meow\3.7.0\package\package.json
67 error code EJSONPARSE
68 error Failed to parse json
68 error No data, empty input at 1:1
68 error
68 error ^
69 error File: C:\Users\admin7\AppData\Roaming\npm-cache\meow\3.7.0\package\package.json
70 error Failed to parse package.json data.
70 error package.json must be actual JSON, not just JavaScript.
70 error
70 error This is not a bug in npm.
70 error Tell the package author to fix their package.json file. JSON.parse
71 verbose exit [ 1, true ]

Create extension

I want to create a Google extension that takes a value in the number of a field in a specific page, checks another text value in another field (this value in text will represent a value in my code, with that two values it will calculate the value percentage of the first value with the second, then it will show that percentage of the side of the first value on the page.

I'm a beginner in programming I'm studying the basics still, I want to develop this extension to practice creating something

Can I create all this in HTML? Do I need to be part of Java? Is it possible to create? And leave it acting automatically as if it were part of the code?

Parse Aliases

I know that now to parse need use aliases package (related #24).

One of my projects consists of scripts (about a hundred) to run in Continuous Integration.

I have to add the same lines in each file.

const aliases = require('aliases');

meow(help, { alias: aliases(help, {h: 'help'}) });

I think that we can add parseAliases option to simplify API.

const help = `
    Usage
      $ unicorn <name>

    Options
      -r, --rainbow  Lorem ipsum dolor sit amet
      -m, --magic    Aenean commodo ligula eget dolor
`;

meow(help, { parseAliases: true });

I'd really like to have this feature by default.

We can parse aliases if alias option is not specified. It won't break backward compatibility.

Flags containing hyphens are split and not parsed correctly

I wanted to add some --no-x flags but meow doesn't handle them properly. Looks like they get split in the middle and aliased versions do not work either.

{
    flags: {
      columns: {
        type: 'string',
        alias: 'c',
      },
      'no-color': {
        alias: 'nc',
        type: 'boolean',
      },
      'no-map': {
        alias: 'nm',
        type: 'boolean',
      },
    },
  },

Calling node index.js package.json --no-map --no-color --columns 16 returns

{ noColor: false,
  nc: false,
  noMap: false,
  nm: false,
  map: false,
  color: false,
  columns: '16',
  c: '16',
}

instead of this (fields have been fixed too to resemble the actually passed ones):

{ noColor: true,
  nc: true,
  noMap: true,
  nm: true,
  noColor: true,
  columns: '16',
  c: '16',
}

Support `required` flags

Issuehunt badges

Some options must always be specified.

I want to have a way to specify the required options in API.

Example

const cli = meow(`
    Usage
      $ process

    Options
      -i, --input   Input file
      -o, --output  Output file

    Examples
      $ process --input=lib/file.js --output=dest/file.js
`, {
    required: ['input', 'output']
});

A program without required options must quit with an error message.

$ process --output=dest/file.js

Missing required option:
    --input, -i  Input file

IssueHunt Summary

sbencoding sbencoding has been rewarded.

Backers (Total: $60.00)

Submitted pull Requests


Tips

Help shortcut

Currently, I do this in most CLI's without defining any other options:

meow({
    help: [
        'Example',
        '  $ fullname',
        '  Sindre Sorhus'
    ]
});

Maybe we should add a help shortcut?

meow([
    'Example',
    '  $ fullname',
    '  Sindre Sorhus'
]);

So the first argument can either be the help or an object of options.

@kevva @arthurvr @shinnn Thoughts?

How to prevent inferring type of flags

Hey,

My script can accept migration name as a --to parameter, but meow keeps casting it to number when someone writes only first part of migration (e.g. 20160905185721). Is there a way to prevent such cast, I want always a string? Tried following with no luck:

{
  minimistOptions: {
    string: ['to', 'from', 'only', 't', 'from', 'o']
  },
  inferType: false
}

Error helper

Most of my CLI's have this:

var cli = meow();

fn(function (err) {
    if (err) {
        console.error(err.message);
        process.exit(1);
    }
});

Wonder if we could abstract out the error handling.

Eg:

var cli = meow();

fn('unicorn', function (err) {
    cli.handleError(err);
});

It could potentially also handle showing the stack when --verbose is passed.

Thoughts?

// @kevva @floatdrop @arthurvr @shinnn

Bundle dependencies

I usually don't care to do this, but it would be nice if meow was simply one dependency as it would help the install time on lots of small CLIs.

Not exactly sure the best way to do this. It should be something that doesn't add any build-script for development, meaning, everything should be handled in a prepublish script.

Maybe npm-packager or just build it with Webpack.

Suggestions and help welcome.

Add a `booleanish` option

This came up while implementing the --debug flag for AVA.

Basically, there are two ways to use the debug flag:

# default port (5858)
ava --debug test.js

# specific port
ava --debug=1234 test.js

# not allowed - this won't work
ava --debug 1234 test.js

The reason you can't use the last one is because it's ambiguous whether you meant "run two test files with the default port" or "run one file with port 1234".

When you specify the flag as boolean:

meow(help, {
  boolean: [
    'debug'
  ]
});

You get true or false regardless. However you must specify it as a boolean, or this:

ava --debug test.js

To be interpreted as:

{
  flags: {
    debug: 'test.js'
  }
}

My solution was to set debug up as a boolean, then if I got true, reparse argv to find the port

I think it might be interesting to allow this:

meow(helper, {
  booleanish: {
    debug: {
      true: 5858,
      false: false,
      parse: function (value) {
        value = parseInt(value, 10);

        if (isNaN(value)) {
          throw new Error('must be a number');
        }

        return value;
      }
    }
  }
});

The basic usage of the booleanish option is:

  • true: What gets returned if it is used as a boolean flag --debug
  • false: What gets returned if no flag appears (or --no-debug is used).
  • parse: If they use the --debug=XXX - this function is used to parse the XXX part. It can throw an Error for invalid values, and meow should print the Error message, and exit.

This would greatly ease the creation of dual purpose flags that can be used either as simple booleans, or be supplied with a config value.

Blows up if `pkg.bin` is a string

... is troublesome since the ternary reports true on a string, but then the interpreter spews when trying to call Object.keys on it.

I would've provided tests + a fix but your test suit does not (to my knowledge) allow the input of arbitrary pkg objects

use case, to wrap up

"bin": "bin/browser-sync.js",
/Users/shakyshane/sites/oss/browser-sync/node_modules/meow/index.js:36
        process.title = pkg.bin ? Object.keys(pkg.bin)[0] : pkg.name;
                                         ^
TypeError: Object.keys called on non-object
    at Function.keys (native)
    at module.exports (/Users/shakyshane/sites/oss/browser-sync/node_modules/meow/index.js:36:35)
    at Object.<anonymous> (/Users/shakyshane/sites/oss/browser-sync/bin/browser-sync.js:14:11)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
    at node.js:814:3

Outputs "undefined" if there is no description

I don't want to output my package.json description at the top of my CLI's help text. There's no obvious way to disable this.

I tried passing in a custom pkg object, omitting the description field:

import meow from 'meow';
import pkg from '../package.json';

const cli = meow(`
  Blah blah blah.
`, {
  pkg: {version: pkg.version}
});

...but this results in:

$ foo --help
  undefined

  Blah blah blah.

I guess I could set the description to "" but that feels like a hack and leaves an extra newline.

This is a nice little library btw!

Parse custom `input` name

const cli = meow(`
    Usage
      $ foo <bar>

    Options
      --rainbow, -r  Include a rainbow
`, {customInput: true});
/*
{
    bar: ['unicorns'], // <-----------------
    flags: {rainbow: true},
    ...
}
*/

Spaces instead of tab in help

When using the help section you need to use tabs to indent not spaces. For example with a tab vs 4 spaces before --background.

Works

const cli = meow(`
	Usage
	  $ astro [input]
	Options
	  --help            Show help menu
	  --background      Start background importing
`);

Unaligned

const cli = meow(`
	Usage
	  $ astro [input]
	Options
	  --help            Show help menu
          --background      Start background importing
`);

@sindresorhus if this is intended feel free to close as I mainly opened this for others that come searching the issues section as to why their help section isn't aligned correctly.

Print help manually

Is there a way to print help manually? like if something goes wrong we just show help message with something like: meow.help()? and it exactly print the foo --help result?

[Question] How to enable alias

I want to avoid this

var save = cli.flags.s || cli.flags.save

and simply check cli.flags.save instead.

Checking the documentation I require meow as:

var cli = require('meow')({
  pkg: pkg,
  help: fs.readFileSync(__dirname + '/help.txt', 'utf8'),
  alias: {
    f: 'file',
    s: 'save'
  }
})

but doesn't work. Any idea? :(

Allow script to transform flag input via callback

WHAT
Allow dependent scripts to (optionally) specify how flag input should be parsed by providing callback functions at instantiation time.

Callback functions would be applied to the raw CLI input, and the resulting values would be exposed to the dependent script as normal (eg. via cli.flags).

For example:

meow( {
    flags: {
        unicorn: {
            alias: 'u',
            callback: value => {
                // Perform transformation and return result. 
            }
        }
    }
} );

WHY
This would be useful for cases where the underlying API requires an array value for a specific option.

Rather than updating the API to support/parse both arrays and strings, the transformation could be handled directly in the CLI layer.

For example:

meow( {
    flags: {
        excludes: {
            callback: value => {
                return value.split(',');
            }
        }
    }
} );
$ <cli command> <input> --excludes logs,temp,dist // [ 'logs', 'temp', 'dist' ]

HOW
I've stubbed out an initial implementation and test on my fork, which I'd be happy to submit for review.

NOTES
I stumbled on Issue #44 after digging into this proposed update. I'm not sure what the state of that issue is, but it looks like there's at least some overlap in terms of functionality.

Custom Arguments Object (option.argv) not working?

Hi there!

I'm having a little trouble figuring out how to use the documented {argv} option. Maybe I'm completely missing something obvious, in which case, apologies.

From the docs:

argv

Type: array
Default: process.argv.slice(2)

Custom arguments object.

Here's my code:

const help = `
	Usage
	  $ yay

	Options
	  -r, --root Root directory
`

const cli = meow(help, {argv: ['--root', 'foo']})

// What I'm expecting...
console.log(cli.flags) // {root: 'foo'}
console.log(cli.input) // ['root', 'foo']

// What I'm seeing...
console.log(cli.flags) // {}
console.log(cli.input) // []

// Same applies to...
const cli = meow(help, {argv: ['root', 'foo']})
const cli = meow(help, {argv: ['-r', 'foo']})

Any ideas?

Configurable version option

In node-sass, we want to print both node-sass and libsass (the base lib) versions when user queries node-sass --version (or even node-sass -v) like so:

node-sass version: 2.0.1
libsass version: 3.1.0

without changing the semver "version": "2.0.1", in package.json.

Please make the version option configurable in addition to the default behavior (console.log(pkg.version)).

stdin support?

If you haven't noticed I'm having a blast here stealing your code but I realized: meow has no piping support. Any plans on adding it?

fix v4.0.0 release notes

sorry for opening an issue about this, but not sure how else to inform.

The release notes showed this:


Before

const cli = meow(
	`
		Help text
	`,
	boolean: [
		'unicorn'
	],
	string: [
		'fooBar'
	],
	alias: {
		u: 'unicorn'
	},
	default: {
		foobar: 'foo'
	}
});

After

const cli = meow(
	`
		Help text
	`,
	flags: {
		unicorn: {
			type: 'boolean',
			alias: 'u'
		},
		fooBar: {
			type: 'string',
			default: 'foo'
		}
	}
});

However, I think the the outer object is missing.

For example,

const cli = meow(
	`
		Help text
	`,
	boolean: [
		'unicorn'
	],
	string: [
		'fooBar'
	],
	alias: {
		u: 'unicorn'
	},
	default: {
		foobar: 'foo'
	}
});

should be

const cli = meow(
	`
		Help text
	`,
        {
		boolean: [
			'unicorn'
		],
		string: [
			'fooBar'
		],
		alias: {
			u: 'unicorn'
		},
		default: {
			foobar: 'foo'
		}
        }
});

and same for the other place. i got a bit confused by this so thought it was worth mentioning

Allow subcommands to handle --help

Currently when handling subcommands using separate meow instances like this:

const bar = argv => {
	const cli = meow({
		argv,
		help: `
		  Usage
		    $ foo bar <input>
	`});
};

const cli = meow(`
	Usage
	  $ foo <command>

	Commands
	  bar
`);

// Check cli.input and handle commands

If the user enters $ foo bar --help they get the help for foo and not foo bar

There's a wrapper called moggie that handles subcommands, but I was thinking we could to add a commands: [commands] option to meow so it doesn't block the --help flag?

Meow could either:

  • Not show help if a command is matched, leaving everything else to the user to handle
  • Handle the argv filtering and return the matched command and filtered argv

I'm happy to write something and submit a PR.

Autocompletion?

Have you guys thought about tabbed autocompletion support for commands, flags and file system? This could go to this module directly, or add a tip if there another module doing it.

Using meow probably breaks Electrons launch-process

I'm using meow to parse any cli-options and decisively exit the launch, showing the help:

const _ = require('lodash');
const meow = require('meow');

module.exports = () => {
    const cli = meow(`
        Options:

        Usage:
`);

    if (_.isArray(cli.flags) &&
        _.includes(cli.flags, 'help')
    ) {
        cli.showHelp(0);
    }

    return cli;
}

This generates the following Warnings in the console and the readyevent gets never fired:

node v5.10.0
electron 0.37.8
May  3 12:48:39  [99560] <Warning>: CGSConnectionByID: 0 is not a valid connection ID.
...
May  3 12:48:39  [99560] <Warning>: CGSConnectionByID: 0 is not a valid connection ID.
May  3 12:48:39  [99560] <Warning>: Invalid Connection ID 0
event 'will-finish-launching' fired.
May  3 12:48:39  [99560] <Warning>: CGSConnectionByID: 0 is not a valid connection ID.
...

If comment the whole export out, it runs like a glance:

node v5.10.0
electron 0.37.8
event 'will-finish-launching' fired.
event 'ready' fired.

It is probably worth mentioning, that the event-subscription happens immediately after the cli-parsing.
If there is anything i can do - give me a hint! πŸ‘‹

npm ERR! Invalid name: "<%= moduleName %>" when trying to install

Getting this error when trying to install:

npm install --save meow
npm ERR! Darwin 14.5.0
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "install" "--save" "meow"
npm ERR! node v4.2.3
npm ERR! npm  v2.14.7

npm ERR! Invalid name: "<%= moduleName %>"
npm ERR! 
npm ERR! If you need help, you may report this error at:
npm ERR!     <https://github.com/npm/npm/issues>

Here is debug-log:

0 info it worked if it ends with ok
1 verbose cli [ '/usr/local/bin/node',
1 verbose cli   '/usr/local/bin/npm',
1 verbose cli   'install',
1 verbose cli   '--save',
1 verbose cli   'meow' ]
2 info using [email protected]
3 info using [email protected]
4 verbose install initial load of /Volumes/Macintosh HD/Users/dmitrizaitsev/Dropbox/p/WebDev/Sandbox/Sindre-start-project/package.json
5 verbose stack Error: Invalid name: "<%= moduleName %>"
5 verbose stack     at ensureValidName (/usr/local/lib/node_modules/npm/node_modules/normalize-package-data/lib/fixer.js:331:15)
5 verbose stack     at Object.module.exports.fixNameField (/usr/local/lib/node_modules/npm/node_modules/normalize-package-data/lib/fixer.js:210:5)
5 verbose stack     at /usr/local/lib/node_modules/npm/node_modules/normalize-package-data/lib/normalize.js:32:38
5 verbose stack     at Array.forEach (native)
5 verbose stack     at normalize (/usr/local/lib/node_modules/npm/node_modules/normalize-package-data/lib/normalize.js:31:15)
5 verbose stack     at final (/usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:338:5)
5 verbose stack     at then (/usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:113:5)
5 verbose stack     at /usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:232:12
5 verbose stack     at /usr/local/lib/node_modules/npm/node_modules/graceful-fs/graceful-fs.js:76:16
5 verbose stack     at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:380:3)
6 verbose cwd /Volumes/Macintosh HD/Users/dmitrizaitsev/Dropbox/p/WebDev/Sandbox/Sindre-start-project
7 error Darwin 14.5.0
8 error argv "/usr/local/bin/node" "/usr/local/bin/npm" "install" "--save" "meow"
9 error node v4.2.3
10 error npm  v2.14.7
11 error Invalid name: "<%= moduleName %>"
12 error If you need help, you may report this error at:
12 error     <https://github.com/npm/npm/issues>
13 verbose exit [ 1, true ]
npm-debug.log (END) 

Consider allowing configuration to be loaded from `package.json`.

Like what yargs does with pkgConf. If I had a package.json like

"someKey": {
  "someFlag": "someValue"
}

and told meow to look at someKey, it'd take that configuration into account. Maybe you could even pass someKey as an argument, like

myTool -configKey someKey

Only show error stack if `--verbose` flag is set

We discussed this briefly in a commit in dev-time-cli.

At the moment, when an error occurs and it is not handled by the developer, the entire error stack is shown.

devTime(cli.input[0], cli.flags).then(result => {
    console.log(time);
});
$ dev-time 0
TypeError: Expected a user
    at module.exports (/Users/sam/Projects/opensource/dev-time-cli/node_modules/dev-time/index.js:59:25)
    at Object.<anonymous> (/Users/sam/Projects/opensource/dev-time-cli/cli.js:41:1)
    at Module._compile (module.js:435:26)
    at Object.Module._extensions..js (module.js:442:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Function.Module.runMain (module.js:467:10)
    at startup (node.js:134:18)
    at node.js:961:3

This was before I disabled argument type parsing

When an error occurs, you got that "ugly" error string representation with the entire stacktrace. While this is very usefully, especially for debugging and reporting issues, it's not that user friendly.

proposal

Show a nice and clean error message. Something like pageres (but instead logSymbols.error).

screen shot 2015-12-09 at 10 13 19

If you want the entire stack trace, use the --verbose (or -v) flag.

Feedback and opinions more then welcome.

// @sindresorhus @kevva @Qix- @arthurvr

Idea: adopt docopt

It would be awesome if meow could adopt http://docopt.org/ to deduce additional behaviour from the help text. This could be

  • disabled by default
  • help with #69
  • add more validation to user input
  • ...

meow-plus

An idea, maybe totally silly.

I was thinking of bundling every little tools I use when creating a new CLI, sort of like meow does.

I would usually need everything meow does plus:

  • A lightweight logger, ideally based on debug and npmlog
  • tab completion, something like integrating tabtab here but with completion registered automatically from help output and parse-help
  • chalk & log-symbos, maybe tightly integrated with the logger. I kinda like being able to do Hello:red Sindre:bold (:color used to escape strings with chalk methods)
  • stdin helpers (#20)

I wonder if it is something that could go into meow directly, otherwise it will probably go into a meow-plus package.

😺

Version on npm doesn't provide flag defaults

On 3.7.0 the flags output is an empty object. On commit 554119b it provides the default:

Created this file:

const m = require('meow');
const cli = m(`foo`, { flags: { foo: { default: 'bar' } } });
console.log(cli);
$ npm show meow | grep version:
  version: '3.7.0',
$ npm install [email protected]

$ node index.js
{ input: [],
  flags: {},
  pkg:
   { name: 'test-meow',
     version: '1.0.0',
     description: '',
     main: 'index.js',
     scripts: { test: 'echo "Error: no test specified" && exit 1' },
     author: '',
     license: 'ISC',
     dependencies: { meow: '^3.7.0' },
     readme: 'ERROR: No README data found!',
     _id: '[email protected]' },
  help: '\n  foo',
  showHelp: [Function: showHelp] }

$ npm install https://github.com/sindresorhus/meow#554119b
$ node index.js
{ input: [],
  flags: { foo: 'bar' },
  pkg:
   { name: 'test-meow',
     version: '1.0.0',
     description: '',
     main: 'index.js',
     scripts: { test: 'echo "Error: no test specified" && exit 1' },
     author: '',
     license: 'ISC',
     dependencies: { meow: 'git+https://github.com/sindresorhus/meow.git#554119b' },
     readme: 'ERROR: No README data found!',
     _id: '[email protected]' },
  help: '\n  foo\n',
  showHelp: [Function: showHelp] }

Should not camelcase key '--'

when passing minimistOpts {'--': true} and run a given example:

cli whatever -- ava test.js

meow returns:

{
  ...
  flags: {
    '': ['ava', 'test.js']
  }
  // while it should be '--': ['ava', 'test.js']
}

stdin handling

Note, not reading, but handling when to read from stdin.

Currently it's this logic: https://github.com/sindresorhus/find-versions-cli/blob/56dbd77051147819abdf845504af3b3cc1dd2935/cli.js#L30-L41

The logic is, we only try to read from stdin when there's no input and process.isTTY === false. Otherwise it won't work when used with child_process.execFile so the logic is hard to get right for many
if you only check isTTY, which i did with most of my CLIs previously, it wouldn't work with execFile, as isTTY is false there and it tries to read from stdin.

From hangouts chat:

Sindre: might consider handling reading stdin too, though not quite sure about that
maybe half of my CLIs read from stdin

Sam Verschueren: I would say "why not". But then again, it's an extra meow dependency

Sindre: extra deps doesn't matter that much since it's only used top-level by a CLI but the we can begin with the above. I want it separate anyways as some CLIs does streaming stdin reading which would require manual work anyways. so I'm thinking first a cli.stdinOrInput and maybe at a later point we can do cli.stdin() which makes use of the former.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.