UNPKG

9.33 kBJavaScriptView Raw
1#!/usr/bin/env node
2
3'use strict';
4
5require('core-js/modules/es.array.iterator');
6var _reduce = require('ramda/src/reduce');
7var program = require('commander');
8require('core-js/modules/es.string.replace');
9var _map = require('ramda/src/map');
10var _prop = require('ramda/src/prop');
11var _descend = require('ramda/src/descend');
12var _sort = require('ramda/src/sort');
13var _lensProp = require('ramda/src/lensProp');
14var _set = require('ramda/src/set');
15var _compose = require('ramda/src/compose');
16var _multiply = require('ramda/src/multiply');
17var _always = require('ramda/src/always');
18var _ifElse = require('ramda/src/ifElse');
19var _divide = require('ramda/src/divide');
20var _flip = require('ramda/src/flip');
21var _any = require('ramda/src/any');
22var _filter = require('ramda/src/filter');
23var _find = require('ramda/src/find');
24var _endsWith = require('ramda/src/endsWith');
25var _startsWith = require('ramda/src/startsWith');
26var _anyPass = require('ramda/src/anyPass');
27var _replace = require('ramda/src/replace');
28var _is = require('ramda/src/is');
29var snippets = require('../lib/snippets.json');
30var _pick = require('ramda/src/pick');
31var _toPairs = require('ramda/src/toPairs');
32var _join = require('ramda/src/join');
33var Renderer = require('marked-terminal');
34var chalk = require('chalk');
35var marked = require('marked');
36var cliHighlight = require('cli-highlight');
37var clipboardy = require('clipboardy');
38
39function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
40
41var _reduce__default = /*#__PURE__*/_interopDefaultLegacy(_reduce);
42var program__default = /*#__PURE__*/_interopDefaultLegacy(program);
43var _map__default = /*#__PURE__*/_interopDefaultLegacy(_map);
44var _prop__default = /*#__PURE__*/_interopDefaultLegacy(_prop);
45var _descend__default = /*#__PURE__*/_interopDefaultLegacy(_descend);
46var _sort__default = /*#__PURE__*/_interopDefaultLegacy(_sort);
47var _lensProp__default = /*#__PURE__*/_interopDefaultLegacy(_lensProp);
48var _set__default = /*#__PURE__*/_interopDefaultLegacy(_set);
49var _compose__default = /*#__PURE__*/_interopDefaultLegacy(_compose);
50var _multiply__default = /*#__PURE__*/_interopDefaultLegacy(_multiply);
51var _always__default = /*#__PURE__*/_interopDefaultLegacy(_always);
52var _ifElse__default = /*#__PURE__*/_interopDefaultLegacy(_ifElse);
53var _divide__default = /*#__PURE__*/_interopDefaultLegacy(_divide);
54var _flip__default = /*#__PURE__*/_interopDefaultLegacy(_flip);
55var _any__default = /*#__PURE__*/_interopDefaultLegacy(_any);
56var _filter__default = /*#__PURE__*/_interopDefaultLegacy(_filter);
57var _find__default = /*#__PURE__*/_interopDefaultLegacy(_find);
58var _endsWith__default = /*#__PURE__*/_interopDefaultLegacy(_endsWith);
59var _startsWith__default = /*#__PURE__*/_interopDefaultLegacy(_startsWith);
60var _anyPass__default = /*#__PURE__*/_interopDefaultLegacy(_anyPass);
61var _replace__default = /*#__PURE__*/_interopDefaultLegacy(_replace);
62var _is__default = /*#__PURE__*/_interopDefaultLegacy(_is);
63var snippets__default = /*#__PURE__*/_interopDefaultLegacy(snippets);
64var _pick__default = /*#__PURE__*/_interopDefaultLegacy(_pick);
65var _toPairs__default = /*#__PURE__*/_interopDefaultLegacy(_toPairs);
66var _join__default = /*#__PURE__*/_interopDefaultLegacy(_join);
67var Renderer__default = /*#__PURE__*/_interopDefaultLegacy(Renderer);
68var chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk);
69var marked__default = /*#__PURE__*/_interopDefaultLegacy(marked);
70
71const enforceSingleNewLine = x => _is__default['default'](String, x) ? _compose__default['default'](_replace__default['default'](/[\r\n]+/g, '\n'), _replace__default['default'](/[\r\n]*$/, ''))(x) : x;
72const randomNumberInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
73const startsOrEndsWith = (val, query) => _anyPass__default['default']([_startsWith__default['default'], _endsWith__default['default']])(query, val);
74
75const fuzzyMatch = query => x => new RegExp(query).test(x.id);
76
77const getSnippet = (snippets, id) => _find__default['default'](x => x.id === id, snippets);
78const getSnippetsByTag = (snippets, id) => _filter__default['default'](x => _any__default['default'](y => y === id, x.tags), snippets);
79const randomSnippet = snippets => snippets[randomNumberInRange(0, snippets.length - 1)];
80
81const computeRelevance = (id, query) => {
82 const base = query.length * 10;
83 const diffInChars = id.replace(query, '').length + 1;
84
85 const divideByDiffInChars = _flip__default['default'](_divide__default['default'])(diffInChars);
86
87 const multi = _ifElse__default['default'](_always__default['default'](startsOrEndsWith(id, query)), _multiply__default['default'](0.75), _multiply__default['default'](0.5));
88
89 if (id === query) return base;
90 return _compose__default['default'](divideByDiffInChars, multi)(base);
91};
92
93const setSearchRelevance = query => x => _set__default['default'](_lensProp__default['default']('relevance'), computeRelevance(x.id, query), x);
94
95const searchSnippets = (snippets, query) => _compose__default['default'](_sort__default['default'](_descend__default['default'](_prop__default['default']('relevance'))), _map__default['default'](setSearchRelevance(query)), _filter__default['default'](fuzzyMatch(query)))(snippets);
96
97marked__default['default'].setOptions({
98 renderer: new Renderer__default['default']()
99});
100const colorizedPrint = x => {
101 const printMap = {
102 code: y => cliHighlight.highlight(y, {
103 language: 'javascript'
104 }),
105 description: y => enforceSingleNewLine(marked__default['default'](y)),
106 example: y => cliHighlight.highlight(y, {
107 language: 'javascript'
108 }),
109 id: y => chalk__default['default'].magenta.bold(y),
110 tags: _compose__default['default'](chalk__default['default'].gray.italic, _join__default['default'](', '))
111 };
112
113 const print = y => _compose__default['default'](_replace__default['default'](/\n$/, ''), _join__default['default']('\n'), _map__default['default'](([k, v]) => printMap[k](v) + (k === 'id' ? '' : '\n')), _toPairs__default['default'])(y);
114
115 return _compose__default['default'](_join__default['default']('\n\n'), _map__default['default'](print))(x);
116};
117const printSnippet = ({
118 cp,
119 layout,
120 json
121}, x) => {
122 const arr = _is__default['default'](Array, x) ? x : [x];
123 const layoutMap = {
124 c: 'code',
125 d: 'description',
126 e: 'example',
127 i: 'id',
128 t: 'tags'
129 };
130
131 const keysByLayout = _map__default['default'](k => layoutMap[k])(Array.from(layout || 'itced'));
132
133 if (x == null) return '';
134
135 if (cp) {
136 clipboardy.writeSync(_compose__default['default'](_join__default['default']('\n'), _map__default['default'](_prop__default['default']('code')))(arr));
137 }
138
139 const pickedSnippet = _map__default['default'](_pick__default['default'](keysByLayout))(arr);
140
141 return _compose__default['default'](console.log, json ? JSON.stringify : colorizedPrint)(pickedSnippet);
142};
143
144var version = "1.5.2";
145
146const isTest = process.env.NODE_ENV === 'test';
147const actions = {
148 random: opts => printSnippet(opts, randomSnippet(snippets__default['default'])),
149 search: (opts, query) => printSnippet(opts, searchSnippets(snippets__default['default'], query)),
150 tag: (opts, id) => printSnippet(opts, getSnippetsByTag(snippets__default['default'], id)),
151 view: (opts, id) => printSnippet(opts, getSnippet(snippets__default['default'], id))
152};
153
154const addCommand = settings => _reduce__default['default']((acc, [key, ...args]) => acc[key](...args), program__default['default'], settings);
155
156const addAction = action => ['action', (...args) => ((input, opts = {}) => {
157 if (!input) return program__default['default'].outputHelp();
158 return isTest ? // NOTE: Commander.js sadly does not include a way to hook onto given
159 // actions for integration testing. We solve this by outputting state
160 // when NODE_ENV is test.
161 console.log(JSON.stringify([action, input, !!opts.cp, !!opts.json, opts.layout])) : actions[action](opts, input);
162})(...(action === 'random' ? [true, args[0]] : args))];
163
164const commonOptions = [['option', '-c, --cp', 'copy code to clipboard', false], ['option', '-j, --json', 'output in json format', false], ['option', '-l, --layout <layout>', 'print in specified layout', 'itced']];
165program__default['default'].version(version);
166addCommand([['command', 'r'], ['alias', 'random'], ['description', ['view random snippet']], ...commonOptions, addAction('random')]);
167addCommand([['command', 's [query]'], ['alias', 'search'], ['description', ['fuzzy search snippets by id']], ...commonOptions, addAction('search')]);
168addCommand([['command', 't [id]'], ['alias', 'tag'], ['description', ['view snippets by tag']], ...commonOptions, addAction('tag')]);
169addCommand([['command', 'v [id]'], ['alias', 'view'], ['description', ['view snippet with id']], ...commonOptions, addAction('view')]);
170addCommand([['command', '* [id]'], ['description', ['view snippet with id']], addAction('view')]);
171program__default['default'].on('--help', () => console.log(['', 'Examples:', ' 30s head', ' 30s v head', ' 30s view head', '', ' 30s r', ' 30s random', '', ' 30s s -j flatten', ' 30s search --json flatten', '', ' 30s t -l ic array', ' 30s tag --layout ic array'].join('\n')));
172program__default['default'].parse(process.argv);
173
174if (process.argv.length <= 2) {
175 program__default['default'].outputHelp();
176}