13
# *) .git/remotes file names
14
# *) git 'subcommands'
15
# *) tree paths within 'ref:path/to/file' expressions
16
+# *) file paths within current working directory and index
17
# *) common --long-options
18
#
19
# To use these routines:
234
COMPREPLY=($(compgen -P "${2-}" -S "${4- }" -W "$1" -- "${3-$cur}"))
235
}
236
237
+# Generates completion reply with compgen from newline-separated possible
238
+# completion filenames.
239
+# It accepts 1 to 3 arguments:
240
+# 1: List of possible completion filenames, separated by a single newline.
241
+# 2: A directory prefix to be added to each possible completion filename
242
+# (optional).
243
+# 3: Generate possible completion matches for this word (optional).
244
+__gitcomp_file ()
245
+{
246
+ local IFS=$'\n'
247
+
248
+ # XXX does not work when the directory prefix contains a tilde,
249
+ # since tilde expansion is not applied.
250
+ # This means that COMPREPLY will be empty and Bash default
251
+ # completion will be used.
252
+ COMPREPLY=($(compgen -P "${2-}" -W "$1" -- "${3-$cur}"))
253
+
254
+ # Tell Bash that compspec generates filenames.
255
+ compopt -o filenames 2>/dev/null
256
+}
257
+
258
+__git_index_file_list_filter_compat ()
259
+{
260
+ local path
261
+
262
+ while read -r path; do
263
+ case "$path" in
264
+ ?*/*) echo "${path%%/*}/" ;;
265
+ *) echo "$path" ;;
266
+ esac
267
+ done
268
+}
269
+
270
+__git_index_file_list_filter_bash ()
271
+{
272
+ local path
273
+
274
+ while read -r path; do
275
+ case "$path" in
276
+ ?*/*)
277
+ # XXX if we append a slash to directory names when using
278
+ # `compopt -o filenames`, Bash will append another slash.
279
+ # This is pretty stupid, and this the reason why we have to
280
+ # define a compatible version for this function.
281
+ echo "${path%%/*}" ;;
282
+ *)
283
+ echo "$path" ;;
284
+ esac
285
+ done
286
+}
287
+
288
+# Process path list returned by "ls-files" and "diff-index --name-only"
289
+# commands, in order to list only file names relative to a specified
290
+# directory, and append a slash to directory names.
291
+__git_index_file_list_filter ()
292
+{
293
+ # Default to Bash >= 4.x
294
+ __git_index_file_list_filter_bash
295
+}
296
+
297
+# Execute git ls-files, returning paths relative to the directory
298
+# specified in the first argument, and using the options specified in
299
+# the second argument.
300
+__git_ls_files_helper ()
301
+{
302
+ # NOTE: $2 is not quoted in order to support multiple options
303
+ cd "$1" && git ls-files --exclude-standard $2
304
+} 2>/dev/null
305
+
306
+
307
+# Execute git diff-index, returning paths relative to the directory
308
+# specified in the first argument, and using the tree object id
309
+# specified in the second argument.
310
+__git_diff_index_helper ()
311
+{
312
+ cd "$1" && git diff-index --name-only --relative "$2"
313
+} 2>/dev/null
314
+
315
+# __git_index_files accepts 1 or 2 arguments:
316
+# 1: Options to pass to ls-files (required).
317
+# Supported options are --cached, --modified, --deleted, --others,
318
+# and --directory.
319
+# 2: A directory path (optional).
320
+# If provided, only files within the specified directory are listed.
321
+# Sub directories are never recursed. Path must have a trailing
322
+# slash.
323
+__git_index_files ()
324
+{
325
+ local dir="$(__gitdir)" root="${2-.}"
326
+
327
+ if [ -d "$dir" ]; then
328
+ __git_ls_files_helper "$root" "$1" | __git_index_file_list_filter |
329
+ sort | uniq
330
+ fi
331
+}
332
+
333
+# __git_diff_index_files accepts 1 or 2 arguments:
334
+# 1) The id of a tree object.
335
+# 2) A directory path (optional).
336
+# If provided, only files within the specified directory are listed.
337
+# Sub directories are never recursed. Path must have a trailing
338
+# slash.
339
+__git_diff_index_files ()
340
+{
341
+ local dir="$(__gitdir)" root="${2-.}"
342
+
343
+ if [ -d "$dir" ]; then
344
+ __git_diff_index_helper "$root" "$1" | __git_index_file_list_filter |
345
+ sort | uniq
346
+ fi
347
+}
348
+
349
__git_heads ()
350
{
351
local dir="$(__gitdir)"
543
}
544
545
546
+# __git_complete_index_file requires 1 argument: the options to pass to
547
+# ls-file
548
+__git_complete_index_file ()
549
+{
550
+ local pfx cur_="$cur"
551
+
552
+ case "$cur_" in
553
+ ?*/*)
554
+ pfx="${cur_%/*}"
555
+ cur_="${cur_##*/}"
556
+ pfx="${pfx}/"
557
+
558
+ __gitcomp_file "$(__git_index_files "$1" "$pfx")" "$pfx" "$cur_"
559
+ ;;
560
+ *)
561
+ __gitcomp_file "$(__git_index_files "$1")" "" "$cur_"
562
+ ;;
563
+ esac
564
+}
565
+
566
+# __git_complete_diff_index_file requires 1 argument: the id of a tree
567
+# object
568
+__git_complete_diff_index_file ()
569
+{
570
+ local pfx cur_="$cur"
571
+
572
+ case "$cur_" in
573
+ ?*/*)
574
+ pfx="${cur_%/*}"
575
+ cur_="${cur_##*/}"
576
+ pfx="${pfx}/"
577
+
578
+ __gitcomp_file "$(__git_diff_index_files "$1" "$pfx")" "$pfx" "$cur_"
579
+ ;;
580
+ *)
581
+ __gitcomp_file "$(__git_diff_index_files "$1")" "" "$cur_"
582
+ ;;
583
+ esac
584
+}
585
+
586
__git_complete_file ()
587
{
588
__git_complete_revlist_file
875
return 1
876
}
877
878
+# Try to count non option arguments passed on the command line for the
879
+# specified git command.
880
+# When options are used, it is necessary to use the special -- option to
881
+# tell the implementation were non option arguments begin.
882
+# XXX this can not be improved, since options can appear everywhere, as
883
+# an example:
884
+# git mv x -n y
885
+#
886
+# __git_count_arguments requires 1 argument: the git command executed.
887
+__git_count_arguments ()
888
+{
889
+ local word i c=0
890
+
891
+ # Skip "git" (first argument)
892
+ for ((i=1; i < ${#words[@]}; i++)); do
893
+ word="${words[i]}"
894
+
895
+ case "$word" in
896
+ --)
897
+ # Good; we can assume that the following are only non
898
+ # option arguments.
899
+ ((c = 0))
900
+ ;;
901
+ "$1")
902
+ # Skip the specified git command and discard git
903
+ # main options
904
+ ((c = 0))
905
+ ;;
906
+ ?*)
907
+ ((c++))
908
+ ;;
909
+ esac
910
+ done
911
+
912
+ printf "%d" $c
913
+}
914
+
915
__git_whitespacelist="nowarn warn error error-all fix"
916
917
_git_am ()
960
961
_git_add ()
962
{
773
- __git_has_doubledash && return
774
-
963
case "$cur" in
964
--*)
965
__gitcomp "
968
"
969
return
970
esac
783
- COMPREPLY=()
971
+
972
+ # XXX should we check for --update and --all options ?
973
+ __git_complete_index_file "--others --modified"
974
}
975
976
_git_archive ()
1120
1121
_git_clean ()
1122
{
933
- __git_has_doubledash && return
934
-
1123
case "$cur" in
1124
--*)
1125
__gitcomp "--dry-run --quiet"
1126
return
1127
;;
1128
esac
941
- COMPREPLY=()
1129
+
1130
+ # XXX should we check for -x option ?
1131
+ __git_complete_index_file "--others"
1132
}
1133
1134
_git_clone ()
1159
1160
_git_commit ()
1161
{
972
- __git_has_doubledash && return
1162
+ case "$prev" in
1163
+ -c|-C)
1164
+ __gitcomp_nl "$(__git_refs)" "" "${cur}"
1165
+ return
1166
+ ;;
1167
+ esac
1168
1169
case "$cur" in
1170
--cleanup=*)
1193
"
1194
return
1195
esac
1001
- COMPREPLY=()
1196
+
1197
+ if git rev-parse --verify --quiet HEAD >/dev/null; then
1198
+ __git_complete_diff_index_file "HEAD"
1199
+ else
1200
+ # This is the first commit
1201
+ __git_complete_index_file "--cached"
1202
+ fi
1203
}
1204
1205
_git_describe ()
1417
1418
_git_ls_files ()
1419
{
1219
- __git_has_doubledash && return
1220
-
1420
case "$cur" in
1421
--*)
1422
__gitcomp "--cached --deleted --modified --others --ignored
1429
return
1430
;;
1431
esac
1233
- COMPREPLY=()
1432
+
1433
+ # XXX ignore options like --modified and always suggest all cached
1434
+ # files.
1435
+ __git_complete_index_file "--cached"
1436
}
1437
1438
_git_ls_remote ()
1564
return
1565
;;
1566
esac
1365
- COMPREPLY=()
1567
+
1568
+ if [ $(__git_count_arguments "mv") -gt 0 ]; then
1569
+ # We need to show both cached and untracked files (including
1570
+ # empty directories) since this may not be the last argument.
1571
+ __git_complete_index_file "--cached --others --directory"
1572
+ else
1573
+ __git_complete_index_file "--cached"
1574
+ fi
1575
}
1576
1577
_git_name_rev ()
2277
2278
_git_rm ()
2279
{
2071
- __git_has_doubledash && return
2072
-
2280
case "$cur" in
2281
--*)
2282
__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
2283
return
2284
;;
2285
esac
2079
- COMPREPLY=()
2286
+
2287
+ __git_complete_index_file "--cached"
2288
}
2289
2290
_git_shortlog ()
2649
compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0
2650
}
2651
2652
+ __gitcomp_file ()
2653
+ {
2654
+ emulate -L zsh
2655
+
2656
+ local IFS=$'\n'
2657
+ compset -P '*[=:]'
2658
+ compadd -Q -p "${2-}" -f -- ${=1} && _ret=0
2659
+ }
2660
+
2661
__git_zsh_helper ()
2662
{
2663
emulate -L ksh
2679
2680
compdef _git git gitk
2681
return
2682
+elif [[ -n ${BASH_VERSION-} ]]; then
2683
+ if ((${BASH_VERSINFO[0]} < 4)); then
2684
+ # compopt is not supported
2685
+ __git_index_file_list_filter ()
2686
+ {
2687
+ __git_index_file_list_filter_compat
2688
+ }
2689
+ fi
2690
fi
2691
2692
__git_func_wrap ()