Advertisement
Guest User

fish-completion

a guest
Jul 27th, 2021
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 6.95 KB | None | 0 0
  1. # fish completion for restic                               -*- shell-script -*-
  2.  
  3. function __restic_debug
  4.     set -l file "$BASH_COMP_DEBUG_FILE"
  5.     if test -n "$file"
  6.         echo "$argv" >> $file
  7.     end
  8. end
  9.  
  10. function __restic_perform_completion
  11.     __restic_debug "Starting __restic_perform_completion"
  12.  
  13.     # Extract all args except the last one
  14.     set -l args (commandline -opc)
  15.     # Extract the last arg and escape it in case it is a space
  16.     set -l lastArg (string escape -- (commandline -ct))
  17.  
  18.     __restic_debug "args: $args"
  19.     __restic_debug "last arg: $lastArg"
  20.  
  21.     set -l requestComp "$args[1] __complete $args[2..-1] $lastArg"
  22.  
  23.     __restic_debug "Calling $requestComp"
  24.     set -l results (eval $requestComp 2> /dev/null)
  25.  
  26.     # Some programs may output extra empty lines after the directive.
  27.     # Let's ignore them or else it will break completion.
  28.     # Ref: https://github.com/spf13/cobra/issues/1279
  29.     for line in $results[-1..1]
  30.         if test (string trim -- $line) = ""
  31.             # Found an empty line, remove it
  32.             set results $results[1..-2]
  33.         else
  34.             # Found non-empty line, we have our proper output
  35.             break
  36.         end
  37.     end
  38.  
  39.     set -l comps $results[1..-2]
  40.     set -l directiveLine $results[-1]
  41.  
  42.     # For Fish, when completing a flag with an = (e.g., <program> -n=<TAB>)
  43.     # completions must be prefixed with the flag
  44.     set -l flagPrefix (string match -r -- '-.*=' "$lastArg")
  45.  
  46.     __restic_debug "Comps: $comps"
  47.     __restic_debug "DirectiveLine: $directiveLine"
  48.     __restic_debug "flagPrefix: $flagPrefix"
  49.  
  50.     for comp in $comps
  51.         printf "%s%s\n" "$flagPrefix" "$comp"
  52.     end
  53.  
  54.     printf "%s\n" "$directiveLine"
  55. end
  56.  
  57. # This function does two things:
  58. # - Obtain the completions and store them in the global __restic_comp_results
  59. # - Return false if file completion should be performed
  60. function __restic_prepare_completions
  61.     __restic_debug ""
  62.     __restic_debug "========= starting completion logic =========="
  63.  
  64.     # Start fresh
  65.     set --erase __restic_comp_results
  66.  
  67.     set -l results (__restic_perform_completion)
  68.     __restic_debug "Completion results: $results"
  69.  
  70.     if test -z "$results"
  71.         __restic_debug "No completion, probably due to a failure"
  72.         # Might as well do file completion, in case it helps
  73.         return 1
  74.     end
  75.  
  76.     set -l directive (string sub --start 2 $results[-1])
  77.     set --global __restic_comp_results $results[1..-2]
  78.  
  79.     __restic_debug "Completions are: $__restic_comp_results"
  80.     __restic_debug "Directive is: $directive"
  81.  
  82.     set -l shellCompDirectiveError 1
  83.     set -l shellCompDirectiveNoSpace 2
  84.     set -l shellCompDirectiveNoFileComp 4
  85.     set -l shellCompDirectiveFilterFileExt 8
  86.     set -l shellCompDirectiveFilterDirs 16
  87.  
  88.     if test -z "$directive"
  89.         set directive 0
  90.     end
  91.  
  92.     set -l compErr (math (math --scale 0 $directive / $shellCompDirectiveError) % 2)
  93.     if test $compErr -eq 1
  94.         __restic_debug "Received error directive: aborting."
  95.         # Might as well do file completion, in case it helps
  96.         return 1
  97.     end
  98.  
  99.     set -l filefilter (math (math --scale 0 $directive / $shellCompDirectiveFilterFileExt) % 2)
  100.     set -l dirfilter (math (math --scale 0 $directive / $shellCompDirectiveFilterDirs) % 2)
  101.     if test $filefilter -eq 1; or test $dirfilter -eq 1
  102.         __restic_debug "File extension filtering or directory filtering not supported"
  103.         # Do full file completion instead
  104.         return 1
  105.     end
  106.  
  107.     set -l nospace (math (math --scale 0 $directive / $shellCompDirectiveNoSpace) % 2)
  108.     set -l nofiles (math (math --scale 0 $directive / $shellCompDirectiveNoFileComp) % 2)
  109.  
  110.     __restic_debug "nospace: $nospace, nofiles: $nofiles"
  111.  
  112.     # If we want to prevent a space, or if file completion is NOT disabled,
  113.     # we need to count the number of valid completions.
  114.     # To do so, we will filter on prefix as the completions we have received
  115.     # may not already be filtered so as to allow fish to match on different
  116.     # criteria than the prefix.
  117.     if test $nospace -ne 0; or test $nofiles -eq 0
  118.         set -l prefix (commandline -t | string escape --style=regex)
  119.         __restic_debug "prefix: $prefix"
  120.  
  121.         set -l completions (string match -r -- "^$prefix.*" $__restic_comp_results)
  122.         set --global __restic_comp_results $completions
  123.         __restic_debug "Filtered completions are: $__restic_comp_results"
  124.  
  125.         # Important not to quote the variable for count to work
  126.         set -l numComps (count $__restic_comp_results)
  127.         __restic_debug "numComps: $numComps"
  128.  
  129.         if test $numComps -eq 1; and test $nospace -ne 0
  130.             # We must first split on \t to get rid of the descriptions to be
  131.             # able to check what the actual completion will be.
  132.             # We don't need descriptions anyway since there is only a single
  133.             # real completion which the shell will expand immediately.
  134.             set -l split (string split --max 1 \t $__restic_comp_results[1])
  135.  
  136.             # Fish won't add a space if the completion ends with any
  137.             # of the following characters: @=/:.,
  138.             set -l lastChar (string sub -s -1 -- $split)
  139.             if not string match -r -q "[@=/:.,]" -- "$lastChar"
  140.                 # In other cases, to support the "nospace" directive we trick the shell
  141.                 # by outputting an extra, longer completion.
  142.                 __restic_debug "Adding second completion to perform nospace directive"
  143.                 set --global __restic_comp_results $split[1] $split[1].
  144.                 __restic_debug "Completions are now: $__restic_comp_results"
  145.             end
  146.         end
  147.  
  148.         if test $numComps -eq 0; and test $nofiles -eq 0
  149.             # To be consistent with bash and zsh, we only trigger file
  150.             # completion when there are no other completions
  151.             __restic_debug "Requesting file completion"
  152.             return 1
  153.         end
  154.     end
  155.  
  156.     return 0
  157. end
  158.  
  159. # Since Fish completions are only loaded once the user triggers them, we trigger them ourselves
  160. # so we can properly delete any completions provided by another script.
  161. # Only do this if the program can be found, or else fish may print some errors; besides,
  162. # the existing completions will only be loaded if the program can be found.
  163. if type -q "restic"
  164.     # The space after the program name is essential to trigger completion for the program
  165.     # and not completion of the program name itself.
  166.     # Also, we use '> /dev/null 2>&1' since '&>' is not supported in older versions of fish.
  167.     complete --do-complete "restic " > /dev/null 2>&1
  168. end
  169.  
  170. # Remove any pre-existing completions for the program since we will be handling all of them.
  171. complete -c restic -e
  172.  
  173. # The call to __restic_prepare_completions will setup __restic_comp_results
  174. # which provides the program's completion choices.
  175. complete -c restic -n '__restic_prepare_completions' -f -a '$__restic_comp_results'
  176.  
  177.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement