rubish-gem 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.dockerignore +23 -0
- data/Dockerfile +54 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +12 -0
- data/lib/rubish/arithmetic.rb +140 -0
- data/lib/rubish/ast.rb +168 -0
- data/lib/rubish/builtins/arithmetic.rb +129 -0
- data/lib/rubish/builtins/bind_readline.rb +834 -0
- data/lib/rubish/builtins/directory_stack.rb +182 -0
- data/lib/rubish/builtins/echo_printf.rb +510 -0
- data/lib/rubish/builtins/hash_directories.rb +260 -0
- data/lib/rubish/builtins/read.rb +299 -0
- data/lib/rubish/builtins/trap.rb +324 -0
- data/lib/rubish/codegen.rb +1273 -0
- data/lib/rubish/completion.rb +840 -0
- data/lib/rubish/completions/bash_helpers.rb +530 -0
- data/lib/rubish/completions/git.rb +431 -0
- data/lib/rubish/completions/help_parser.rb +453 -0
- data/lib/rubish/completions/ssh.rb +114 -0
- data/lib/rubish/config.rb +267 -0
- data/lib/rubish/data/builtin_help.rb +716 -0
- data/lib/rubish/data/completion_data.rb +53 -0
- data/lib/rubish/data/readline_config.rb +47 -0
- data/lib/rubish/data/shell_options.rb +251 -0
- data/lib/rubish/data_define.rb +65 -0
- data/lib/rubish/execution_context.rb +1124 -0
- data/lib/rubish/expansion.rb +988 -0
- data/lib/rubish/history.rb +663 -0
- data/lib/rubish/lazy_loader.rb +127 -0
- data/lib/rubish/lexer.rb +1194 -0
- data/lib/rubish/parser.rb +1167 -0
- data/lib/rubish/prompt.rb +766 -0
- data/lib/rubish/repl.rb +2267 -0
- data/lib/rubish/runtime/builtins.rb +7222 -0
- data/lib/rubish/runtime/command.rb +1153 -0
- data/lib/rubish/runtime/job.rb +153 -0
- data/lib/rubish/runtime.rb +1169 -0
- data/lib/rubish/shell_state.rb +241 -0
- data/lib/rubish/startup_profiler.rb +67 -0
- data/lib/rubish/version.rb +5 -0
- data/lib/rubish.rb +60 -0
- data/sig/rubish.rbs +4 -0
- metadata +85 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rubish
|
|
4
|
+
module Builtins
|
|
5
|
+
# ==========================================================================
|
|
6
|
+
# Git completion function
|
|
7
|
+
# ==========================================================================
|
|
8
|
+
|
|
9
|
+
def _git_completion(cmd, cur, prev)
|
|
10
|
+
words = @comp_words
|
|
11
|
+
cword = @comp_cword
|
|
12
|
+
|
|
13
|
+
# Determine git subcommand
|
|
14
|
+
subcommand = nil
|
|
15
|
+
subcommand_idx = nil
|
|
16
|
+
words.each_with_index do |word, idx|
|
|
17
|
+
next if idx == 0 # Skip 'git'
|
|
18
|
+
next if word.start_with?('-') # Skip options
|
|
19
|
+
|
|
20
|
+
# Found subcommand
|
|
21
|
+
subcommand = word
|
|
22
|
+
subcommand_idx = idx
|
|
23
|
+
break
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if subcommand.nil? || cword <= (subcommand_idx || 1)
|
|
27
|
+
# Complete git subcommands or top-level options
|
|
28
|
+
if cur.start_with?('-')
|
|
29
|
+
@compreply = GIT_COMMON_OPTIONS.select { |opt| opt.start_with?(cur) }
|
|
30
|
+
else
|
|
31
|
+
@compreply = GIT_COMMANDS.select { |c| c.start_with?(cur) }
|
|
32
|
+
end
|
|
33
|
+
return
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Complete based on subcommand
|
|
37
|
+
case subcommand
|
|
38
|
+
when 'add'
|
|
39
|
+
_git_complete_add(cur, prev)
|
|
40
|
+
when 'branch'
|
|
41
|
+
_git_complete_branch(cur, prev)
|
|
42
|
+
when 'checkout', 'switch'
|
|
43
|
+
_git_complete_checkout(cur, prev)
|
|
44
|
+
when 'commit'
|
|
45
|
+
_git_complete_commit(cur, prev)
|
|
46
|
+
when 'diff'
|
|
47
|
+
_git_complete_diff(cur, prev)
|
|
48
|
+
when 'fetch', 'pull', 'push'
|
|
49
|
+
_git_complete_remote_branch(cur, prev, subcommand)
|
|
50
|
+
when 'log', 'show'
|
|
51
|
+
_git_complete_log(cur, prev)
|
|
52
|
+
when 'merge', 'rebase'
|
|
53
|
+
_git_complete_refs(cur)
|
|
54
|
+
when 'remote'
|
|
55
|
+
_git_complete_remote(cur, prev, words, cword, subcommand_idx)
|
|
56
|
+
when 'reset'
|
|
57
|
+
_git_complete_reset(cur, prev)
|
|
58
|
+
when 'revert'
|
|
59
|
+
_git_complete_refs(cur)
|
|
60
|
+
when 'stash'
|
|
61
|
+
_git_complete_stash(cur, prev, words, cword, subcommand_idx)
|
|
62
|
+
when 'tag'
|
|
63
|
+
_git_complete_tag(cur, prev)
|
|
64
|
+
else
|
|
65
|
+
# Default: complete files and refs
|
|
66
|
+
_git_complete_refs(cur)
|
|
67
|
+
_git_complete_files(cur)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def _git_complete_add(cur, prev)
|
|
72
|
+
case prev
|
|
73
|
+
when '-p', '--patch'
|
|
74
|
+
_git_complete_files(cur)
|
|
75
|
+
else
|
|
76
|
+
if cur.start_with?('-')
|
|
77
|
+
opts = %w[-n --dry-run -v --verbose -i --interactive -p --patch
|
|
78
|
+
-e --edit -f --force -u --update -A --all --no-ignore-removal
|
|
79
|
+
--no-all --ignore-removal -N --intent-to-add --refresh
|
|
80
|
+
--ignore-errors --ignore-missing --sparse --pathspec-from-file=
|
|
81
|
+
--pathspec-file-nul --renormalize --chmod=+x --chmod=-x]
|
|
82
|
+
@compreply = opts.select { |opt| opt.start_with?(cur) }
|
|
83
|
+
else
|
|
84
|
+
_git_complete_files(cur)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def _git_complete_branch(cur, prev)
|
|
90
|
+
case prev
|
|
91
|
+
when '-d', '-D', '--delete', '-m', '-M', '--move', '-c', '-C', '--copy'
|
|
92
|
+
_git_complete_local_branches(cur)
|
|
93
|
+
when '-u', '--set-upstream-to'
|
|
94
|
+
_git_complete_remote_refs(cur)
|
|
95
|
+
when '-t', '--track'
|
|
96
|
+
_git_complete_remote_refs(cur)
|
|
97
|
+
else
|
|
98
|
+
if cur.start_with?('-')
|
|
99
|
+
opts = %w[-a --all -d -D --delete -f --force -i --ignore-case -l --list
|
|
100
|
+
-m -M --move -c -C --copy -r --remotes --show-current -v --verbose
|
|
101
|
+
-q --quiet --track -t --no-track --set-upstream-to -u --unset-upstream
|
|
102
|
+
--edit-description --contains --no-contains --merged --no-merged
|
|
103
|
+
--column --no-column --sort= --points-at --format= --color --no-color]
|
|
104
|
+
@compreply = opts.select { |opt| opt.start_with?(cur) }
|
|
105
|
+
else
|
|
106
|
+
_git_complete_local_branches(cur)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def _git_complete_checkout(cur, prev)
|
|
112
|
+
case prev
|
|
113
|
+
when '-b', '-B', '--orphan'
|
|
114
|
+
# New branch name - don't complete
|
|
115
|
+
@compreply = []
|
|
116
|
+
when '--'
|
|
117
|
+
_git_complete_files(cur)
|
|
118
|
+
else
|
|
119
|
+
if cur.start_with?('-')
|
|
120
|
+
opts = %w[-q --quiet -f --force -b -B --detach --ours --theirs
|
|
121
|
+
-m --merge -l --track -t --no-track --orphan --ignore-other-worktrees
|
|
122
|
+
--recurse-submodules --no-recurse-submodules --progress --no-progress
|
|
123
|
+
--overlay --no-overlay --pathspec-from-file= --pathspec-file-nul]
|
|
124
|
+
@compreply = opts.select { |opt| opt.start_with?(cur) }
|
|
125
|
+
else
|
|
126
|
+
_git_complete_refs(cur)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def _git_complete_commit(cur, prev)
|
|
132
|
+
case prev
|
|
133
|
+
when '-C', '-c', '--reuse-message', '--reedit-message', '--fixup', '--squash'
|
|
134
|
+
_git_complete_refs(cur)
|
|
135
|
+
when '-m', '--message'
|
|
136
|
+
@compreply = [] # Message string
|
|
137
|
+
when '-F', '--file', '--pathspec-from-file'
|
|
138
|
+
_git_complete_files(cur)
|
|
139
|
+
when '--author'
|
|
140
|
+
@compreply = [] # Author string
|
|
141
|
+
when '--date'
|
|
142
|
+
@compreply = [] # Date string
|
|
143
|
+
when '--cleanup'
|
|
144
|
+
@compreply = %w[strip whitespace verbatim scissors default].select { |opt| opt.start_with?(cur) }
|
|
145
|
+
else
|
|
146
|
+
if cur.start_with?('-')
|
|
147
|
+
opts = %w[-a --all -p --patch --reset-author -s --signoff -n --no-verify
|
|
148
|
+
-v --verbose -u --untracked-files -q --quiet --dry-run
|
|
149
|
+
--short --branch --porcelain --long -z --null --status
|
|
150
|
+
--no-status -F --file -m --message --author --date
|
|
151
|
+
-C --reuse-message -c --reedit-message --fixup --squash
|
|
152
|
+
--amend --no-edit -e --edit --cleanup= --trailer
|
|
153
|
+
--only -i --include --allow-empty --allow-empty-message]
|
|
154
|
+
@compreply = opts.select { |opt| opt.start_with?(cur) }
|
|
155
|
+
else
|
|
156
|
+
_git_complete_files(cur)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def _git_complete_diff(cur, prev)
|
|
162
|
+
if cur.start_with?('-')
|
|
163
|
+
opts = %w[-p -u --patch -U --unified= --raw --patch-with-raw --stat
|
|
164
|
+
--numstat --shortstat --dirstat --summary --patch-with-stat
|
|
165
|
+
-z --name-only --name-status --color --no-color --color-moved
|
|
166
|
+
--word-diff --color-words --no-renames --check --full-index
|
|
167
|
+
--binary -a --text -R --ignore-space-change -w
|
|
168
|
+
--ignore-all-space -b --ignore-blank-lines --inter-hunk-context=
|
|
169
|
+
--patience --histogram --diff-algorithm= --anchored=
|
|
170
|
+
--minimal --no-index --cached --staged -S -G --pickaxe-regex]
|
|
171
|
+
@compreply = opts.select { |opt| opt.start_with?(cur) }
|
|
172
|
+
else
|
|
173
|
+
_git_complete_refs(cur)
|
|
174
|
+
_git_complete_files(cur)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def _git_complete_remote_branch(cur, prev, subcommand)
|
|
179
|
+
if cur.start_with?('-')
|
|
180
|
+
case subcommand
|
|
181
|
+
when 'fetch'
|
|
182
|
+
opts = %w[-q --quiet -v --verbose --all -a --append --depth= --deepen=
|
|
183
|
+
--shallow-since= --shallow-exclude= --unshallow --update-shallow
|
|
184
|
+
--dry-run -f --force -k --keep -p --prune -n --no-tags -t --tags
|
|
185
|
+
--refmap= -u --update-head-ok --progress --no-progress -j --jobs=
|
|
186
|
+
--prefetch --set-upstream -o --server-option= --upload-pack]
|
|
187
|
+
when 'pull'
|
|
188
|
+
opts = %w[-q --quiet -v --verbose --rebase -r --no-rebase --ff-only
|
|
189
|
+
--no-ff --ff --no-commit --commit --no-stat --stat
|
|
190
|
+
--no-signoff --signoff --no-log --log --squash --no-squash
|
|
191
|
+
--strategy= -X --strategy-option= --depth= -s --strategy=
|
|
192
|
+
--allow-unrelated-histories --autostash --no-autostash]
|
|
193
|
+
when 'push'
|
|
194
|
+
opts = %w[-q --quiet -v --verbose --all --mirror --tags --follow-tags
|
|
195
|
+
-n --dry-run --porcelain --delete --prune -u --set-upstream
|
|
196
|
+
--thin --no-thin --force -f --force-with-lease --repo
|
|
197
|
+
--no-verify --progress --signed= --push-option= --atomic
|
|
198
|
+
-d --delete --receive-pack= --exec= -o --push-option=]
|
|
199
|
+
else
|
|
200
|
+
opts = []
|
|
201
|
+
end
|
|
202
|
+
@compreply = opts.select { |opt| opt.start_with?(cur) }
|
|
203
|
+
else
|
|
204
|
+
_git_complete_remotes(cur)
|
|
205
|
+
_git_complete_refs(cur)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def _git_complete_log(cur, prev)
|
|
210
|
+
if cur.start_with?('-')
|
|
211
|
+
opts = %w[--follow -p --patch --stat --shortstat --numstat --summary
|
|
212
|
+
--name-only --name-status --pretty= --format= --abbrev-commit
|
|
213
|
+
--oneline --graph --decorate --no-decorate --all --branches
|
|
214
|
+
--remotes --tags --source --merges --no-merges --first-parent
|
|
215
|
+
--author= --committer= --grep= --all-match --invert-grep
|
|
216
|
+
--regexp-ignore-case --since= --after= --until= --before=
|
|
217
|
+
--ancestry-path --cherry-pick --left-right --reverse
|
|
218
|
+
-n --max-count= --skip= -S -G --pickaxe-regex --walk-reflogs
|
|
219
|
+
--merge --boundary --simplify-merges --date= --date-order
|
|
220
|
+
--author-date-order --topo-order --full-history]
|
|
221
|
+
@compreply = opts.select { |opt| opt.start_with?(cur) }
|
|
222
|
+
else
|
|
223
|
+
_git_complete_refs(cur)
|
|
224
|
+
_git_complete_files(cur)
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def _git_complete_remote(cur, prev, words, cword, subcommand_idx)
|
|
229
|
+
# Determine remote subcommand
|
|
230
|
+
remote_subcmd = nil
|
|
231
|
+
words[(subcommand_idx + 1)..].each do |word|
|
|
232
|
+
next if word.start_with?('-')
|
|
233
|
+
next if word.empty? # Skip empty words
|
|
234
|
+
remote_subcmd = word
|
|
235
|
+
break
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
if remote_subcmd.nil? || remote_subcmd.empty?
|
|
239
|
+
# Complete remote subcommands
|
|
240
|
+
remote_cmds = %w[add rename remove rm show prune update get-url set-url set-head set-branches]
|
|
241
|
+
@compreply = remote_cmds.select { |c| c.start_with?(cur) }
|
|
242
|
+
return
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
case remote_subcmd
|
|
246
|
+
when 'add'
|
|
247
|
+
if cur.start_with?('-')
|
|
248
|
+
opts = %w[-t --track -m --master -f --fetch --tags --no-tags --mirror=]
|
|
249
|
+
@compreply = opts.select { |opt| opt.start_with?(cur) }
|
|
250
|
+
end
|
|
251
|
+
when 'rename', 'remove', 'rm', 'show', 'prune', 'get-url', 'set-url', 'set-head', 'set-branches'
|
|
252
|
+
_git_complete_remotes(cur)
|
|
253
|
+
when 'update'
|
|
254
|
+
if cur.start_with?('-')
|
|
255
|
+
@compreply = %w[-p --prune].select { |opt| opt.start_with?(cur) }
|
|
256
|
+
else
|
|
257
|
+
# Complete remote groups or remotes
|
|
258
|
+
_git_complete_remotes(cur)
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def _git_complete_reset(cur, prev)
|
|
264
|
+
if cur.start_with?('-')
|
|
265
|
+
opts = %w[-q --quiet --soft --mixed --hard --merge --keep -p --patch -N
|
|
266
|
+
--intent-to-add --pathspec-from-file= --pathspec-file-nul]
|
|
267
|
+
@compreply = opts.select { |opt| opt.start_with?(cur) }
|
|
268
|
+
else
|
|
269
|
+
_git_complete_refs(cur)
|
|
270
|
+
_git_complete_files(cur)
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def _git_complete_stash(cur, prev, words, cword, subcommand_idx)
|
|
275
|
+
# Determine stash subcommand
|
|
276
|
+
stash_subcmd = nil
|
|
277
|
+
words[(subcommand_idx + 1)..].each do |word|
|
|
278
|
+
next if word.start_with?('-')
|
|
279
|
+
next if word.empty? # Skip empty words
|
|
280
|
+
stash_subcmd = word
|
|
281
|
+
break
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
if stash_subcmd.nil? || stash_subcmd.empty?
|
|
285
|
+
stash_cmds = %w[list show drop pop apply branch push save clear create store]
|
|
286
|
+
@compreply = stash_cmds.select { |c| c.start_with?(cur) }
|
|
287
|
+
return
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
case stash_subcmd
|
|
291
|
+
when 'show', 'drop', 'pop', 'apply', 'branch'
|
|
292
|
+
_git_complete_stash_refs(cur)
|
|
293
|
+
when 'push', 'save'
|
|
294
|
+
if cur.start_with?('-')
|
|
295
|
+
opts = %w[-p --patch -k --keep-index --no-keep-index -q --quiet
|
|
296
|
+
-u --include-untracked -a --all -m --message --pathspec-from-file=]
|
|
297
|
+
@compreply = opts.select { |opt| opt.start_with?(cur) }
|
|
298
|
+
else
|
|
299
|
+
_git_complete_files(cur)
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def _git_complete_tag(cur, prev)
|
|
305
|
+
case prev
|
|
306
|
+
when '-m', '--message', '-F', '--file'
|
|
307
|
+
@compreply = [] # Message or file
|
|
308
|
+
when '-u', '--local-user'
|
|
309
|
+
@compreply = [] # GPG key
|
|
310
|
+
else
|
|
311
|
+
if cur.start_with?('-')
|
|
312
|
+
opts = %w[-a --annotate -s --sign -u --local-user -f --force -d --delete
|
|
313
|
+
-v --verify -n --n= -l --list --sort= --contains --no-contains
|
|
314
|
+
--merged --no-merged --points-at --format= --color --no-color
|
|
315
|
+
-i --ignore-case -m --message -F --file --cleanup=]
|
|
316
|
+
@compreply = opts.select { |opt| opt.start_with?(cur) }
|
|
317
|
+
else
|
|
318
|
+
_git_complete_tags(cur)
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# Helper methods for git completion
|
|
324
|
+
|
|
325
|
+
def _git_complete_refs(cur)
|
|
326
|
+
# Complete git refs (branches, tags, commits)
|
|
327
|
+
@compreply ||= []
|
|
328
|
+
return unless git_repo?
|
|
329
|
+
|
|
330
|
+
begin
|
|
331
|
+
# Get all refs
|
|
332
|
+
refs = `git for-each-ref --format='%(refname:short)' 2>/dev/null`.split("\n")
|
|
333
|
+
refs.concat(`git rev-parse --symbolic --branches --tags --remotes 2>/dev/null`.split("\n"))
|
|
334
|
+
refs.uniq!
|
|
335
|
+
@compreply.concat(refs.select { |r| r.start_with?(cur) })
|
|
336
|
+
rescue
|
|
337
|
+
# Git command failed
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
def _git_complete_local_branches(cur)
|
|
342
|
+
@compreply = []
|
|
343
|
+
return unless git_repo?
|
|
344
|
+
|
|
345
|
+
begin
|
|
346
|
+
branches = `git for-each-ref --format='%(refname:short)' refs/heads/ 2>/dev/null`.split("\n")
|
|
347
|
+
@compreply = branches.select { |b| b.start_with?(cur) }
|
|
348
|
+
rescue
|
|
349
|
+
# Git command failed
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
def _git_complete_remote_refs(cur)
|
|
354
|
+
@compreply = []
|
|
355
|
+
return unless git_repo?
|
|
356
|
+
|
|
357
|
+
begin
|
|
358
|
+
refs = `git for-each-ref --format='%(refname:short)' refs/remotes/ 2>/dev/null`.split("\n")
|
|
359
|
+
@compreply = refs.select { |r| r.start_with?(cur) }
|
|
360
|
+
rescue
|
|
361
|
+
# Git command failed
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
def _git_complete_remotes(cur)
|
|
366
|
+
@compreply ||= []
|
|
367
|
+
return unless git_repo?
|
|
368
|
+
|
|
369
|
+
begin
|
|
370
|
+
remotes = `git remote 2>/dev/null`.split("\n")
|
|
371
|
+
@compreply.concat(remotes.select { |r| r.start_with?(cur) })
|
|
372
|
+
rescue
|
|
373
|
+
# Git command failed
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
def _git_complete_tags(cur)
|
|
378
|
+
@compreply ||= []
|
|
379
|
+
return unless git_repo?
|
|
380
|
+
|
|
381
|
+
begin
|
|
382
|
+
tags = `git tag -l 2>/dev/null`.split("\n")
|
|
383
|
+
@compreply.concat(tags.select { |t| t.start_with?(cur) })
|
|
384
|
+
rescue
|
|
385
|
+
# Git command failed
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
def _git_complete_stash_refs(cur)
|
|
390
|
+
@compreply = []
|
|
391
|
+
return unless git_repo?
|
|
392
|
+
|
|
393
|
+
begin
|
|
394
|
+
stashes = `git stash list 2>/dev/null`.each_line.map { |l| l.split(':').first }.compact
|
|
395
|
+
@compreply = stashes.select { |s| s.start_with?(cur) }
|
|
396
|
+
rescue
|
|
397
|
+
# Git command failed
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
def _git_complete_files(cur)
|
|
402
|
+
@compreply ||= []
|
|
403
|
+
|
|
404
|
+
# Get modified/untracked files for git commands
|
|
405
|
+
if git_repo?
|
|
406
|
+
begin
|
|
407
|
+
# Modified files
|
|
408
|
+
modified = `git diff --name-only 2>/dev/null`.split("\n")
|
|
409
|
+
# Staged files
|
|
410
|
+
staged = `git diff --cached --name-only 2>/dev/null`.split("\n")
|
|
411
|
+
# Untracked files
|
|
412
|
+
untracked = `git ls-files --others --exclude-standard 2>/dev/null`.split("\n")
|
|
413
|
+
|
|
414
|
+
files = (modified + staged + untracked).uniq
|
|
415
|
+
@compreply.concat(files.select { |f| f.start_with?(cur) })
|
|
416
|
+
rescue
|
|
417
|
+
# Git command failed, fall back to regular file completion
|
|
418
|
+
end
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
# Also complete regular files
|
|
422
|
+
pattern = cur.empty? ? '*' : "#{cur}*"
|
|
423
|
+
@compreply.concat(Dir.glob(pattern).select { |f| File.file?(f) || File.directory?(f) })
|
|
424
|
+
@compreply.uniq!
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
def git_repo?
|
|
428
|
+
system('git rev-parse --git-dir >/dev/null 2>&1')
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
end
|