github.com/coreos/rocket@v1.30.1-0.20200224141603-171c416fac02/rkt/completion.go (about) 1 // Copyright 2017 The rkt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "io" 19 "os" 20 21 "github.com/spf13/cobra" 22 ) 23 24 var ( 25 cmdCompletion = &cobra.Command{ 26 Use: "completion SHELL", 27 Short: "Output shell completion code for the specified shell", 28 Long: `This command outputs completion code for the specified shell. The generated 29 code must be evaluated to provide interactive completion of rkt sub-commands. 30 This can be done by sourcing it from the .bash_profile. 31 32 Save completion code in a home directory and then include it in .bash_profile 33 script: 34 35 $ rkt completion bash > $HOME/.rkt.bash.inc 36 $ printf ' 37 # rkt shell completion 38 source "$HOME/.rkt.bash.inc" 39 ' >> $HOME/.bash_profile 40 $ source $HOME/.bash_profile 41 42 Alternatively, include the completion code directly into the launched shell: 43 44 $ source <(rkt completion bash)`, 45 ValidArgs: []string{"bash"}, 46 Run: runWrapper(newCompletion(os.Stdout)), 47 } 48 49 bashCompletionFunc = `__rkt_parse_image() 50 { 51 local rkt_output 52 if rkt_output=$(rkt image list --no-legend 2>/dev/null); then 53 out=($(echo "${rkt_output}" | awk '{print $1}')) 54 COMPREPLY=( $( compgen -W "${out[*]}" -- "$cur" ) ) 55 fi 56 } 57 58 __rkt_parse_list() 59 { 60 local rkt_output 61 if rkt_output=$(rkt list --no-legend 2>/dev/null); then 62 if [[ -n "$1" ]]; then 63 out=($(echo "${rkt_output}" | grep ${1} | awk '{print $1}')) 64 else 65 out=($(echo "${rkt_output}" | awk '{print $1}')) 66 fi 67 COMPREPLY=( $( compgen -W "${out[*]}" -- "$cur" ) ) 68 fi 69 } 70 71 __custom_func() { 72 case ${last_command} in 73 rkt_image_export | \ 74 rkt_image_extract | \ 75 rkt_image_cat-manifest | \ 76 rkt_image_render | \ 77 rkt_image_rm | \ 78 rkt_run | \ 79 rkt_prepare) 80 __rkt_parse_image 81 return 82 ;; 83 rkt_run-prepared) 84 __rkt_parse_list prepared 85 return 86 ;; 87 rkt_enter) 88 __rkt_parse_list running 89 return 90 ;; 91 rkt_rm) 92 __rkt_parse_list "prepare\|exited" 93 return 94 ;; 95 rkt_status) 96 __rkt_parse_list 97 return 98 ;; 99 *) 100 ;; 101 esac 102 } 103 ` 104 105 completionShells = map[string]func(io.Writer, *cobra.Command) error{ 106 "bash": runBashCompletion, 107 } 108 ) 109 110 func init() { 111 cmdRkt.AddCommand(cmdCompletion) 112 } 113 114 // newCompletion creates a new command with a bounded writer. Writer 115 // is used to print the generated shell-completion script, which is 116 // intended to be consumed by the CLI users. 117 func newCompletion(w io.Writer) func(*cobra.Command, []string) int { 118 return func(cmd *cobra.Command, args []string) int { 119 return runCompletion(w, cmd, args) 120 } 121 } 122 123 // runCompletion is a command handler to generate the shell script with 124 // shell completion functions. 125 // 126 // It ensures that there are enough arguments to generate the completion 127 // scripts. 128 func runCompletion(w io.Writer, cmd *cobra.Command, args []string) (exit int) { 129 if len(args) == 0 { 130 stderr.Print("shell type is not specified") 131 return 254 132 } 133 134 if len(args) > 1 { 135 stderr.Print("too many arguments, only shell type is expected") 136 return 254 137 } 138 139 // Right now only bash completion is supported, but zsh could be 140 // supported in a future as well. 141 completion, ok := completionShells[args[0]] 142 if !ok { 143 stderr.Printf("'%s' shell is not supported", args[0]) 144 return 254 145 } 146 147 // Write the shell completion to the specified writer. 148 err := completion(w, cmd.Parent()) 149 if err != nil { 150 stderr.PrintE("completion failed", err) 151 return 254 152 } 153 154 return 0 155 } 156 157 // runBashCompletion generates bash completion script by delegating 158 // this responsibility to the cobra package itself. 159 func runBashCompletion(out io.Writer, cmd *cobra.Command) error { 160 return cmd.GenBashCompletion(out) 161 }