[READ-ONLY] Mirror of https://github.com/bombshell-dev/tab. shell autocompletions for javascript CLIs
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256import { ShellCompDirective } from './t';
export function generate(name: string, exec: string): string { // Replace '-' and ':' with '_' for variable names const nameForVar = name.replace(/[-:]/g, '_');
// Shell completion directives const ShellCompDirectiveError = ShellCompDirective.ShellCompDirectiveError; const ShellCompDirectiveNoSpace = ShellCompDirective.ShellCompDirectiveNoSpace; const ShellCompDirectiveNoFileComp = ShellCompDirective.ShellCompDirectiveNoFileComp; const ShellCompDirectiveFilterFileExt = ShellCompDirective.ShellCompDirectiveFilterFileExt; const ShellCompDirectiveFilterDirs = ShellCompDirective.ShellCompDirectiveFilterDirs; const ShellCompDirectiveKeepOrder = ShellCompDirective.ShellCompDirectiveKeepOrder;
return `# fish completion for ${name} -*- shell-script -*-
function __${nameForVar}_debug set -l file "$BASH_COMP_DEBUG_FILE" if test -n "$file" echo "$argv" >> $file endend
function __${nameForVar}_perform_completion __${nameForVar}_debug "Starting __${nameForVar}_perform_completion"
# Extract all args except the last one set -l args (commandline -opc) # Extract the last arg and escape it in case it is a space or wildcard set -l lastArg (string escape -- (commandline -ct))
__${nameForVar}_debug "args: $args" __${nameForVar}_debug "last arg: $lastArg"
# Build the completion request command set -l requestComp "${exec} complete -- (string join ' ' -- (string escape -- $args[2..-1])) $lastArg"
__${nameForVar}_debug "Calling $requestComp" set -l results (eval $requestComp 2> /dev/null)
# Some programs may output extra empty lines after the directive. # Let's ignore them or else it will break completion. # Ref: https://github.com/spf13/cobra/issues/1279 for line in $results[-1..1] if test (string trim -- $line) = "" # Found an empty line, remove it set results $results[1..-2] else # Found non-empty line, we have our proper output break end end
set -l comps $results[1..-2] set -l directiveLine $results[-1]
# For Fish, when completing a flag with an = (e.g., <program> -n=<TAB>) # completions must be prefixed with the flag set -l flagPrefix (string match -r -- '-.*=' "$lastArg")
__${nameForVar}_debug "Comps: $comps" __${nameForVar}_debug "DirectiveLine: $directiveLine" __${nameForVar}_debug "flagPrefix: $flagPrefix"
for comp in $comps printf "%s%s\\n" "$flagPrefix" "$comp" end
printf "%s\\n" "$directiveLine"end
# This function limits calls to __${nameForVar}_perform_completion, by caching the resultfunction __${nameForVar}_perform_completion_once __${nameForVar}_debug "Starting __${nameForVar}_perform_completion_once"
if test -n "$__${nameForVar}_perform_completion_once_result" __${nameForVar}_debug "Seems like a valid result already exists, skipping __${nameForVar}_perform_completion" return 0 end
set --global __${nameForVar}_perform_completion_once_result (__${nameForVar}_perform_completion) if test -z "$__${nameForVar}_perform_completion_once_result" __${nameForVar}_debug "No completions, probably due to a failure" return 1 end
__${nameForVar}_debug "Performed completions and set __${nameForVar}_perform_completion_once_result" return 0end
# This function is used to clear the cached result after completions are runfunction __${nameForVar}_clear_perform_completion_once_result __${nameForVar}_debug "" __${nameForVar}_debug "========= clearing previously set __${nameForVar}_perform_completion_once_result variable ==========" set --erase __${nameForVar}_perform_completion_once_result __${nameForVar}_debug "Successfully erased the variable __${nameForVar}_perform_completion_once_result"end
function __${nameForVar}_requires_order_preservation __${nameForVar}_debug "" __${nameForVar}_debug "========= checking if order preservation is required =========="
__${nameForVar}_perform_completion_once if test -z "$__${nameForVar}_perform_completion_once_result" __${nameForVar}_debug "Error determining if order preservation is required" return 1 end
set -l directive (string sub --start 2 $__${nameForVar}_perform_completion_once_result[-1]) __${nameForVar}_debug "Directive is: $directive"
set -l shellCompDirectiveKeepOrder ${ShellCompDirectiveKeepOrder} set -l keeporder (math (math --scale 0 $directive / $shellCompDirectiveKeepOrder) % 2) __${nameForVar}_debug "Keeporder is: $keeporder"
if test $keeporder -ne 0 __${nameForVar}_debug "This does require order preservation" return 0 end
__${nameForVar}_debug "This doesn't require order preservation" return 1end
# This function does two things:# - Obtain the completions and store them in the global __${nameForVar}_comp_results# - Return false if file completion should be performedfunction __${nameForVar}_prepare_completions __${nameForVar}_debug "" __${nameForVar}_debug "========= starting completion logic =========="
# Start fresh set --erase __${nameForVar}_comp_results
__${nameForVar}_perform_completion_once __${nameForVar}_debug "Completion results: $__${nameForVar}_perform_completion_once_result"
if test -z "$__${nameForVar}_perform_completion_once_result" __${nameForVar}_debug "No completion, probably due to a failure" # Might as well do file completion, in case it helps return 1 end
set -l directive (string sub --start 2 $__${nameForVar}_perform_completion_once_result[-1]) set --global __${nameForVar}_comp_results $__${nameForVar}_perform_completion_once_result[1..-2]
__${nameForVar}_debug "Completions are: $__${nameForVar}_comp_results" __${nameForVar}_debug "Directive is: $directive"
set -l shellCompDirectiveError ${ShellCompDirectiveError} set -l shellCompDirectiveNoSpace ${ShellCompDirectiveNoSpace} set -l shellCompDirectiveNoFileComp ${ShellCompDirectiveNoFileComp} set -l shellCompDirectiveFilterFileExt ${ShellCompDirectiveFilterFileExt} set -l shellCompDirectiveFilterDirs ${ShellCompDirectiveFilterDirs}
if test -z "$directive" set directive 0 end
set -l compErr (math (math --scale 0 $directive / $shellCompDirectiveError) % 2) if test $compErr -eq 1 __${nameForVar}_debug "Received error directive: aborting." # Might as well do file completion, in case it helps return 1 end
set -l filefilter (math (math --scale 0 $directive / $shellCompDirectiveFilterFileExt) % 2) set -l dirfilter (math (math --scale 0 $directive / $shellCompDirectiveFilterDirs) % 2) if test $filefilter -eq 1; or test $dirfilter -eq 1 __${nameForVar}_debug "File extension filtering or directory filtering not supported" # Do full file completion instead return 1 end
set -l nospace (math (math --scale 0 $directive / $shellCompDirectiveNoSpace) % 2) set -l nofiles (math (math --scale 0 $directive / $shellCompDirectiveNoFileComp) % 2)
__${nameForVar}_debug "nospace: $nospace, nofiles: $nofiles"
# If we want to prevent a space, or if file completion is NOT disabled, # we need to count the number of valid completions. # To do so, we will filter on prefix as the completions we have received # may not already be filtered so as to allow fish to match on different # criteria than the prefix. if test $nospace -ne 0; or test $nofiles -eq 0 set -l prefix (commandline -t | string escape --style=regex) __${nameForVar}_debug "prefix: $prefix"
set -l completions (string match -r -- "^$prefix.*" $__${nameForVar}_comp_results) set --global __${nameForVar}_comp_results $completions __${nameForVar}_debug "Filtered completions are: $__${nameForVar}_comp_results"
# Important not to quote the variable for count to work set -l numComps (count $__${nameForVar}_comp_results) __${nameForVar}_debug "numComps: $numComps"
if test $numComps -eq 1; and test $nospace -ne 0 # We must first split on \\t to get rid of the descriptions to be # able to check what the actual completion will be. # We don't need descriptions anyway since there is only a single # real completion which the shell will expand immediately. set -l split (string split --max 1 "\\t" $__${nameForVar}_comp_results[1])
# Fish won't add a space if the completion ends with any # of the following characters: @=/:., set -l lastChar (string sub -s -1 -- $split) if not string match -r -q "[@=/:.,]" -- "$lastChar" # In other cases, to support the "nospace" directive we trick the shell # by outputting an extra, longer completion. __${nameForVar}_debug "Adding second completion to perform nospace directive" set --global __${nameForVar}_comp_results $split[1] $split[1]. __${nameForVar}_debug "Completions are now: $__${nameForVar}_comp_results" end end
if test $numComps -eq 0; and test $nofiles -eq 0 # To be consistent with bash and zsh, we only trigger file # completion when there are no other completions __${nameForVar}_debug "Requesting file completion" return 1 end end
return 0end
# Since Fish completions are only loaded once the user triggers them, we trigger them ourselves# so we can properly delete any completions provided by another script.# Only do this if the program can be found, or else fish may print some errors; besides,# the existing completions will only be loaded if the program can be found.if type -q "${name}" # The space after the program name is essential to trigger completion for the program # and not completion of the program name itself. # Also, we use '> /dev/null 2>&1' since '&>' is not supported in older versions of fish. complete --do-complete "${name} " > /dev/null 2>&1end
# Remove any pre-existing completions for the program since we will be handling all of them.complete -c ${name} -e
# This will get called after the two calls below and clear the cached resultcomplete -c ${name} -n '__${nameForVar}_clear_perform_completion_once_result'# The call to __${nameForVar}_prepare_completions will setup __${nameForVar}_comp_results# which provides the program's completion choices.# If this doesn't require order preservation, we don't use the -k flagcomplete -c ${name} -n 'not __${nameForVar}_requires_order_preservation && __${nameForVar}_prepare_completions' -f -a '$__${nameForVar}_comp_results'# Otherwise we use the -k flagcomplete -k -c ${name} -n '__${nameForVar}_requires_order_preservation && __${nameForVar}_prepare_completions' -f -a '$__${nameForVar}_comp_results'`;}