From 36c4fb1f4568fb8af2086c435a264dcffb2a69ac Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Thu, 11 Jun 2020 22:02:58 +0200 Subject: [PATCH 01/22] chore: give rest a sensible variable name --- src/repl/completer.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/repl/completer.js b/src/repl/completer.js index 942e0ed..4ef2d1f 100644 --- a/src/repl/completer.js +++ b/src/repl/completer.js @@ -35,11 +35,11 @@ function getMatches (opts, subcommands, rest) { if (rest.length === 0) { return args } else { - const foo = rest[0] + const partialArg = rest[0] - if (args.includes(foo)) return only + if (args.includes(partialArg)) return only - const started = args.filter(arg => arg.startsWith(foo)) + const started = args.filter(arg => arg.startsWith(partialArg)) if (started.length > 0) return started else return [] } From 7dd1cf2d6a5717895175b1dec5ff26f81130d26a Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Thu, 11 Jun 2020 22:21:27 +0200 Subject: [PATCH 02/22] refactor: move completer into its own directory --- src/repl/completer/flatMap.js | 8 +++++ src/repl/completer/getMatches.d.ts | 3 ++ .../{completer.js => completer/getMatches.js} | 34 ++----------------- src/repl/completer/getMatches.test.js | 17 ++++++++++ src/repl/completer/index.d.ts | 5 +++ src/repl/completer/index.js | 29 ++++++++++++++++ src/repl/completer/index.test.js | 0 7 files changed, 65 insertions(+), 31 deletions(-) create mode 100644 src/repl/completer/flatMap.js create mode 100644 src/repl/completer/getMatches.d.ts rename src/repl/{completer.js => completer/getMatches.js} (57%) create mode 100644 src/repl/completer/getMatches.test.js create mode 100644 src/repl/completer/index.d.ts create mode 100644 src/repl/completer/index.js create mode 100644 src/repl/completer/index.test.js diff --git a/src/repl/completer/flatMap.js b/src/repl/completer/flatMap.js new file mode 100644 index 0000000..10b8e21 --- /dev/null +++ b/src/repl/completer/flatMap.js @@ -0,0 +1,8 @@ +const flatMap = (a, f) => a.reduce( + (acc, a) => [...acc, ...f(a)], + [] +) + +module.exports = { + flatMap +} \ No newline at end of file diff --git a/src/repl/completer/getMatches.d.ts b/src/repl/completer/getMatches.d.ts new file mode 100644 index 0000000..5f5e7d1 --- /dev/null +++ b/src/repl/completer/getMatches.d.ts @@ -0,0 +1,3 @@ +import {Opt} from '../../index' + +export const getMatches: (opts: Opt[], subcommands: any, rest: string[]) => string[] \ No newline at end of file diff --git a/src/repl/completer.js b/src/repl/completer/getMatches.js similarity index 57% rename from src/repl/completer.js rename to src/repl/completer/getMatches.js index 4ef2d1f..d8139a6 100644 --- a/src/repl/completer.js +++ b/src/repl/completer/getMatches.js @@ -1,29 +1,4 @@ -const completer = (parser, commands) => { - const parse = parser(commands) - - return line => { - if (line === '') { - const args = flatMap(commands.opts, cmd => cmd.args) - return [args, ''] - } - - const {args} = parse(line) - - const {_, ...subcommands} = args - - let matches = getMatches(commands.opts, subcommands, _) - - if (line[line.length - 1] !== ' ' && matches.length === 1) { - matches = matches.map(m => ' ' + m) - } - - return [matches, ''] - } -} - -module.exports = { - completer -} +import {flatMap} from './flatMap' function getMatches (opts, subcommands, rest) { return flatMap(Object.entries(subcommands), ([key, value]) => { @@ -49,9 +24,6 @@ function getMatches (opts, subcommands, rest) { }) } -function flatMap (a, f) { - return a.reduce( - (acc, a) => [...acc, ...f(a)], - [] - ) +module.exports = { + getMatches } \ No newline at end of file diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js new file mode 100644 index 0000000..95a78a0 --- /dev/null +++ b/src/repl/completer/getMatches.test.js @@ -0,0 +1,17 @@ +const {getMatches} = require('./getMatches') + +test('getMatches ', () => { + const opts = [ + {key: 'a', args: ['-a'], types: ['1']} + ] + + const subcommands = + + const rest = null + + const res = getMatches(opts, subcommands, rest) + + const exp = ['foo', 'bar', 'baz'] + + expect(res).toStrictEqual(exp) +}) \ No newline at end of file diff --git a/src/repl/completer/index.d.ts b/src/repl/completer/index.d.ts new file mode 100644 index 0000000..10e74c8 --- /dev/null +++ b/src/repl/completer/index.d.ts @@ -0,0 +1,5 @@ +import {Err, Opt} from '../../index' + +export const completer: (parser: (opt?: Opt) => (any?: A) => {errs: Err[], any: B}, commands: Opt) => + (line: string) => + string[] \ No newline at end of file diff --git a/src/repl/completer/index.js b/src/repl/completer/index.js new file mode 100644 index 0000000..1b4933d --- /dev/null +++ b/src/repl/completer/index.js @@ -0,0 +1,29 @@ +import {getMatches} from './getMatches' +import {flatMap} from './flatMap' + +const completer = (parser, commands) => { + const parse = parser(commands) + + return line => { + if (line === '') { + const args = flatMap(commands.opts, cmd => cmd.args) + return [args, ''] + } + + const {args} = parse(line) + + const {_, ...subcommands} = args + + let matches = getMatches(commands.opts, subcommands, _) + + if (line[line.length - 1] !== ' ' && matches.length === 1) { + matches = matches.map(m => ' ' + m) + } + + return [matches, ''] + } +} + +module.exports = { + completer +} \ No newline at end of file diff --git a/src/repl/completer/index.test.js b/src/repl/completer/index.test.js new file mode 100644 index 0000000..e69de29 From 05eb304bd5509af2a514561352bd8fb81a83da35 Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:34:20 +0200 Subject: [PATCH 03/22] refactor: rename repl to replEval --- src/repl/index.js | 4 ++-- src/repl/{eval.js => replEval.js} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/repl/{eval.js => replEval.js} (91%) diff --git a/src/repl/index.js b/src/repl/index.js index a64afbc..1126d1c 100644 --- a/src/repl/index.js +++ b/src/repl/index.js @@ -1,5 +1,5 @@ const nodeRepl = require('repl') -const {eval} = require('./eval') +const {replEval} = require('./replEval') const {completer} = require('./completer') const repl = (parser, commands) => { @@ -8,8 +8,8 @@ const repl = (parser, commands) => { nodeRepl.start({ prompt: `${commands.key}~$ `, ignoreUndefined: true, - eval: eval(parser, commands), completer: completer(parser, commands) + eval: replEval(parser, commands), }) } diff --git a/src/repl/eval.js b/src/repl/replEval.js similarity index 91% rename from src/repl/eval.js rename to src/repl/replEval.js index d7147d2..919477b 100644 --- a/src/repl/eval.js +++ b/src/repl/replEval.js @@ -1,4 +1,4 @@ -const eval = (parser, commands) => { +const replEval = (parser, commands) => { const parse = parser(commands) return (cmd, context, filename, callback) => { @@ -22,5 +22,5 @@ const eval = (parser, commands) => { } module.exports = { - eval + replEval } \ No newline at end of file From 795b8c158543cb1d589ccee66d630bb6a3a943fc Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:37:35 +0200 Subject: [PATCH 04/22] refactor: restart implementing completer using shargs lexer --- src/repl/completer/getMatches.d.ts | 3 -- src/repl/completer/getMatches.js | 29 ------------------ src/repl/completer/getMatches.test.js | 17 ----------- src/repl/completer/index.d.ts | 2 +- src/repl/completer/index.js | 42 +++++++++++++++------------ src/repl/completer/index.test.js | 0 src/repl/index.d.ts | 2 +- src/repl/index.js | 4 +-- 8 files changed, 28 insertions(+), 71 deletions(-) delete mode 100644 src/repl/completer/getMatches.d.ts delete mode 100644 src/repl/completer/getMatches.js delete mode 100644 src/repl/completer/getMatches.test.js delete mode 100644 src/repl/completer/index.test.js diff --git a/src/repl/completer/getMatches.d.ts b/src/repl/completer/getMatches.d.ts deleted file mode 100644 index 5f5e7d1..0000000 --- a/src/repl/completer/getMatches.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import {Opt} from '../../index' - -export const getMatches: (opts: Opt[], subcommands: any, rest: string[]) => string[] \ No newline at end of file diff --git a/src/repl/completer/getMatches.js b/src/repl/completer/getMatches.js deleted file mode 100644 index d8139a6..0000000 --- a/src/repl/completer/getMatches.js +++ /dev/null @@ -1,29 +0,0 @@ -import {flatMap} from './flatMap' - -function getMatches (opts, subcommands, rest) { - return flatMap(Object.entries(subcommands), ([key, value]) => { - const opts2 = opts.filter(_ => _.key === key) - const args = flatMap(opts2, cmd => flatMap(cmd.opts || [], _ => _.args || [`<${_.key}>`])) - const only = flatMap(opts2, cmd => flatMap(cmd.opts || [], _ => _.only || [])) - - if (Array.isArray(value._)) { - if (rest.length === 0) { - return args - } else { - const partialArg = rest[0] - - if (args.includes(partialArg)) return only - - const started = args.filter(arg => arg.startsWith(partialArg)) - if (started.length > 0) return started - else return [] - } - } else { - return getMatches(flatMap(opts2, opt => opt.opts), value, rest) - } - }) -} - -module.exports = { - getMatches -} \ No newline at end of file diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js deleted file mode 100644 index 95a78a0..0000000 --- a/src/repl/completer/getMatches.test.js +++ /dev/null @@ -1,17 +0,0 @@ -const {getMatches} = require('./getMatches') - -test('getMatches ', () => { - const opts = [ - {key: 'a', args: ['-a'], types: ['1']} - ] - - const subcommands = - - const rest = null - - const res = getMatches(opts, subcommands, rest) - - const exp = ['foo', 'bar', 'baz'] - - expect(res).toStrictEqual(exp) -}) \ No newline at end of file diff --git a/src/repl/completer/index.d.ts b/src/repl/completer/index.d.ts index 10e74c8..2e9eddc 100644 --- a/src/repl/completer/index.d.ts +++ b/src/repl/completer/index.d.ts @@ -1,5 +1,5 @@ import {Err, Opt} from '../../index' -export const completer: (parser: (opt?: Opt) => (any?: A) => {errs: Err[], any: B}, commands: Opt) => +export const completer: (lexer: (opt?: Opt) => (any?: A) => {errs: Err[], opts: B}, commands: Opt, opts?: {only?: boolean}) => (line: string) => string[] \ No newline at end of file diff --git a/src/repl/completer/index.js b/src/repl/completer/index.js index 1b4933d..f6f6dbe 100644 --- a/src/repl/completer/index.js +++ b/src/repl/completer/index.js @@ -1,29 +1,35 @@ -import {getMatches} from './getMatches' -import {flatMap} from './flatMap' +const {flatMap} = require('./flatMap') -const completer = (parser, commands) => { - const parse = parser(commands) +const completer = (lexer, cmd, {only = false} = {only: false}) => { + const lex = lexer(cmd) return line => { - if (line === '') { - const args = flatMap(commands.opts, cmd => cmd.args) - return [args, ''] - } - - const {args} = parse(line) - - const {_, ...subcommands} = args + const {opts} = lex(line) - let matches = getMatches(commands.opts, subcommands, _) - - if (line[line.length - 1] !== ' ' && matches.length === 1) { - matches = matches.map(m => ' ' + m) - } + const values = justValues(opts) - return [matches, ''] + return [[], line] } } module.exports = { completer +} + +function justValues (opts) { + return flatMap(opts, opt => { + if (Array.isArray(opt.values)) { + if (isSubcommand(opt)) { + return [{...opt, values: justValues(opt.values)}] + } else { + return [opt] + } + } else { + return [] + } + }) +} + +function isSubcommand ({opts} = {opts: undefined}) { + return Array.isArray(opts) } \ No newline at end of file diff --git a/src/repl/completer/index.test.js b/src/repl/completer/index.test.js deleted file mode 100644 index e69de29..0000000 diff --git a/src/repl/index.d.ts b/src/repl/index.d.ts index daa27c3..3c397d2 100644 --- a/src/repl/index.d.ts +++ b/src/repl/index.d.ts @@ -22,4 +22,4 @@ export interface Opt { [key: string]: any } -export const repl: (parser: (opt?: Opt) => (any?: A) => {errs: Err[], any: B}, commands: Opt) => void \ No newline at end of file +export const repl: (parser: (opt?: Opt) => (any?: A) => {errs: Err[], args: B}, commands: Opt) => void \ No newline at end of file diff --git a/src/repl/index.js b/src/repl/index.js index 1126d1c..56bf914 100644 --- a/src/repl/index.js +++ b/src/repl/index.js @@ -2,14 +2,14 @@ const nodeRepl = require('repl') const {replEval} = require('./replEval') const {completer} = require('./completer') -const repl = (parser, commands) => { +const repl = (lexer, parser, commands, {only = false} = {only: false}) => { console.log(commands.desc ? commands.desc + '\n' : '') nodeRepl.start({ prompt: `${commands.key}~$ `, ignoreUndefined: true, - completer: completer(parser, commands) eval: replEval(parser, commands), + completer: completer(lexer, commands, {only}) }) } From c2a5d23af8b49217ef9d98a54bac9d52826e589e Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:40:53 +0200 Subject: [PATCH 05/22] feat: add new getMatches function --- src/repl/completer/getMatches.js | 145 +++++++++++++++++++++++++++++++ src/repl/completer/index.js | 5 +- 2 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 src/repl/completer/getMatches.js diff --git a/src/repl/completer/getMatches.js b/src/repl/completer/getMatches.js new file mode 100644 index 0000000..180d0e7 --- /dev/null +++ b/src/repl/completer/getMatches.js @@ -0,0 +1,145 @@ +const {flatMap} = require('./flatMap') + +function getMatches (line, values, cmd, {only}) { + // 1. If line is empty, return all args and pos arg of command + if (line === '') { + const matches = summarize(cmd) + return match(matches, line) + } + + const cmdStack = getCmdStack(cmd, values) + const rest = getRest(values) + + // 2. If last value is command and not rest, show args of last command + if (rest === null) { + const cmd2 = cmdStack[cmdStack.length - 1] + const matches = summarize(cmd2) + return match(matches, line) + } + + // 3. If rest is -- display all command options + if (rest === '--') { + const matches = summarize(cmd) + return match(matches, line) + } + + let matches = [] + + // 4. Check if rest is args in any of the stack commands (from right to left) + // -> if args of subcommand, show all its opts + // -> if args is option, show its only field or empty if missing + for (let i = cmdStack.length - 1; i >= 0; i--) { + const cmd2 = cmdStack[i] + + const optsWithRestArg = flatMap( + cmd2.opts, + opt => (opt.args || []).includes(rest) ? [opt] : [] + ) + + if (optsWithRestArg.length > 0) { + matches = flatMap(optsWithRestArg, opt => { + if (isSubcommand(opt)) return summarize(opt) + else { + if (opt.descArg) return [opt.descArg] + if (only === true && opt.only) return opt.only + if (opt.types) return [`${(opt.types || []).map(type => '<' + type + '>').join(' ')}`] + return [] + } + }) + + break + } + } + + if (matches.length > 0) return match(matches, line) + + // 5. If not, check if rest is start of args in any of the stack commands (from right to left) + // -> if yes, matches are all right-most args that start with rest + for (let i = cmdStack.length - 1; i >= 0; i--) { + const cmd2 = cmdStack[i] + + const argsStartingWithRest = flatMap( + cmd2.opts, + opt => flatMap(opt.args || [], arg => arg.startsWith(rest) ? [arg] : []) + ) + + if (argsStartingWithRest.length > 0) { + matches = argsStartingWithRest + + break + } + } + + if (matches.length > 0) return complete(matches, line, rest) + + // 6. If not, + // -> Matches are first non-required pos arg of rightmost command without values, or any subcommand of any of the stack commands + for (let i = cmdStack.length - 1; i >= 0; i--) { + const cmd2 = cmdStack[i] + const args = summarize(cmd2) + matches = [...matches, ...args] + } + + return match(matches, line) + } + + module.exports = { + getMatches + } + + function match (matches, line) { + if (matches.length === 1) return [[line + ' ' + matches[0]], line] + return [matches, line] + } + + function complete (matches, line, rest) { + if (matches.length === 1) return [[line.slice(0, line.length - rest.length) + matches[0]], line] + return [matches, line] + } + + function getCmdStack (cmd, values) { + let stack = [cmd] + + for (let i = values.length - 1; i >= 0; i--) { + const opt = values[i] + + if (isSubcommand(opt)) { + const stack2 = getCmdStack(opt, opt.values) + stack = [...stack, ...stack2] + break + } + } + + return stack + } + + function isSubcommand ({opts} = {opts: undefined}) { + return Array.isArray(opts) + } + + function getRest (values) { + if (values.length === 0) return null + + const opt = values[values.length - 1] + + switch (true) { + case isSubcommand(opt): return getRest(opt.values || []) + case isRest(opt): return opt.values[0] + default: return null + } + } + + function isRest (opt) { + return Object.keys(opt).length === 1 && Array.isArray(opt.values) && opt.values.length === 1 + } + + function summarize (cmd) { + return flatMap(cmd.opts || [], opt => opt.args ? opt.args : argName(opt)) + } + + function argName ({key, types, only, descArg}) { + if (typeof descArg === 'string') return [descArg] + if (Array.isArray(only)) return only + if (Array.isArray(types) && types.length > 0) return [types.map(type => `<${type}>`).join(' ')] + return [`<${key}>`] + } \ No newline at end of file diff --git a/src/repl/completer/index.js b/src/repl/completer/index.js index f6f6dbe..e479dcd 100644 --- a/src/repl/completer/index.js +++ b/src/repl/completer/index.js @@ -1,4 +1,5 @@ -const {flatMap} = require('./flatMap') +const {flatMap} = require('./flatMap') +const {getMatches} = require('./getMatches') const completer = (lexer, cmd, {only = false} = {only: false}) => { const lex = lexer(cmd) @@ -8,7 +9,7 @@ const completer = (lexer, cmd, {only = false} = {only: false}) => { const values = justValues(opts) - return [[], line] + return getMatches(line, values, cmd, {only}) } } From b8d910832c7fa360d1e224a970171c9306354e29 Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:41:18 +0200 Subject: [PATCH 06/22] test: test if completer returns all cmd args and pos args for empty line --- src/repl/completer/index.test.js | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/repl/completer/index.test.js diff --git a/src/repl/completer/index.test.js b/src/repl/completer/index.test.js new file mode 100644 index 0000000..4bf6dfa --- /dev/null +++ b/src/repl/completer/index.test.js @@ -0,0 +1,39 @@ +const {completer} = require('.') + +const jet = {key: 'jet', args: ['--jet'], types: ['6']} + +const lot = {key: 'lot', args: ['--lot'], types: []} + +const Cat = {key: 'Cat', args: ['Cat'], opts: [ + jet, + {key: 'kit', args: ['--kit'], types: ['7', '8']}, + lot, + {key: 'mad', args: ['--mad'], types: ['9', '10'], only: ['A', 'B']}, + {key: 'nut', args: ['--nut'], types: ['9', '10'], only: ['C']} +]} + +const cmd = {key: 'Arc', opts: [ + {key: 'Bat', args: ['Bat'], opts: []}, + Cat, + {key: 'dot', args: ['-d', '--dot'], types: ['1']}, + {key: 'eat', args: ['-e', '--eat'], types: ['1', '2']}, + {key: 'fat', args: ['--fat'], types: []}, + {key: 'gut', types: ['3']}, + {key: 'hat', types: ['4', '5']}, + {key: 'ink', descArg: 'INK'} +]} + +test('completer returns all cmd args and pos args for empty line', () => { + const line = '' + + const lexer = () => () => ({ + errs: [], + opts: [] + }) + + const res = completer(lexer, cmd, {only: true})(line) + + const exp = [['Bat', 'Cat', '-d', '--dot', '-e', '--eat', '--fat', '<3>', '<4> <5>', 'INK'], line] + + expect(res).toStrictEqual(exp) +}) \ No newline at end of file From 4379ec32f8ee793c30730f9f5ff9e59d084edb93 Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:42:38 +0200 Subject: [PATCH 07/22] test: test if getMatches returns all cmd args and pos args on unknown input --- src/repl/completer/getMatches.test.js | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/repl/completer/getMatches.test.js diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js new file mode 100644 index 0000000..4d17f1d --- /dev/null +++ b/src/repl/completer/getMatches.test.js @@ -0,0 +1,36 @@ +const {getMatches} = require('./getMatches') + +const jet = {key: 'jet', args: ['--jet'], types: ['6']} + +const lot = {key: 'lot', args: ['--lot'], types: []} + +const Cat = {key: 'Cat', args: ['Cat'], opts: [ + jet, + {key: 'kit', args: ['--kit'], types: ['7', '8']}, + lot, + {key: 'mad', args: ['--mad'], types: ['9', '10'], only: ['A', 'B']}, + {key: 'nut', args: ['--nut'], types: ['9', '10'], only: ['C']} +]} + +const cmd = {key: 'Arc', opts: [ + {key: 'Bat', args: ['Bat'], opts: []}, + Cat, + {key: 'dot', args: ['-d', '--dot'], types: ['1']}, + {key: 'eat', args: ['-e', '--eat'], types: ['1', '2']}, + {key: 'fat', args: ['--fat'], types: []}, + {key: 'gut', types: ['3']}, + {key: 'hat', types: ['4', '5']}, + {key: 'ink', descArg: 'INK'} +]} + +test('getMatches returns all cmd args and pos args on unknown input', () => { + const line = '' + + const values = [] + + const res = getMatches(line, values, cmd, {only: true}) + + const exp = [['Bat', 'Cat', '-d', '--dot', '-e', '--eat', '--fat', '<3>', '<4> <5>', 'INK'], line] + + expect(res).toStrictEqual(exp) +}) \ No newline at end of file From 2d1d6319cd0cfc333f59d8ca0e85869f88a30a18 Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:43:16 +0200 Subject: [PATCH 08/22] test: test if getMatches returns all cmd args and pos args on unknown input --- src/repl/completer/getMatches.test.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js index 4d17f1d..bdb4042 100644 --- a/src/repl/completer/getMatches.test.js +++ b/src/repl/completer/getMatches.test.js @@ -33,4 +33,18 @@ test('getMatches returns all cmd args and pos args on unknown input', () => { const exp = [['Bat', 'Cat', '-d', '--dot', '-e', '--eat', '--fat', '<3>', '<4> <5>', 'INK'], line] expect(res).toStrictEqual(exp) -}) \ No newline at end of file +}) + +test('getMatches returns all cmd args and pos args on unknown input', () => { + const line = 'cvbnkl' + + const values = [ + {values: ['cvbnkl']} + ] + + const res = getMatches(line, values, cmd, {only: true}) + + const exp = [['Bat', 'Cat', '-d', '--dot', '-e', '--eat', '--fat', '<3>', '<4> <5>', 'INK'], line] + + expect(res).toStrictEqual(exp) +}) From 9f98542315882519edba213f3d466094cbff569a Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:43:40 +0200 Subject: [PATCH 09/22] test: test if getMatches returns full options args on partial input for subcommands --- src/repl/completer/getMatches.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js index bdb4042..716d6a5 100644 --- a/src/repl/completer/getMatches.test.js +++ b/src/repl/completer/getMatches.test.js @@ -48,3 +48,18 @@ test('getMatches returns all cmd args and pos args on unknown input', () => { expect(res).toStrictEqual(exp) }) + +test('getMatches returns full options args on partial input for subcommands', () => { + const line = 'Ba' + + const values = [ + {values: ['Ba']} + ] + + const res = getMatches(line, values, cmd, {only: true}) + + const exp = [['Bat'], line] + + expect(res).toStrictEqual(exp) +}) + From 0bfc0547547867f849ccbffe331ef713a07a502b Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:43:55 +0200 Subject: [PATCH 10/22] test: test if getMatches completes full options args on partial input for primitive options --- src/repl/completer/getMatches.test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js index 716d6a5..fed9f69 100644 --- a/src/repl/completer/getMatches.test.js +++ b/src/repl/completer/getMatches.test.js @@ -63,3 +63,16 @@ test('getMatches returns full options args on partial input for subcommands', () expect(res).toStrictEqual(exp) }) +test('getMatches completes full options args on partial input for primitive options', () => { + const line = '--do' + + const values = [ + {values: ['--do']} + ] + + const res = getMatches(line, values, cmd, {only: true}) + + const exp = [['--dot'], line] + + expect(res).toStrictEqual(exp) +}) From 70cfb4d4490c201ba989b3ecf2484007dd328aeb Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:44:12 +0200 Subject: [PATCH 11/22] test: test if getMatches completes full options args on partial input for primitive arrays --- src/repl/completer/getMatches.test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js index fed9f69..66db983 100644 --- a/src/repl/completer/getMatches.test.js +++ b/src/repl/completer/getMatches.test.js @@ -76,3 +76,17 @@ test('getMatches completes full options args on partial input for primitive opti expect(res).toStrictEqual(exp) }) + +test('getMatches completes full options args on partial input for primitive arrays', () => { + const line = '--ea' + + const values = [ + {values: ['--ea']} + ] + + const res = getMatches(line, values, cmd, {only: true}) + + const exp = [['--eat'], line] + + expect(res).toStrictEqual(exp) +}) From 3770ed18d48fd6688f39201381d4999fe890852c Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:44:22 +0200 Subject: [PATCH 12/22] test: test if getMatches completes full options args on partial input for flag options --- src/repl/completer/getMatches.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js index 66db983..ad22ef7 100644 --- a/src/repl/completer/getMatches.test.js +++ b/src/repl/completer/getMatches.test.js @@ -90,3 +90,18 @@ test('getMatches completes full options args on partial input for primitive arra expect(res).toStrictEqual(exp) }) + +test('getMatches completes full options args on partial input for flag options', () => { + const line = '--f' + + const values = [ + {values: ['--f']} + ] + + const res = getMatches(line, values, cmd, {only: true}) + + const exp = [['--fat'], line] + + expect(res).toStrictEqual(exp) +}) + From 3cf1459e8cbc2c0340cef9105dad61e0fd541bdd Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:44:34 +0200 Subject: [PATCH 13/22] test: test if getMatches completes full options args on partial input for subcommands --- src/repl/completer/getMatches.test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js index ad22ef7..9ab5b5a 100644 --- a/src/repl/completer/getMatches.test.js +++ b/src/repl/completer/getMatches.test.js @@ -105,3 +105,17 @@ test('getMatches completes full options args on partial input for flag options', expect(res).toStrictEqual(exp) }) +test('getMatches completes full options args on partial input for subcommands', () => { + const line = 'Ba' + + const values = [ + {values: ['Ba']} + ] + + const res = getMatches(line, values, cmd, {only: true}) + + const exp = [['Bat'], line] + + expect(res).toStrictEqual(exp) +}) + From 0a7d652190d114fb7d10f8f964cd413978b536bb Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:44:47 +0200 Subject: [PATCH 14/22] test: test if getMatches completes full options args on partial input for primitive options in subcommands --- src/repl/completer/getMatches.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js index 9ab5b5a..f65d725 100644 --- a/src/repl/completer/getMatches.test.js +++ b/src/repl/completer/getMatches.test.js @@ -119,3 +119,18 @@ test('getMatches completes full options args on partial input for subcommands', expect(res).toStrictEqual(exp) }) +test('getMatches completes full options args on partial input for primitive options in subcommands', () => { + const line = 'Cat --je' + + const values = [ + {...Cat, values: [ + {values: ['--je']} + ]} + ] + + const res = getMatches(line, values, cmd, {only: true}) + + const exp = [['Cat --jet'], line] + + expect(res).toStrictEqual(exp) +}) From 588a06e0a2094f06b4dcf50b097944410ec6741f Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:45:00 +0200 Subject: [PATCH 15/22] test: test if getMatches completes full options args on partial input for primitive arrays in subcommands --- src/repl/completer/getMatches.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js index f65d725..106a5e8 100644 --- a/src/repl/completer/getMatches.test.js +++ b/src/repl/completer/getMatches.test.js @@ -134,3 +134,19 @@ test('getMatches completes full options args on partial input for primitive opti expect(res).toStrictEqual(exp) }) + +test('getMatches completes full options args on partial input for primitive arrays in subcommands', () => { + const line = 'Cat --ki' + + const values = [ + {...Cat, values: [ + {values: ['--ki']} + ]} + ] + + const res = getMatches(line, values, cmd, {only: true}) + + const exp = [['Cat --kit'], line] + + expect(res).toStrictEqual(exp) +}) From f0e8e169d6257402fa0f7b6f5c1c665dc0fde724 Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:45:12 +0200 Subject: [PATCH 16/22] test: test if getMatches completes full options args on partial input for flag options in subcommands --- src/repl/completer/getMatches.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js index 106a5e8..d2623b6 100644 --- a/src/repl/completer/getMatches.test.js +++ b/src/repl/completer/getMatches.test.js @@ -150,3 +150,19 @@ test('getMatches completes full options args on partial input for primitive arra expect(res).toStrictEqual(exp) }) + +test('getMatches completes full options args on partial input for flag options in subcommands', () => { + const line = 'Cat --lo' + + const values = [ + {...Cat, values: [ + {values: ['--lo']} + ]} + ] + + const res = getMatches(line, values, cmd, {only: true}) + + const exp = [['Cat --lot'], line] + + expect(res).toStrictEqual(exp) +}) From 0d4de3900fe7c4d4be4f4db90cd43f0a75d5576c Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:45:24 +0200 Subject: [PATCH 17/22] test: test if getMatches uses only to suggest possible value of array option in subcommands --- src/repl/completer/getMatches.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js index d2623b6..e9c8c87 100644 --- a/src/repl/completer/getMatches.test.js +++ b/src/repl/completer/getMatches.test.js @@ -166,3 +166,19 @@ test('getMatches completes full options args on partial input for flag options i expect(res).toStrictEqual(exp) }) + +test('getMatches uses only to suggest possible value of array option in subcommands', () => { + const line = 'Cat --mad' + + const values = [ + {...Cat, values: [ + {values: ['--mad']} + ]} + ] + + const res = getMatches(line, values, cmd, {only: true}) + + const exp = [['A', 'B'], line] + + expect(res).toStrictEqual(exp) +}) From ff84c77147b442320ddc66c203b9ec33a509a2d6 Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:45:35 +0200 Subject: [PATCH 18/22] test: test if getMatches uses only to complete value of array option in subcommands --- src/repl/completer/getMatches.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js index e9c8c87..3e14512 100644 --- a/src/repl/completer/getMatches.test.js +++ b/src/repl/completer/getMatches.test.js @@ -182,3 +182,19 @@ test('getMatches uses only to suggest possible value of array option in subcomma expect(res).toStrictEqual(exp) }) + +test('getMatches uses only to complete value of array option in subcommands', () => { + const line = 'Cat --nut' + + const values = [ + {...Cat, values: [ + {values: ['--nut']} + ]} + ] + + const res = getMatches(line, values, cmd, {only: true}) + + const exp = [['Cat --nut C'], line] + + expect(res).toStrictEqual(exp) +}) From d75f6c880e9783c7784da827a28b2a0aa84529af Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:45:47 +0200 Subject: [PATCH 19/22] test: test if getMatches returns all cmd args and pos args on -- --- src/repl/completer/getMatches.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js index 3e14512..fe721a2 100644 --- a/src/repl/completer/getMatches.test.js +++ b/src/repl/completer/getMatches.test.js @@ -198,3 +198,21 @@ test('getMatches uses only to complete value of array option in subcommands', () expect(res).toStrictEqual(exp) }) + +test('getMatches returns all cmd args and pos args on --', () => { + const line = 'Cat --jet A --lot --' + + const values = [ + {...Cat, values: [ + {...jet, values: ['A']}, + {...lot, values: [1]}, + {values: ['--']} + ]} + ] + + const res = getMatches(line, values, cmd, {only: true}) + + const exp = [['Bat', 'Cat', '-d', '--dot', '-e', '--eat', '--fat', '<3>', '<4> <5>', 'INK'], line] + + expect(res).toStrictEqual(exp) +}) From 275cdd5051a58fe0169019fd42815eb9019c1986 Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:45:59 +0200 Subject: [PATCH 20/22] test: test if getMatches returns all subcommand args and pos args with no rest --- src/repl/completer/getMatches.test.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js index fe721a2..b4c5f66 100644 --- a/src/repl/completer/getMatches.test.js +++ b/src/repl/completer/getMatches.test.js @@ -216,3 +216,20 @@ test('getMatches returns all cmd args and pos args on --', () => { expect(res).toStrictEqual(exp) }) + +test('getMatches returns all subcommand args and pos args with no rest', () => { + const line = 'Cat --jet A --lot' + + const values = [ + {...Cat, values: [ + {...jet, values: ['A']}, + {...lot, values: [1]} + ]} + ] + + const res = getMatches(line, values, cmd, {only: true}) + + const exp = [['--jet', '--kit', '--lot', '--mad', '--nut'], line] + + expect(res).toStrictEqual(exp) +}) From 4c4ae2c350a3cc00892abef53ad55792c7e4dffd Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:46:12 +0200 Subject: [PATCH 21/22] test: test if etMatches returns all subcommand args and pos args with no rest --- src/repl/completer/getMatches.test.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/repl/completer/getMatches.test.js b/src/repl/completer/getMatches.test.js index b4c5f66..1843bfa 100644 --- a/src/repl/completer/getMatches.test.js +++ b/src/repl/completer/getMatches.test.js @@ -233,3 +233,20 @@ test('getMatches returns all subcommand args and pos args with no rest', () => { expect(res).toStrictEqual(exp) }) + +test('getMatches returns all subcommand args and pos args with no rest', () => { + const line = 'Cat --jet A --lot' + + const values = [ + {...Cat, values: [ + {...jet, values: ['A']}, + {...lot, values: [1]} + ]} + ] + + const res = getMatches(line, values, cmd, {only: true}) + + const exp = [['--jet', '--kit', '--lot', '--mad', '--nut'], line] + + expect(res).toStrictEqual(exp) +}) \ No newline at end of file From 81621528c1739c665ed565aaa3ec24e1c3785489 Mon Sep 17 00:00:00 2001 From: Philipp Wille Date: Sat, 13 Jun 2020 21:48:15 +0200 Subject: [PATCH 22/22] chore: bump version to 0.2.0 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 030eaf7..7433cfd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "shargs-repl", - "version": "0.1.0", + "version": "0.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -755,9 +755,9 @@ "dev": true }, "acorn": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz", - "integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz", + "integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==", "dev": true }, "acorn-globals": { diff --git a/package.json b/package.json index bbd300e..abda078 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "shargs-repl", - "version": "0.1.0", + "version": "0.2.0", "description": "A REPL using shargs commands", "keywords": [ "shargs",