1 | #!/usr/bin/env node
|
2 |
|
3 | 'use strict';
|
4 |
|
5 | require('core-js/modules/es.array.iterator');
|
6 | var _reduce = require('ramda/src/reduce');
|
7 | var program = require('commander');
|
8 | require('core-js/modules/es.string.replace');
|
9 | var _map = require('ramda/src/map');
|
10 | var _prop = require('ramda/src/prop');
|
11 | var _descend = require('ramda/src/descend');
|
12 | var _sort = require('ramda/src/sort');
|
13 | var _lensProp = require('ramda/src/lensProp');
|
14 | var _set = require('ramda/src/set');
|
15 | var _compose = require('ramda/src/compose');
|
16 | var _multiply = require('ramda/src/multiply');
|
17 | var _always = require('ramda/src/always');
|
18 | var _ifElse = require('ramda/src/ifElse');
|
19 | var _divide = require('ramda/src/divide');
|
20 | var _flip = require('ramda/src/flip');
|
21 | var _any = require('ramda/src/any');
|
22 | var _filter = require('ramda/src/filter');
|
23 | var _find = require('ramda/src/find');
|
24 | var _endsWith = require('ramda/src/endsWith');
|
25 | var _startsWith = require('ramda/src/startsWith');
|
26 | var _anyPass = require('ramda/src/anyPass');
|
27 | var _replace = require('ramda/src/replace');
|
28 | var _is = require('ramda/src/is');
|
29 | var snippets = require('../lib/snippets.json');
|
30 | var _pick = require('ramda/src/pick');
|
31 | var _toPairs = require('ramda/src/toPairs');
|
32 | var _join = require('ramda/src/join');
|
33 | var Renderer = require('marked-terminal');
|
34 | var chalk = require('chalk');
|
35 | var marked = require('marked');
|
36 | var cliHighlight = require('cli-highlight');
|
37 | var clipboardy = require('clipboardy');
|
38 |
|
39 | function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
40 |
|
41 | var _reduce__default = _interopDefaultLegacy(_reduce);
|
42 | var program__default = _interopDefaultLegacy(program);
|
43 | var _map__default = _interopDefaultLegacy(_map);
|
44 | var _prop__default = _interopDefaultLegacy(_prop);
|
45 | var _descend__default = _interopDefaultLegacy(_descend);
|
46 | var _sort__default = _interopDefaultLegacy(_sort);
|
47 | var _lensProp__default = _interopDefaultLegacy(_lensProp);
|
48 | var _set__default = _interopDefaultLegacy(_set);
|
49 | var _compose__default = _interopDefaultLegacy(_compose);
|
50 | var _multiply__default = _interopDefaultLegacy(_multiply);
|
51 | var _always__default = _interopDefaultLegacy(_always);
|
52 | var _ifElse__default = _interopDefaultLegacy(_ifElse);
|
53 | var _divide__default = _interopDefaultLegacy(_divide);
|
54 | var _flip__default = _interopDefaultLegacy(_flip);
|
55 | var _any__default = _interopDefaultLegacy(_any);
|
56 | var _filter__default = _interopDefaultLegacy(_filter);
|
57 | var _find__default = _interopDefaultLegacy(_find);
|
58 | var _endsWith__default = _interopDefaultLegacy(_endsWith);
|
59 | var _startsWith__default = _interopDefaultLegacy(_startsWith);
|
60 | var _anyPass__default = _interopDefaultLegacy(_anyPass);
|
61 | var _replace__default = _interopDefaultLegacy(_replace);
|
62 | var _is__default = _interopDefaultLegacy(_is);
|
63 | var snippets__default = _interopDefaultLegacy(snippets);
|
64 | var _pick__default = _interopDefaultLegacy(_pick);
|
65 | var _toPairs__default = _interopDefaultLegacy(_toPairs);
|
66 | var _join__default = _interopDefaultLegacy(_join);
|
67 | var Renderer__default = _interopDefaultLegacy(Renderer);
|
68 | var chalk__default = _interopDefaultLegacy(chalk);
|
69 | var marked__default = _interopDefaultLegacy(marked);
|
70 |
|
71 | const enforceSingleNewLine = x => _is__default['default'](String, x) ? _compose__default['default'](_replace__default['default'](/[\r\n]+/g, '\n'), _replace__default['default'](/[\r\n]*$/, ''))(x) : x;
|
72 | const randomNumberInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
|
73 | const startsOrEndsWith = (val, query) => _anyPass__default['default']([_startsWith__default['default'], _endsWith__default['default']])(query, val);
|
74 |
|
75 | const fuzzyMatch = query => x => new RegExp(query).test(x.id);
|
76 |
|
77 | const getSnippet = (snippets, id) => _find__default['default'](x => x.id === id, snippets);
|
78 | const getSnippetsByTag = (snippets, id) => _filter__default['default'](x => _any__default['default'](y => y === id, x.tags), snippets);
|
79 | const randomSnippet = snippets => snippets[randomNumberInRange(0, snippets.length - 1)];
|
80 |
|
81 | const 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 |
|
93 | const setSearchRelevance = query => x => _set__default['default'](_lensProp__default['default']('relevance'), computeRelevance(x.id, query), x);
|
94 |
|
95 | const 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 |
|
97 | marked__default['default'].setOptions({
|
98 | renderer: new Renderer__default['default']()
|
99 | });
|
100 | const 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 | };
|
117 | const 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 |
|
144 | var version = "1.5.2";
|
145 |
|
146 | const isTest = process.env.NODE_ENV === 'test';
|
147 | const 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 |
|
154 | const addCommand = settings => _reduce__default['default']((acc, [key, ...args]) => acc[key](...args), program__default['default'], settings);
|
155 |
|
156 | const addAction = action => ['action', (...args) => ((input, opts = {}) => {
|
157 | if (!input) return program__default['default'].outputHelp();
|
158 | return isTest ?
|
159 |
|
160 |
|
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 |
|
164 | const 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']];
|
165 | program__default['default'].version(version);
|
166 | addCommand([['command', 'r'], ['alias', 'random'], ['description', ['view random snippet']], ...commonOptions, addAction('random')]);
|
167 | addCommand([['command', 's [query]'], ['alias', 'search'], ['description', ['fuzzy search snippets by id']], ...commonOptions, addAction('search')]);
|
168 | addCommand([['command', 't [id]'], ['alias', 'tag'], ['description', ['view snippets by tag']], ...commonOptions, addAction('tag')]);
|
169 | addCommand([['command', 'v [id]'], ['alias', 'view'], ['description', ['view snippet with id']], ...commonOptions, addAction('view')]);
|
170 | addCommand([['command', '* [id]'], ['description', ['view snippet with id']], addAction('view')]);
|
171 | program__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')));
|
172 | program__default['default'].parse(process.argv);
|
173 |
|
174 | if (process.argv.length <= 2) {
|
175 | program__default['default'].outputHelp();
|
176 | }
|