From 922ca13816cdaa1049dc167567cd6ca3309bbd8d Mon Sep 17 00:00:00 2001 From: Trent Mick Date: Fri, 8 Jan 2016 11:07:43 -0800 Subject: [PATCH] clistyle: Much improved bash completions (importantly for the clistyle changes, it supports subsubcommands) --- CHANGES.md | 2 ++ README.md | 21 +++++++++++++------- etc/triton-bash-completion-types.sh | 8 ++++++++ lib/cli.js | 2 +- lib/do_completion.js | 29 ++++++++++++++++++++++++---- package.json | 2 +- test/integration/cli-account.test.js | 9 ++++----- 7 files changed, 55 insertions(+), 18 deletions(-) create mode 100644 etc/triton-bash-completion-types.sh diff --git a/CHANGES.md b/CHANGES.md index 7bc5b48..1a03147 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,8 @@ ## 4.0.0 (not yet released) +- Much improved Bash completion. + - XXX changes in `triton instance,key,network,account`. Drops `triton whoami`. Want to keep that? diff --git a/README.md b/README.md index 5e85cf6..a9498c9 100644 --- a/README.md +++ b/README.md @@ -61,17 +61,24 @@ for example: ### Bash completion -You can quickly source `triton` bash completions in your current -shell with: +Install Bash completion with - source <(triton completion) +```bash +triton completion > /usr/local/etc/bash_completion.d/triton +``` -For a more permanent installation: +Alternatively, if you don't have or don't want to use a "bash\_completion.d" +dir, then something like this would work: - triton completion >> ~/.bashrc +```bash +triton completion > ~/.triton.completion +echo "source ~/.triton.completion" >> ~/.bashrc +``` - # Or maybe: - triton completion > /usr/local/etc/bash_completion.d/triton +Then open a new shell or manually `source FILE` that completion file, and +play with the bash completions: + + triton ## `triton` CLI Usage diff --git a/etc/triton-bash-completion-types.sh b/etc/triton-bash-completion-types.sh new file mode 100644 index 0000000..36f2fc9 --- /dev/null +++ b/etc/triton-bash-completion-types.sh @@ -0,0 +1,8 @@ +# Functions for Bash completion of some 'triton' option/arg types. +function complete_tritonprofile { + local word="$1" + local candidates + candidates=$(ls -1 ~/.triton/profiles.d/*.json 2>/dev/null \ + | sed -E 's/^.*\/([^\/]+)\.json$/\1/') + compgen $compgen_opts -W "$candidates" -- "$word" +} diff --git a/lib/cli.js b/lib/cli.js index 7fde823..aa70c6d 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -17,7 +17,6 @@ var child_process = require('child_process'), exec = child_process.exec; var cmdln = require('cmdln'), Cmdln = cmdln.Cmdln; -var fs = require('fs'); var mkdirp = require('mkdirp'); var util = require('util'), format = util.format; @@ -57,6 +56,7 @@ var OPTIONS = [ { names: ['profile', 'p'], type: 'string', + completionType: 'tritonprofile', env: 'TRITON_PROFILE', helpArg: 'NAME', help: 'Triton client profile to use.' diff --git a/lib/do_completion.js b/lib/do_completion.js index 71c5275..2646b73 100644 --- a/lib/do_completion.js +++ b/lib/do_completion.js @@ -10,13 +10,24 @@ * `triton completion ...` */ +var fs = require('fs'); +var path = require('path'); + + function do_completion(subcmd, opts, args, cb) { if (opts.help) { this.do_help('help', {}, [subcmd], cb); return; } - console.log(this.bashCompletion()); + if (opts.raw) { + console.log(this.bashCompletionSpec()); + } else { + var specExtra = fs.readFileSync( + path.join(__dirname, '../etc/triton-bash-completion-types.sh'), + 'utf8'); + console.log(this.bashCompletion({specExtra: specExtra})); + } cb(); } @@ -25,16 +36,26 @@ do_completion.options = [ names: ['help', 'h'], type: 'bool', help: 'Show this help.' + }, + { + names: ['raw'], + type: 'bool', + hidden: true, + help: 'Only output the Bash completion "spec". ' + + 'This is only useful for debugging.' } ]; do_completion.help = [ 'Output bash completion code for the `triton` CLI.', '', 'Installation:', - ' triton completion >> ~/.bashrc', + ' {{name}} completion > /usr/local/etc/bash_completion.d/{{name}}', '', - 'Or maybe:', - ' triton completion > /usr/local/etc/bash_completion.d/triton' + 'Alternative installation:', + ' {{name}} completion > ~/.{{name}}.completion', + ' echo "source ~/.{{name}}.completion" >> ~/.bashrc', + '', + '{{options}}' ].join('\n'); do_completion.hidden = true; diff --git a/package.json b/package.json index e87be12..08a6c6f 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "backoff": "2.4.1", "bigspinner": "3.1.0", "bunyan": "1.5.1", - "cmdln": "3.4.2", + "cmdln": "3.5.0", "extsprintf": "1.0.2", "lomstream": "1.1.0", "mkdirp": "0.5.1", diff --git a/test/integration/cli-account.test.js b/test/integration/cli-account.test.js index fb4d8d7..888bdb4 100644 --- a/test/integration/cli-account.test.js +++ b/test/integration/cli-account.test.js @@ -43,8 +43,8 @@ test('triton account', function (tt) { }); }); - tt.test(' triton account', function (t) { - h.triton('account', function (err, stdout, stderr) { + tt.test(' triton account get', function (t) { + h.triton('account get', function (err, stdout, stderr) { if (h.ifErr(t, err)) return t.end(); t.ok(new RegExp( @@ -53,8 +53,8 @@ test('triton account', function (tt) { }); }); - tt.test(' triton account -j', function (t) { - h.triton('account -j', function (err, stdout, stderr) { + tt.test(' triton account get -j', function (t) { + h.triton('account get -j', function (err, stdout, stderr) { if (h.ifErr(t, err)) return t.end(); var account = JSON.parse(stdout); @@ -62,5 +62,4 @@ test('triton account', function (tt) { t.end(); }); }); - });