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

lambduh

v3.1.0

Published

transform stdin with JS lambda instead of using sed, jq, etc. Duh!

Downloads

27

Readme

lambduh

Build Status Coverage Status semantic-release Commitizen friendly

Turing-complete JS commandline JSON/text transformer and file renamer

Can't remember how sed works. Can't remember how cut works. I just don't have to use them often enough to commit them to memory. When I first read about jq, I thought Hmm, this is cool, but I love ES6. I know it well. Can't I just do all of this stuff in JS?

These days I'm too lazy to read manpages and learn tools like jq, sed, awk, etc. for things that I could I could write a JS expression for in ten seconds. All that was lacking was a basic command to handle the I/O. Just look how frigging easy stuff is:

npm install --global lambduh
Print lines of file in reverse order:
> duh 'lines => lines.reverse()' < somefile
Swap first and last name:
> duh 'line => line.split(/\s+/g).reverse().join(", ")' < names
Edwards, Andy
Doe, John
Put all lodash functions on global scope for duh commands for the next few examples
> cd ~ && npm install lodash
> echo 'Object.assign(global, require("lodash"))' >> ~/.lambduh.js
Shuffle lines of a file
> duh 'lines => shuffle(lines)' < somefile
See who's been committing to react recently:
> curl 'https://api.github.com/repos/facebook/react/commits?per_page=100' \
  | duh 'json => mapValues(groupBy(json, "commit.committer.name"), size)'
{
  "GitHub": 60,
  "Dan Abramov": 17,
  "Flarnie Marchan": 2,
  "Brian Vaughn": 3,
  "Nathan Hunzaker": 5,
  "Brandon Dail": 8,
  "Ben Alpert": 1,
  "Andrew Clark": 1,
  "Dominic Gannaway": 3
}
Destructure and restructure JSON subdocuments
> curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=2' \
  | duh 'json => json.map(({ commit: { message, committer: { name } } }) => ({ message, name }))'
[
  {
    "message": "Deal with strptime() on OS X and *BSD (fix #1415)\n\nstrptime() on OS X and *BSDs (reputedly) does not set tm_wday and\ntm_yday unless corresponding %U and %j format specifiers were used.\nThat can be... surprising when one parsed year, month, and day anyways.\nGlibc's strptime() conveniently sets tm_wday and tm_yday in those cases,\nbut OS X's does not, ignoring them completely.\n\nThis commit makes jq compute those where possible, though the day of\nweek computation may be wrong for dates before 1900-03-01 or after\n2099-12-31.",
    "name": "Nicolas Williams"
  },
  {
    "message": "Attempt to fix #1415\n\nOS X (and *BSD) strptime() does not set tm_wday nor tm_yday unless\ncorresponding format options are used.  That means we must call timegm()\nto set them.",
    "name": "Nicolas Williams"
  }
]
Rename .jsx files in the current directory to .js:
duh mv *.jsx 'file => file.replace(/\.jsx$/g, ".js")'
Rename all .jsx files in the current subtree to .js:
find . -name *.jsx | duh mv 'file => file.replace(/\.jsx$/g, ".js")'
Flatten music stored as artist/album/filename into a single directory:
duh mv */*/* 'file => { var [artist, album, file] = file.split(/\//g); return `${artist} - ${album} - ${file}` }'

Node version note

The syntax that duh accepts for your function depends on the version of Node you're running. If you're running a really old version, you may not be able to use lambdas, and will have to resort to function () { return ... } instead.

Command

You can use lambduh or just duh.

Modes

You may have noticed above that you can apply a transformation to each line of a plain text file. This is pretty much the only magic built into the duh command:

  • If the first argument is mv (rather than a function), it runs in move mode.
  • If the first argument of your function is lines (ignoring case), it runs in lines mode.
  • Otherwise if the first argument of your function starts with l or L, it runs in line mode.
  • If the first argument of your function starts with t or T, it runs in text mode.
  • Otherwise, it runs in json mode.

:star: :+1: Nice!! :punch: :sparkles:

JSON Mode

JSON.parses stdin, calls your function on it, writes JSON.stringify to stdout. Duh!

Line Mode

Reads lines from stdin one-by-one, calls your function on each with (text, lineNumber), and writes what it returns to stdout, except:

  • If your function returns false, it quits reading lines.
  • If your function returns null or undefined, it skips to the next line without printing anything.

Lines Mode

Calls your function with an array of lines from stdin. If your function returns an array of lines, it writes them in order to stdout. Otherwise, it calls String on it and writes that string to stdout.

Text Mode

Calls your function with the entire text from stdin in a single string, and writes what your function returns to stdout.

Move Mode

Move mode renames each file (or directory) in the arguments by applying your provided function (which must be the last argument) to each filename. If you don't provide any files in the arguments, or one of your arguments is a single dash (-), it will also read from stdin, treating each line as a filename.

By default it will print the old and new filenames and then ask for confirmation before actually moving them.

Options

  • -y: move the files without asking you to confirm the new names.
  • --dry-run: just print out the old and new file names, then exit.

Customization

lambduh requires any .lambduh.js files in the working directory or its ancestors (from root to deepest), as well as .lambduh.js in your home directory. You can use these files to put functions on global scope so that you can use them in your function argument to lambduh. For example, here are some of the things I put in my ~/.lambduh.js:

Object.assign(global, require('lodash')) // put all lodash functions on context
global.replace = require('preserve-case') // case-preserving string.replace, often handy

With this I can do powerful stuff like:

> echo '{ "a": "foo bar", "b": "FOO BAR", "c": "it's all about the fooBar", "d": "foo-bar" }' \
  | duh 'json => mapValues(json, value => replace(value, "foo bar", "baz qux"))'
{
  "a": "baz qux",
  "b": "BAZ QUX",
  "c": "it's all about the bazQux",
  "d": "baz-qux"
}