diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..73f69e09
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 00000000..03d9549e
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jsLinters/eslint.xml b/.idea/jsLinters/eslint.xml
new file mode 100644
index 00000000..541945bb
--- /dev/null
+++ b/.idea/jsLinters/eslint.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 00000000..1763e153
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000..9114e226
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/plugin-autocomplete.iml b/.idea/plugin-autocomplete.iml
new file mode 100644
index 00000000..d6ebd480
--- /dev/null
+++ b/.idea/plugin-autocomplete.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..35eb1ddf
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/base.ts b/src/base.ts
index f051c4a2..21bb289f 100644
--- a/src/base.ts
+++ b/src/base.ts
@@ -33,7 +33,7 @@ export abstract class AutocompleteBase extends Command {
this.error('Missing required argument shell')
}
this.errorIfWindows()
- if (!['bash', 'zsh'].includes(shell)) {
+ if (!['bash', 'fish', 'zsh'].includes(shell)) {
throw new Error(`${shell} is not a supported shell for autocomplete`)
}
}
diff --git a/src/commands/autocomplete/create.ts b/src/commands/autocomplete/create.ts
index 755e8b97..cb3d1af3 100644
--- a/src/commands/autocomplete/create.ts
+++ b/src/commands/autocomplete/create.ts
@@ -1,3 +1,4 @@
+import * as child_process from 'child_process'
import * as fs from 'fs-extra'
import * as path from 'path'
@@ -51,6 +52,10 @@ export default class Create extends AutocompleteBase {
await fs.writeFile(this.bashCompletionFunctionPath, this.bashCompletionFunction)
await fs.writeFile(this.zshSetupScriptPath, this.zshSetupScript)
await fs.writeFile(this.zshCompletionFunctionPath, this.zshCompletionFunction)
+ if (this.config.shell === 'fish') {
+ debug(`fish shell detected, writing completion to ${this.fishCompletionFunctionPath}`)
+ await fs.writeFile(this.fishCompletionFunctionPath, this.fishCompletionFunction)
+ }
}
private get bashSetupScriptPath(): string {
@@ -78,6 +83,12 @@ export default class Create extends AutocompleteBase {
return path.join(this.bashFunctionsDir, `${this.cliBin}.bash`)
}
+ private get fishCompletionFunctionPath(): string {
+ // dynamically load path to completions file
+ const dir = child_process.execSync('pkg-config --variable completionsdir fish').toString().trimRight()
+ return `${dir}/${this.cliBin}.fish`
+ }
+
private get zshCompletionFunctionPath(): string {
// /autocomplete/functions/zsh/_
return path.join(this.zshFunctionsDir, `_${this.cliBin}`)
@@ -221,13 +232,51 @@ complete -o default -F _${cliBin} ${cliBin}
`
}
+ private get fishCompletionFunction(): string {
+ const cliBin = this.cliBin
+ const completions = []
+ completions.push(`
+function __fish_${cliBin}_needs_command
+ set cmd (commandline -opc)
+ if [ (count $cmd) -eq 1 ]
+ return 0
+ else
+ return 1
+ end
+end
+
+function __fish_${cliBin}_using_command
+ set cmd (commandline -opc)
+ if [ (count $cmd) -gt 1 ]
+ if [ $argv[1] = $cmd[2] ]
+ return 0
+ end
+ end
+ return 1
+end`,
+ )
+
+ for (const command of this.commands) {
+ completions.push(`complete -f -c ${cliBin} -n '__fish_${cliBin}_needs_command' -a ${command.id} -d "${command.description}"`)
+ const flags = command.flags || {}
+ Object.keys(flags)
+ .filter(flag => flags[flag] && !flags[flag].hidden)
+ .forEach(flag => {
+ const f = flags[flag] || {}
+ const shortFlag = f.char ? `-s ${f.char}` : ''
+ const description = f.description ? `-d "${f.description}"` : ''
+ const options = f.options ? `-r -a "${f.options.join(' ')}"` : ''
+ completions.push(`complete -f -c ${cliBin} -n ' __fish_${cliBin}_using_command ${command.id}' -l ${flag} ${shortFlag} ${options} ${description}`)
+ })
+ }
+ return completions.join('\n')
+ }
+
private get zshCompletionFunction(): string {
const cliBin = this.cliBin
const allCommandsMeta = this.genAllCommandsMetaString
const caseStatementForFlagsMeta = this.genCaseStatementForFlagsMetaString
-
return `#compdef ${cliBin}
-
_${cliBin} () {
local _command_id=\${words[2]}
local _cur=\${words[CURRENT]}
diff --git a/src/commands/autocomplete/index.ts b/src/commands/autocomplete/index.ts
index 4a991680..45b634a5 100644
--- a/src/commands/autocomplete/index.ts
+++ b/src/commands/autocomplete/index.ts
@@ -18,13 +18,14 @@ export default class Index extends AutocompleteBase {
static examples = [
'$ <%= config.bin %> autocomplete',
'$ <%= config.bin %> autocomplete bash',
+ '$ <%= config.bin %> autocomplete fish',
'$ <%= config.bin %> autocomplete zsh',
'$ <%= config.bin %> autocomplete --refresh-cache',
]
async run() {
const {args, flags} = this.parse(Index)
- const shell = args.shell || this.determineShell(this.config.shell)
+ const shell = args.shell || this.config.shell
this.errorIfNotSupportedShell(shell)
cli.action.start(`${chalk.bold('Building the autocomplete cache')}`)
@@ -33,14 +34,14 @@ export default class Index extends AutocompleteBase {
if (!flags['refresh-cache']) {
const bin = this.config.bin
- const tabStr = shell === 'bash' ? '' : ''
- const note = shell === 'zsh' ? `After sourcing, you can run \`${chalk.cyan('$ compaudit -D')}\` to ensure no permissions conflicts are present` : 'If your terminal starts as a login shell you may need to print the init script into ~/.bash_profile or ~/.profile.'
+ const tabStr = this.getTabStr(shell)
+ const setupStep = this.getSetupStep(shell, bin)
+ const note = this.getNote(shell)
this.log(`
${chalk.bold(`Setup Instructions for ${bin.toUpperCase()} CLI Autocomplete ---`)}
-1) Add the autocomplete env var to your ${shell} profile and source it
-${chalk.cyan(`$ printf "eval $(${bin} autocomplete:script ${shell})" >> ~/.${shell}rc; source ~/.${shell}rc`)}
+1) ${setupStep}
NOTE: ${note}
@@ -52,4 +53,43 @@ Enjoy!
`)
}
}
+
+ private getSetupStep(shell: string, bin: string): string {
+ switch (shell) {
+ case 'bash':
+ case 'zsh':
+ return `Add the autocomplete env var to your ${shell} profile and source it
+${chalk.cyan(`$ printf "$(${bin} autocomplete:script ${shell})" >> ~/.${shell}rc; source ~/.${shell}rc`)}`
+ case 'fish':
+ return `Update your shell to load the new completions
+${chalk.cyan('source ~/.config/fish/config.fish')}`
+ default:
+ return ''
+ }
+ }
+
+ private getNote(shell: string): string {
+ switch (shell) {
+ case 'bash':
+ return 'If your terminal starts as a login shell you may need to print the init script into ~/.bash_profile or ~/.profile.'
+ case 'fish':
+ return 'This assumes your Fish configuration is stored at ~/.config/fish/config.fish'
+ case 'zsh':
+ return `After sourcing, you can run \`${chalk.cyan('$ compaudit -D')}\` to ensure no permissions conflicts are present`
+ default:
+ return ''
+ }
+ }
+
+ private getTabStr(shell: string): string {
+ switch (shell) {
+ case 'bash':
+ return ''
+ case 'fish':
+ case 'zsh':
+ return ''
+ default:
+ return ''
+ }
+ }
}
diff --git a/test/commands/autocomplete/create.test.ts b/test/commands/autocomplete/create.test.ts
index 9490cc61..02cf7049 100644
--- a/test/commands/autocomplete/create.test.ts
+++ b/test/commands/autocomplete/create.test.ts
@@ -101,7 +101,6 @@ complete -o default -F _oclif-example oclif-example\n`)
it('#zshCompletionFunction', () => {
/* eslint-disable no-useless-escape */
expect(cmd.zshCompletionFunction).to.eq(`#compdef oclif-example
-
_oclif-example () {
local _command_id=\${words[2]}
local _cur=\${words[CURRENT]}
diff --git a/test/commands/autocomplete/index.test.ts b/test/commands/autocomplete/index.test.ts
index 710bb763..6405d412 100644
--- a/test/commands/autocomplete/index.test.ts
+++ b/test/commands/autocomplete/index.test.ts
@@ -13,7 +13,7 @@ skipWindows('autocomplete index', () => {
Setup Instructions for OCLIF-EXAMPLE CLI Autocomplete ---
1) Add the autocomplete env var to your bash profile and source it
-$ printf \"eval $(oclif-example autocomplete:script bash)\" >> ~/.bashrc; source ~/.bashrc
+$ printf \"$(oclif-example autocomplete:script bash)\" >> ~/.bashrc; source ~/.bashrc
NOTE: If your terminal starts as a login shell you may need to print the init script into ~/.bash_profile or ~/.profile.
@@ -23,8 +23,7 @@ $ oclif-example command -- # Flag completion
Enjoy!
-`,
- )
+`)
})
test
@@ -35,7 +34,7 @@ Enjoy!
Setup Instructions for OCLIF-EXAMPLE CLI Autocomplete ---
1) Add the autocomplete env var to your zsh profile and source it
-$ printf \"eval $(oclif-example autocomplete:script zsh)\" >> ~/.zshrc; source ~/.zshrc
+$ printf \"$(oclif-example autocomplete:script zsh)\" >> ~/.zshrc; source ~/.zshrc
NOTE: After sourcing, you can run \`$ compaudit -D\` to ensure no permissions conflicts are present
@@ -45,6 +44,28 @@ $ oclif-example command -- # Flag completion
Enjoy!
+`,
+ )
+ })
+
+ test
+ .stdout()
+ .command(['autocomplete', 'fish'])
+ .it('provides fish instructions', ctx => {
+ expect(ctx.stdout).to.equal(`
+Setup Instructions for OCLIF-EXAMPLE CLI Autocomplete ---
+
+1) Update your shell to load the new completions
+source ~/.config/fish/config.fish
+
+NOTE: This assumes your Fish configuration is stored at ~/.config/fish/config.fish
+
+2) Test it out, e.g.:
+$ oclif-example # Command completion
+$ oclif-example command -- # Flag completion
+
+Enjoy!
+
`,
)
})
diff --git a/test/commands/autocomplete/script.test.ts b/test/commands/autocomplete/script.test.ts
index 094f4cf2..0de7e5be 100644
--- a/test/commands/autocomplete/script.test.ts
+++ b/test/commands/autocomplete/script.test.ts
@@ -31,8 +31,12 @@ OCLIF_EXAMPLE_AC_ZSH_SETUP_PATH=${
test
.stdout()
.command(['autocomplete:script', 'fish'])
- .catch(error => {
- expect(error.message).to.contain('fish is not a supported shell for autocomplete')
+ .it('outputs fish profile config', ctx => {
+ expect(ctx.stdout).to.contain(`
+OCLIF_EXAMPLE_AC_FISH_SETUP_PATH=${
+ ctx.config.cacheDir
+}/autocomplete/fish_setup && test -f $OCLIF_EXAMPLE_AC_FISH_SETUP_PATH && source $OCLIF_EXAMPLE_AC_FISH_SETUP_PATH; # oclif-example autocomplete setup
+`,
+ )
})
- .it('errors on unsupported shell')
})