forked from evanpurkhiser/dots
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bash_completion
186 lines (157 loc) · 5.92 KB
/
bash_completion
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#!/bin/bash
# Do completion from a passed list of paths
#
# Accepts 2 arguments
# 1. The list of paths to complete from
# 2. The current word being completed
__dots_path_comp()
{
# This forces readline to only display the last item separated by a slash
compopt -o filenames
local IFS=$'\n'
local k="${#COMPREPLY[@]}"
for path in $(compgen -W "$1" -- $2)
do
local trailing_trim
# Determine what to trim from the end
trailing_trim="${path#${2%/*}/}/"
trailing_trim="${trailing_trim#*/}"
trailing_trim="${trailing_trim%/}"
# Don't add a space if there is more to complete
[[ "$trailing_trim" != "" ]] && compopt -o nospace
# Remove the slash if mark-directories is off
if ! _rl_enabled mark-directories
then
# If The current typed path doesnt have a slash in it yet check if
# it is the full first portion of a path and ignore everything after
# if it is. We don't have to do this once the typed path has a slash
# in it as the logic above will pick up on it
[[ "$2" != */* && "$path" == ${2}/* ]] && path="$2/$trailing_trim"
trailing_trim="/$trailing_trim"
fi
COMPREPLY[k++]="${path%%${trailing_trim}}"
done
}
# Executes a dot command and caches the output. The cache will be invalidated
# when the source directory has a file modified after the cache date. The cached
# variable name will be the passed arguments concatenated with underscores and
# all non alpha-numeric characters replaced with underscores, then prefixed
# with '__dots_cache'.
#
# Accepts a variable number of arguments
__dots_cache() {
# Get the last updated time of the source config files
local source_path="$HOME/.local/etc"
if [[ "$OSTYPE" == "darwin"* ]]
then
local last_update="$(find "$source_path" \
-path "$source_path/.git" -prune -o \
-type f -exec stat -f'%m' {} + | sort -n | tail -1)"
else
local last_update="$(find "$source_path" \
-path "$source_path/.git" -prune -o \
-type f -printf '%T@\n' | sort -n | tail -1)"
fi
# Get the name of the cached variables
local parameters="$@"
local variable_name="__dots_cache_${parameters//[^a-zA-Z0-9_]/_}"
local cache_ts_name="${variable_name}_ts"
# Cache the command output if not cached or expired
if [[ -z ${!cache_ts_name} || ((${!cache_ts_name} < $last_update)) ]]
then
# Update the cache and timestamp variables
eval "$cache_ts_name=$(date +%s)"
eval "$variable_name=\"\$(dots \$parameters)\""
fi
}
_dots_completions()
{
local base_cmds=(groups diff files install help)
local base_flags=(-c --config)
local cur=${COMP_WORDS[$COMP_CWORD]}
local prev=${COMP_WORDS[$COMP_CWORD-1]}
# Determine the command position
local cmd_index=1
[[ ${COMP_WORDS[1]} =~ -c|--config ]] && cmd_index=3
# Include additional flags for the first word
if [[ $COMP_CWORD == 1 ]]
then
COMPREPLY=( $(compgen -W "${base_cmds[*]} ${base_flags[*]}" -- "$cur") )
return
fi
# Perform file completion for the config option
if [[ $cmd_index > $COMP_CWORD ]]
then
compopt -o default
return
fi
# Perform completion on the base command
if [[ $COMP_CWORD == $cmd_index ]]
then
COMPREPLY=( $(compgen -W "${base_cmds[*]}" -- "$cur") )
return
fi
# Sub command index
local cmd2_index=$(( cmd_index + 1 ))
# Perform completion for sub-commands
case "${COMP_WORDS[$cmd_index]}" in
groups)
# Complete group sub commands
if [[ $COMP_CWORD == $cmd2_index ]]
then
COMPREPLY=( $(compgen -W "known current clear set add del" -- "$cur") )
# Complete group set and group add command
elif [[ $COMP_CWORD > $cmd2_index && ( "${COMP_WORDS[$cmd2_index]}" == "set" || "${COMP_WORDS[$cmd2_index]}" == "add" )]]
then
__dots_cache groups known
__dots_path_comp "$__dots_cache_groups_known" "$cur"
# Complete group del command
elif [[ $COMP_CWORD > $cmd2_index && "${COMP_WORDS[$cmd2_index]}" == "del" ]]
then
__dots_cache groups current
__dots_path_comp "$__dots_cache_groups_current" "$cur"
fi
;;
diff)
# Do git diff completion
if [[ "$cur" == --* ]]
then
local git_comp_file="/usr/share/bash-completion/completions/git"
# Load in the git completion file if nessicary
if [[ -z "$__git_diff_common_options" && -e "$git_comp_file" ]]
then
source "$git_comp_file"
fi
# If we were able to load it do completion with common options
if [[ -n "$__git_diff_common_options" ]]
then
COMPREPLY=( $(compgen -W "$__git_diff_common_options" -- "$cur") )
fi
# Do config file path completion
else
__dots_cache files
__dots_path_comp "$__dots_cache_files" "$cur"
fi
;;
files)
__dots_cache files
__dots_path_comp "$__dots_cache_files" "$cur"
;;
install)
# Complete location
if [[ "$prev" =~ -l|--location ]]
then
compopt -o default
# Complete location flag
elif [[ $cur == -* ]]
then
COMPREPLY=( $(compgen -W "-l --location -r --reinstal" -- "$cur") )
# Complete configuration file paths
else
__dots_cache files
__dots_path_comp "$__dots_cache_files" "$cur"
fi
;;
esac
}
complete -F _dots_completions dots