mirror of
https://github.com/fish-shell/fish-shell
synced 2024-11-11 07:34:32 +00:00
parent
4095247deb
commit
f4b4ff63b9
1 changed files with 45 additions and 27 deletions
|
@ -1,5 +1,30 @@
|
|||
# fish completion for git
|
||||
# Use 'command git' to avoid interactions for aliases from git to (e.g.) hub
|
||||
|
||||
# Use this instead of calling git directly; it passes the commands that are
|
||||
# already present on the commandline to git. This is relevant for --work-tree etc, see issue #6219.
|
||||
function __fish_git
|
||||
set -l saved_args $argv
|
||||
set -l global_args
|
||||
set -l cmd (commandline -opc)
|
||||
# We assume that git is the first command until we have a better awareness of subcommands, see #2705.
|
||||
set -e cmd[1]
|
||||
if argparse -s (__fish_git_global_optspecs) -- $cmd 2>/dev/null
|
||||
# All arguments that were parsed by argparse are global git options.
|
||||
set -l num_global_args (math (count $cmd) - (count $argv))
|
||||
if test $num_global_args -ne 0
|
||||
set global_args $cmd[1..$num_global_args]
|
||||
end
|
||||
end
|
||||
# Using 'command git' to avoid interactions for aliases from git to (e.g.) hub
|
||||
command git $global_args $saved_args
|
||||
end
|
||||
|
||||
# Print an optspec for argparse to handle git's options that are independent of any subcommand.
|
||||
function __fish_git_global_optspecs
|
||||
string join \n v-version h/help C= c=+ 'e-exec-path=?' H-html-path M-man-path I-info-path p/paginate \
|
||||
P/no-pager o-no-replace-objects b-bare G-git-dir= W-work-tree= N-namespace= S-super-prefix= \
|
||||
l-literal-pathspecs g-glob-pathspecs O-noglob-pathspecs i-icase-pathspecs
|
||||
end
|
||||
|
||||
function __fish_git_commits
|
||||
# Complete commits with their subject line as the description
|
||||
|
@ -13,7 +38,7 @@ function __fish_git_commits
|
|||
# that happens for 3 commits out of 600k.
|
||||
# For fish, at the time of writing, out of 12200 commits, 7 commits need 8 characters.
|
||||
# And since this takes about 1/3rd of the time that disambiguating takes...
|
||||
command git log --pretty=tformat:"%H"\t"%<(64,trunc)%s" --all --max-count=1000 2>/dev/null \
|
||||
__fish_git log --pretty=tformat:"%H"\t"%<(64,trunc)%s" --all --max-count=1000 2>/dev/null \
|
||||
| string replace -r '^([0-9a-f]{10})[0-9a-f]*\t(.*)' '$1\t$2'
|
||||
end
|
||||
|
||||
|
@ -21,19 +46,19 @@ function __fish_git_recent_commits
|
|||
# Like __fish_git_commits, but not on all branches and limited to
|
||||
# the last 50 commits. Used for fixup, where only the current branch
|
||||
# and the latest commits make sense.
|
||||
command git log --pretty=tformat:"%h"\t"%<(64,trunc)%s" --max-count=50 2>/dev/null
|
||||
__fish_git log --pretty=tformat:"%h"\t"%<(64,trunc)%s" --max-count=50 2>/dev/null
|
||||
end
|
||||
|
||||
function __fish_git_branches
|
||||
# This is much faster than using `git branch`,
|
||||
# and avoids having to deal with localized "detached HEAD" messages.
|
||||
command git for-each-ref --format='%(refname)' refs/heads/ refs/remotes/ 2>/dev/null \
|
||||
__fish_git for-each-ref --format='%(refname)' refs/heads/ refs/remotes/ 2>/dev/null \
|
||||
| string replace -r '^refs/heads/(.*)$' '$1\tLocal Branch' \
|
||||
| string replace -r '^refs/remotes/(.*)$' '$1\tRemote Branch'
|
||||
end
|
||||
|
||||
function __fish_git_local_branches
|
||||
command git for-each-ref --format='%(refname)' refs/heads/ refs/remotes/ 2>/dev/null \
|
||||
__fish_git for-each-ref --format='%(refname)' refs/heads/ refs/remotes/ 2>/dev/null \
|
||||
| string replace -rf '^refs/heads/(.*)$' '$1\tLocal Branch'
|
||||
end
|
||||
|
||||
|
@ -42,18 +67,18 @@ function __fish_git_unique_remote_branches
|
|||
# if they are unambiguous.
|
||||
# E.g. if only alice has a "frobulate" branch
|
||||
# `git checkout frobulate` is equivalent to `git checkout -b frobulate --track alice/frobulate`.
|
||||
command git for-each-ref --format="%(refname:strip=3)" \
|
||||
__fish_git for-each-ref --format="%(refname:strip=3)" \
|
||||
--sort="refname:strip=3" \
|
||||
"refs/remotes/*/$match*" "refs/remotes/*/*/**" 2>/dev/null | \
|
||||
uniq -u
|
||||
end
|
||||
|
||||
function __fish_git_tags
|
||||
command git tag --sort=-creatordate 2>/dev/null
|
||||
__fish_git tag --sort=-creatordate 2>/dev/null
|
||||
end
|
||||
|
||||
function __fish_git_heads
|
||||
set -l gitdir (command git rev-parse --git-dir 2>/dev/null)
|
||||
set -l gitdir (__fish_git rev-parse --git-dir 2>/dev/null)
|
||||
or return # No git dir, no need to even test.
|
||||
for head in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD
|
||||
if test -f $gitdir/$head
|
||||
|
@ -69,7 +94,7 @@ function __fish_git_refs
|
|||
end
|
||||
|
||||
function __fish_git_remotes
|
||||
command git remote 2>/dev/null
|
||||
__fish_git remote 2>/dev/null
|
||||
end
|
||||
|
||||
function __fish_git_files
|
||||
|
@ -90,7 +115,7 @@ function __fish_git_files
|
|||
# to get _all_ kinds of staged files.
|
||||
|
||||
# Save the repo root to remove it from the path later.
|
||||
set -l root (command git rev-parse --show-toplevel --is-bare-repository 2>/dev/null)
|
||||
set -l root (__fish_git rev-parse --show-toplevel --is-bare-repository 2>/dev/null)
|
||||
or return
|
||||
|
||||
# Skip bare repositories.
|
||||
|
@ -152,10 +177,10 @@ function __fish_git_files
|
|||
|
||||
# We pick the v2 format if we can, because it shows relative filenames (if used without "-z").
|
||||
# We fall back on the v1 format by reading git's _version_, because trying v2 first is too slow.
|
||||
set -l ver (command git --version | string replace -rf 'git version (\d+)\.(\d+)\.?.*' '$1\n$2')
|
||||
set -l ver (__fish_git --version | string replace -rf 'git version (\d+)\.(\d+)\.?.*' '$1\n$2')
|
||||
# Version >= 2.11.* has the v2 format.
|
||||
if test "$ver[1]" -gt 2 2>/dev/null; or test "$ver[1]" -eq 2 -a "$ver[2]" -ge 11 2>/dev/null
|
||||
command git $git_opt status --porcelain=2 $status_opt \
|
||||
__fish_git $git_opt status --porcelain=2 $status_opt \
|
||||
| while read -la -d ' ' line
|
||||
set -l file
|
||||
set -l desc
|
||||
|
@ -312,7 +337,7 @@ function __fish_git_files
|
|||
set -l previous
|
||||
# Note that we can't use space as a delimiter between status and filename, because
|
||||
# the status can contain spaces - " M" is different from "M ".
|
||||
command git $git_opt status --porcelain -z $status_opt \
|
||||
__fish_git $git_opt status --porcelain -z $status_opt \
|
||||
| while read -lz line
|
||||
set -l desc
|
||||
# The entire line is the "from" from a rename.
|
||||
|
@ -499,16 +524,9 @@ end
|
|||
|
||||
function __fish_git_needs_command
|
||||
# Figure out if the current invocation already has a command.
|
||||
|
||||
# Git has tons of options, but fortunately only a few can appear before the command.
|
||||
# They are listed here.
|
||||
set -l opts h-help p P-paginate N-no-pager b-bare o-no-replace-objects \
|
||||
l-literal-pathspecs g-glob-pathspecs O-noglob-pathspecs i-icase-pathspecs \
|
||||
e-exec-path= G-git-dir= c= C= v-version H-html-path \
|
||||
m-man-path I-info-path w-work-tree= a-namespace= s-super-prefix=
|
||||
set cmd (commandline -opc)
|
||||
set -l cmd (commandline -opc)
|
||||
set -e cmd[1]
|
||||
argparse -s $opts -- $cmd 2>/dev/null
|
||||
argparse -s (__fish_git_global_optspecs) -- $cmd 2>/dev/null
|
||||
or return 0
|
||||
# These flags function as commands, effectively.
|
||||
set -q _flag_version; and return 1
|
||||
|
@ -591,15 +609,15 @@ function __fish_git_stash_not_using_subcommand
|
|||
end
|
||||
|
||||
function __fish_git_complete_worktrees
|
||||
command git worktree list --porcelain | string replace --regex --filter '^worktree\s*' ''
|
||||
__fish_git worktree list --porcelain | string replace --regex --filter '^worktree\s*' ''
|
||||
end
|
||||
|
||||
function __fish_git_complete_stashes
|
||||
command git stash list --format=%gd:%gs 2>/dev/null | string replace ":" \t
|
||||
__fish_git stash list --format=%gd:%gs 2>/dev/null | string replace ":" \t
|
||||
end
|
||||
|
||||
function __fish_git_aliases
|
||||
command git config -z --get-regexp '^alias\.' 2>/dev/null | while read -lz key value
|
||||
__fish_git config -z --get-regexp '^alias\.' 2>/dev/null | while read -lz key value
|
||||
begin
|
||||
set -l name (string replace -r '^.*\.' '' -- $key)
|
||||
printf "%s\t%s\n" $name "Alias for $value"
|
||||
|
@ -652,7 +670,7 @@ function __fish_git_possible_commithash
|
|||
end
|
||||
|
||||
function __fish_git_reflog
|
||||
command git reflog --no-decorate 2>/dev/null | string replace -r '[0-9a-f]* (.+@\{[0-9]+\}): (.*)$' '$1\t$2'
|
||||
__fish_git reflog --no-decorate 2>/dev/null | string replace -r '[0-9a-f]* (.+@\{[0-9]+\}): (.*)$' '$1\t$2'
|
||||
end
|
||||
|
||||
function __fish_git_help_all_concepts
|
||||
|
@ -728,7 +746,7 @@ end
|
|||
complete -f -c git -l help -d 'Display the manual of a git command'
|
||||
complete -f -c git -n '__fish_git_needs_command' -l version -d 'Display version'
|
||||
complete -x -c git -n '__fish_git_needs_command' -s C -a '(__fish_complete_directories)' -d 'Run as if git was started in this directory'
|
||||
complete -x -c git -n '__fish_git_needs_command' -s c -a '(command git config -l 2>/dev/null | string replace = \t)' -d 'Set a configuration option'
|
||||
complete -x -c git -n '__fish_git_needs_command' -s c -a '(__fish_git config -l 2>/dev/null | string replace = \t)' -d 'Set a configuration option'
|
||||
complete -x -c git -n '__fish_git_needs_command' -l exec-path -a '(__fish_complete_directories)' -d 'Get or set the path to the git programs'
|
||||
complete -f -c git -n '__fish_git_needs_command' -l html-path -d 'Print the path to the html documentation'
|
||||
complete -f -c git -n '__fish_git_needs_command' -l man-path -d 'Print the path to the man documentation'
|
||||
|
|
Loading…
Reference in a new issue