Skip to content

Commit

Permalink
feat: add completion for fish
Browse files Browse the repository at this point in the history
  • Loading branch information
MunifTanjim committed Jun 21, 2020
1 parent 62329f6 commit 575dffe
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export abstract class CompletionBase extends Command {
char: 's',
env: 'SHELL',
parse: (shell) => basename(shell),
options: ['bash', 'zsh'],
options: ['bash', 'fish', 'zsh'],
required: true,
}),
}
Expand Down
5 changes: 5 additions & 0 deletions src/commands/completion/generate.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CompletionBase } from '../../base'
import { generateCompletionScriptForBash } from '../../utils/bash'
import { generateCompletionScriptForFish } from '../../utils/fish'
import { generateCompletionScriptForZsh } from '../../utils/zsh'

export default class CompletionGenerate extends CompletionBase {
Expand All @@ -23,6 +24,10 @@ export default class CompletionGenerate extends CompletionBase {
scriptContent = generateCompletionScriptForBash(this.config)
}

if (shell === 'fish') {
scriptContent = generateCompletionScriptForFish(this.config)
}

if (shell === 'zsh') {
scriptContent = generateCompletionScriptForZsh(this.config)
}
Expand Down
59 changes: 59 additions & 0 deletions src/utils/fish.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import type { Command } from '@oclif/command'
import { getFirstLine } from './template'

export function generateCompletionScriptForFish({
bin,
commands,
}: Command['config']) {
const scriptParts: string[] = []

scriptParts.push(`set -l seen __fish_seen_subcommand_from`)

scriptParts.push(
`set -l commands ${commands.map((command) => command.id).join(' ')}`
)

for (const command of commands) {
if (command.hidden) {
continue
}

const commandParts: string[] = []

commandParts.push(
`complete -c ${bin} -n "not $seen $commands" -f -a ${
command.id
} -d '${getFirstLine(command.description)}'`
)

for (const [name, flag] of Object.entries(command.flags)) {
if (flag.hidden) {
continue
}

let flagPart = `complete -c ${bin} -n "$seen ${command.id}" -l ${name}`

if (flag.char) {
flagPart += ` -s ${flag.char}`
}

if (flag.type === 'option') {
if (flag.options) {
flagPart += ` -x -a "${flag.options.join(' ')}"`
} else {
flagPart += ` -r`
}
}

if (flag.description) {
flagPart += ` -d "${getFirstLine(flag.description)}"`
}

commandParts.push(flagPart)
}

scriptParts.push(commandParts.join('\n'))
}

return scriptParts.join('\n'.repeat(2))
}
4 changes: 4 additions & 0 deletions src/utils/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,7 @@ export function template(
return parts.join('')
}
}

export const getFirstLine = (string = ''): string => {
return string.split('\n')[0]
}

0 comments on commit 575dffe

Please sign in to comment.