npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

humanist

v1.0.2

Published

A specification and parser for command line grammar which is easy to type on Android and iOS keyboards. When using humanist to parse command line options, it is recommended to stay close to natural language. That would make humanist-based syntax a good fi

Downloads

4

Readme

humanist

A specification and parser for command line grammar which is easy to type on Android and iOS keyboards. When using humanist to parse command line options, it is recommended to stay close to natural language. That would make humanist-based syntax a good fit for communicating with bots from PCs and phones.

Humanist commands make extensive use of the period to separate options, since the period is easy to type on all keyboards. On Android and iOS keyboards you can get a period by typing space twice.

Alright, what does it look like?

Assuming there's app called 'reminder', the command line might look like:

reminder due tomorrow todo Get two bottles of milk

Or with a messaging app called 'imessage':

imessage to alice bob carol. text Hello, world.

Options are not case-sensitive. These two are the same.

imessage to alice bob carol. text Hello, world.
imessage To alice bob carol. Text Hello, world.

Installation

npm i humanist

Basic grammar and options

Let's consider the first example:

reminder due tomorrow todo Get two bottles of milk

While defining the reminder app's options, specify that the option 'due' takes a single word as the argument, and that the option 'todo' takes multiple words (an arbitrary number of arguments).

const options = [["due", "single"], ["todo", "multi"]];
const parser = humanist(options);

/* Prints:
{
  due: "tomorrow",
  todo: ["Get", "two", "bottles", "of, "milk"]
}
*/
console.log(parser("due tomorrow todo Get two bottles of milk"));

/*
  Passing an array of words yields the same result.
  With nodejs, you can pass the command line param array.
*/
console.log(
  parser(["due", "tomorrow", "todo", "Get", "two", "bottles", "of", "milk"])
);

Multiple options of arbitrary length (Delimiters)

Humanist uses the period character '.' as a delimiter to separate options which take multiple args.

send to alice bob carol. text Hello, world
const options = [["to", "multi"], ["text", "multi"]];

/* Prints:
{
  to: ["alice", "bob", "carol"],
  text: ["Hello,", "world"]
}
*/
console.log(parser("to alice bob carol. text Hello, world"));

Argument-less options aka Flags

A flag is a boolean which indicates whether an option has been mentioned in the command input.

Here's an example, with a flag called 'privately'.

send privately to alice bob carol. text Hey, ssup?

Humanist parses flags as booleans.

const options = [
  ["to", "multi"],
  ["text", "multi"],
  ["privately", "flag"] // means it's a flag
];

/* Prints:
{
  to: ["alice", "bob", "carol"],
  text: ["Hey,", "ssup?"],
  privately: true
}
*/
console.log(parser("privately to alice bob carol. text Hey, ssup?"));

Join arguments

Sometimes we want to join the resultant array of arguments into a string. In the following example, the todo arguments are joined into "Get two bottles of milk" instead of ["Get", "two", "bottles", "of, "milk"].

const options = [["due", "single"], ["todo", "multi", { join: true }]];
const parser = humanist(options);

/* Prints:
{
  due: "tomorrow",
  todo: "Get two bottles of milk"
}
*/
console.log(parser("due tomorrow todo Get two bottles of milk"));

Repeating options

With the 'multiple' setting, options may be repeated in the command line to provide an array of values. In the following example the option 'todo' is repeated thrice, so its value will be an array of strings.

tasks due tomorrow todo Get Milk. todo Wash clothes. todo Buy shuttles.
const options = [["due", "single"], ["todo", "multi", { join: true }]];
const parser = humanist(options);

/* Prints:
{
  due: "tomorrow",
  todo: ["Get Milk", "Wash clothes", "Buy shuttles"]
}
*/
console.log(
  parser("due tomorrow todo Get Milk. todo Wash clothes. todo Buy shuttles.")
);

Literal strings

Sometimes it's necessary to accept full sentences or paragraphs as input, which may contain multiple periods in them. To specify a literal, add a period to the name of the option and end it with a 'k.' or 'K.'. The 'k.' is not necessary at the end of the sentence.

send to alice bob carol. text. Hey. When are you coming? I am home till 8. K. Send now

Notice the period after 'text' and the 'K.'. Everything in between is taken literally as a string.

const options = [["to", "multi"], ["text", "multi"], ["send", "single"]];

/* Prints:
{
  to: ["alice", "bob", "carol"],
  text: "Hey. When are you coming? I am home till 8.",
  send: "now"
}
*/
console.log(
  parser(
    "to alice bob carol. text. Hey. When are you coming? I am home till 8. K. Send now"
  )
);

Escaping the K.

There may be cases where you need to accept 'K.' as an valid option, but humanist will mistake it for a delimiter. To escape a 'K.' from being treated as a delimiter, simply say 'KK.'. And if you had to say 'KK.', you'll need to type 'KKK.' and so forth.

/* Prints:
{
  alphabets: "E. F. G. H. I. J. K. L.",
  position: "left"
}
*/
console.log(parser("alphabets. E. F. G. H. I. J. KK. L. K. position left"));

Unmatched args at the end of the sentence

Humanist captures the list of unmatched arguments as the underscore property.

const options = [["to", "multi"]];
const parser = humanist(options);

/* Prints:
  {
    to: ["alice", "bob", "carol"],
    _: ["Hello,", "world."]
  }
*/
console.log(parser("to alice bob carol. Hello, world."));

Custom Handling (Advanced)

Humanist allows custom parsing logic to be added via a callback. In the following example, the custom parser handled account names starting with '@'. The options parsed so far are available in the parameter named 'current'.

interface IResult {
  _: string[];
  [key: string]: boolean | string | string[];
}

function parse(arg: string, index: number, args: string[], current: IResult) {
  // If it starts with an '@' it's an account name
  if (/^@/.test(arg)) {
    const nextIndex = index + 1;
    const newResult = { ...current, account: arg.substring(1) };
    return [nextIndex, newResult];
  }
}

const options = [["email", "single"], ["file", "multi"]];
const parser = humanist(options);

/* Prints:
  {
    account: "@scuttlespace",
    email: "[email protected]",
    file: ["a.txt", "b.txt"]
  }
*/
console.log(parser("@scuttlespace email [email protected] file a.txt b.txt"));