Skip to content

Commit

Permalink
chore(ci): run shellcheck on bash/zsh completion scripts (#79)
Browse files Browse the repository at this point in the history
  • Loading branch information
c4spar committed Aug 31, 2020
1 parent 09c0fc2 commit 40f2dc9
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 19 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,23 @@ jobs:
- name: Setup Deno
uses: denolib/setup-deno@master

- name: Setup shellcheck
run: >
wget https://github.com/koalaman/shellcheck/releases/download/v0.7.1/shellcheck-v0.7.1.linux.x86_64.tar.xz &&
tar -xvf shellcheck-v0.7.1.linux.x86_64.tar.xz &&
mv shellcheck-v0.7.1/shellcheck . &&
rm -rf shellcheck-v0.7.1 &&
chmod +x shellcheck &&
./shellcheck --version
- name: Check formatting
run: deno fmt --check

- name: Run linter
run: deno lint --unstable

- name: Run bash check
run: ./shellcheck --shell bash <(deno run -r ./examples/command/shell-completions.ts completions bash)

- name: Run zsh check
run: ./shellcheck --shell bash <(deno run -r ./examples/command/shell-completions.ts completions zsh)
3 changes: 2 additions & 1 deletion command/completions/bash-completions-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ export class BashCompletionsGenerator {
? ` v${this.cmd.getVersion()}`
: "";

return `# bash completion support for ${path}${version}
return `#!/usr/bin/env bash
# bash completion support for ${path}${version}
_${replaceSpecialChars(path)}() {
local word cur prev opts
Expand Down
43 changes: 25 additions & 18 deletions command/completions/zsh-completions-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,20 @@ export class ZshCompletionsGenerator {

/** Generates zsh completions code. */
private generate(): string {
const version: string | undefined = this.cmd.getVersion();
const versionStr = version
? `# version: ${this.cmd.getVersion() || "-"}\n#\n`
const path = this.cmd.getPath();
const name = this.cmd.getName();
const version: string | undefined = this.cmd.getVersion()
? ` v${this.cmd.getVersion()}`
: "";

return `
# compdef _${replaceSpecialChars(this.cmd.getPath())} ${this.cmd.getPath()}
#
# zsh completion for ${this.cmd.getPath()}
#
${versionStr}
return `#!/usr/bin/env zsh
# zsh completion support for ${path}${version}
autoload -U is-at-least
(( $+functions[__${replaceSpecialChars(this.cmd.getName())}_complete] )) ||
function __${replaceSpecialChars(this.cmd.getName())}_complete {
# shellcheck disable=SC2154
(( $+functions[__${replaceSpecialChars(name)}_complete] )) ||
function __${replaceSpecialChars(name)}_complete {
local name="$1"; shift
local action="$1"; shift
integer ret=1
Expand All @@ -42,10 +41,11 @@ function __${replaceSpecialChars(this.cmd.getName())}_complete {
_tags "$name"
while _tags; do
if _requested "$name"; then
values=( \$( ${this.cmd.getName()} completions complete $action $@) )
# shellcheck disable=SC2207
values=( \$( ${name} completions complete "\${action}" "\${@}") )
if (( \${#values[@]} )); then
while _next_label "$name" expl "$action"; do
compadd -S '' "\$expl[@]" $values[@]
compadd -S '' "\${expl[@]}" "\${values[@]}"
done
fi
fi
Expand All @@ -54,9 +54,9 @@ function __${replaceSpecialChars(this.cmd.getName())}_complete {
${this.generateCompletions(this.cmd).trim()}
# _${replaceSpecialChars(this.cmd.getPath())} "\${@}"
# _${replaceSpecialChars(path)} "\${@}"
compdef _${replaceSpecialChars(this.cmd.getPath())} ${this.cmd.getPath()}
compdef _${replaceSpecialChars(path)} ${path}
#
# Local Variables:
Expand All @@ -80,10 +80,16 @@ compdef _${replaceSpecialChars(this.cmd.getPath())} ${this.cmd.getPath()}

path = (path ? path + " " : "") + command.getName();

return `(( $+functions[_${replaceSpecialChars(path)}] )) ||
return `# shellcheck disable=SC2154
(( $+functions[_${replaceSpecialChars(path)}] )) ||
function _${replaceSpecialChars(path)}() {` +
(!command.getParent()
? `\n\n local context state state_descr line\n typeset -A opt_args`
? `
# shellcheck disable=SC2034
local context state state_descr line
# shellcheck disable=SC2034
typeset -A opt_args`
: "") +
this.generateCommandCompletions(command, path) +
this.generateSubCommandCompletions(command, path) +
Expand All @@ -110,6 +116,7 @@ function _${replaceSpecialChars(path)}() {` +
if (completions) {
completions = `
local -a commands
# shellcheck disable=SC2034
commands=(
${completions}
)
Expand Down Expand Up @@ -153,7 +160,7 @@ function _${replaceSpecialChars(path)}() {` +

return `\n
function _command_args() {
case "$words[1]" in\n ${actions}\n esac
case "\${words[1]}" in\n ${actions}\n esac
}`;
}

Expand Down
53 changes: 53 additions & 0 deletions examples/command/shell-completions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env deno run

import { Command } from "../../command/command.ts";
import { CompletionsCommand } from "../../command/completions/mod.ts";

await new Command()
.throwErrors()
.name("cliffy")
.version("0.1.0")
// completions
.complete("verbose", () => ["1", "2", "3"], { global: true })
// options
.option(
"-v, --verbose <verbosity:number:verbose>",
"Increase verbosity.",
{ global: true, value: (cur, prev = 0) => prev + cur },
)
.option(
"-s, --silent <val:string:my-type>",
"Disable output.",
{ global: true },
)
// animal command
.command("animal <animal:string:animal>", "Select an animal.")
.complete("animal", () => ["dog", "cat", "dino"])
.action((_, animal: string) => console.log(animal))
// country command
.command("country <country:string:country>", "Select a country.")
.complete("country", () => ["germany", "spain", "indonesia"])
.action((_, country: string) => console.log(country))
// car command
.command(
"car",
new Command()
.description("Select a car.")
.complete("color", () => ["Black", "Red", "Yellow"])
.option(
"-c, --color <color:string:color>",
"other description...",
{ global: true },
)
.command("audi <model:string:audi>")
.complete("audi", () => ["R8", "R7"])
.action(({ color }, model: string) => console.log({ color, model }))
.command("bmw <model:string:bmw>")
.complete("bmw", () => ["8er", "7er"])
.action(({ color }, model: string) => console.log({ color, model }))
.command("porsche <model:string:porsche>")
.complete("porsche", () => ["911 GT3 RS", "718 Spyder"])
.action(({ color }, model: string) => console.log({ color, model })),
)
.command("completions", new CompletionsCommand())
.parse();

0 comments on commit 40f2dc9

Please sign in to comment.