-
Notifications
You must be signed in to change notification settings - Fork 19
/
completion-gem
141 lines (129 loc) · 4.42 KB
/
completion-gem
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#! bash
# bash completion for the `gem` command.
#
# Copyright (c) 2009-2021 Daniel Luz <dev dot gsz at mernen dot com>.
# Distributed under the MIT license.
# https://mernen.com/projects/completion-ruby
#
# To use, source this file on bash:
# . completion-gem
__gem() {
local gem_bin=("${_RUBY_COMMAND_PREFIX[@]}" "$1")
local cur=$2
local prev=$3
COMPREPLY=()
local gem_command
__gem_get_command
[[ $gem_command = i ]] && gem_command=install
# Can't do anything with non-commands
[[ $gem_command = - ]] && return
if [[ $prev = --config-file ]]; then
# Leave COMPREPLY blank, let the default handle it
return
elif [[ $prev = --*dir || ${COMP_WORDS[$COMP_CWORD]} = --*dir=* ]]; then
# Assume any option ending in 'dir' takes a directory name
type -t _filedir >/dev/null && _filedir -d
return
fi
local choices
if [[ $cur = -* ]]; then
case $gem_command in
"")
choices="-h --help -v --version";;
*)
choices=$(__gem_command_options "$gem_command")
esac
else
case $gem_command in
"")
choices=$(__gem_available_commands);;
help)
choices="commands examples platforms $(__gem_available_commands)";;
build)
if type -t _filedir >/dev/null; then
if [[ $prev = -C ]]; then
_filedir -d
else
_filedir gemspec
fi
fi
return;;
install)
if type -t _filedir >/dev/null; then
if [[ $prev = -i || $prev = -n || $prev = --build-root || ${COMP_WORDS[$COMP_CWORD]} = --build-root=* ]]; then
_filedir -d
else
_filedir gem
fi
fi
return;;
uninstall | cleanup)
choices=$(__gem_installed_gems);;
push | unpack)
type -t _filedir >/dev/null && _filedir gem
return;;
esac
fi
COMPREPLY=($(compgen -W "$choices" -- "$cur"))
}
# Stores in $gem_command the name of the gem command currently in use.
# If no command is found, the variable is not set.
__gem_get_command() {
local i
for ((i=1; i < $COMP_CWORD; ++i)); do
local arg=${COMP_WORDS[$i]}
case $arg in
-h | --help | -v | --version | --)
# These options are command-killers
gem_command=-
return;;
--config-file)
# Skip argument
((++i));;
[^-]*)
gem_command=$arg
# Keep scanning; if a "--" is found, treat the command as finished
for ((++i; i < $COMP_CWORD; ++i)); do
if [[ ${COMP_WORDS[$i]} = -- ]]; then
gem_command=-
return
fi
done
return;;
esac
done
}
# Outputs a list of installed gems, one per line.
__gem_installed_gems() {
"${gem_bin[@]}" list --local --no-details 2>/dev/null | awk '/^[^ ]+ \(/ { print $1 }'
}
# Outputs a list of available commands, one per line.
__gem_available_commands() {
"${gem_bin[@]}" help commands 2>/dev/null | awk '/^ [^ ]/ { print $1 }'
}
# Performs `gem help $1`, scans output for options, emits them one per line.
__gem_command_options() {
# gem help output starts option sections with a header like
# " Common Options:", followed by lines indented with at least
# four spaces, one or more forms for the same option, a couple
# alignment spaces, and a description.
# We assume a header that doesn't mention "Options" denotes the
# end of the list of options.
# Also, some options come with optional parts, like "--[no-]ri";
# we first emit the version with these parts included, then omit
# them.
"${gem_bin[@]}" help "$1" 2>/dev/null |
ruby -ne '
if /^ (\S.*):/
exit unless $1.include? "Options"
elsif /^ {4,}((?:-[-\w\[\],]+ )+)/
$1.gsub(",", " ").split.each do |opt|
# Print option with optional parts
puts opt.gsub(/[\[\]]/, "")
# Print also version w/o optionals if available
opt.gsub!(/\[[^\]]+\]/, "") and puts opt
end
end' 2>/dev/null
}
complete -F __gem -o bashdefault -o default gem gem1.{8..9} gem2.{0..7} gem3.{0..3} jgem
# vim: ai ft=sh sw=4 sts=4 et