mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-12 21:18:53 +00:00
[git completions] Use status v1 output
Apparently the v2 format is too new (released Nov 2016), and the v1 format has everything we need.
This commit is contained in:
parent
64c8d4c265
commit
4fac2f98c2
1 changed files with 39 additions and 42 deletions
|
@ -84,19 +84,17 @@ function __fish_git_files
|
||||||
# to get _all_ kinds of staged files.
|
# to get _all_ kinds of staged files.
|
||||||
|
|
||||||
# git status --porcelain gives us all the info we need, in a format we don't.
|
# git status --porcelain gives us all the info we need, in a format we don't.
|
||||||
# The v2 format thankfully doesn't use " M" to denote a changed unstaged file
|
# The v2 format has better documentation and doesn't use " " to denote anything,
|
||||||
# and "M " to denote a changed staged file, opting for a "." in place of the space.
|
# but it's only been added in git 2.11.0, which was released November 2016.
|
||||||
# So the v1 format would require something other than this `while read` loop.
|
# Instead, we use the v1 format, without explicitly specifying it (since that errors out as well).
|
||||||
#
|
|
||||||
# Unfortunately, the v2 format is really 4 different subformats
|
|
||||||
# - see the explanation inline. (Or on https://git-scm.com/docs/git-status)
|
|
||||||
#
|
#
|
||||||
# Also, we ignore submodules because they aren't useful as arguments (generally),
|
# Also, we ignore submodules because they aren't useful as arguments (generally),
|
||||||
# and they slow things down quite significantly.
|
# and they slow things down quite significantly.
|
||||||
# E.g. `git reset $submodule` won't do anything (not even print an error).
|
# E.g. `git reset $submodule` won't do anything (not even print an error).
|
||||||
|
# --ignore-submodules=all was added in git 1.7.2, released July 2010.
|
||||||
set -l use_next
|
set -l use_next
|
||||||
command git status --porcelain=2 -z --ignore-submodules=all \
|
command git status --porcelain -z --ignore-submodules=all \
|
||||||
| while read -laz -d ' ' line
|
| while read -lz -d '' line
|
||||||
# The entire line is the "from" from a rename.
|
# The entire line is the "from" from a rename.
|
||||||
if set -q use_next[1]
|
if set -q use_next[1]
|
||||||
contains -- $use_next $argv
|
contains -- $use_next $argv
|
||||||
|
@ -105,67 +103,66 @@ function __fish_git_files
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The format is two characters for status, then a space and then
|
||||||
|
# up to a NUL for the filename.
|
||||||
|
#
|
||||||
|
# Use IFS to handle newlines in filenames.
|
||||||
|
set -l IFS
|
||||||
|
set -l stat (string sub -l 2 -- $line)
|
||||||
|
set -l file (string sub -s 4 -- $line)
|
||||||
|
set -e IFS
|
||||||
|
|
||||||
# The basic status format is "XY", where X is "our" state (meaning the staging area),
|
# The basic status format is "XY", where X is "our" state (meaning the staging area),
|
||||||
# and "Y" is "their" state.
|
# and "Y" is "their" state (meaning the work tree).
|
||||||
# A "." means it's unmodified.
|
# A " " means it's unmodified.
|
||||||
switch "$line[1..2]"
|
switch "$stat"
|
||||||
case 'u *'
|
case DD AU UD UA DU AA UU
|
||||||
# Unmerged
|
# Unmerged
|
||||||
# "Unmerged entries have the following format; the first character is a "u" to distinguish from ordinary changed entries."
|
|
||||||
# "u <xy> <sub> <m1> <m2> <m3> <mW> <h1> <h2> <h3> <path>"
|
|
||||||
# This is first to distinguish it from normal modifications et al.
|
|
||||||
contains -- unmerged $argv
|
contains -- unmerged $argv
|
||||||
and printf '%s\t%s\n' "$line[11..-1]" (_ "Unmerged file")
|
and printf '%s\t%s\n' "$file" (_ "Unmerged file")
|
||||||
case '? .R*' '? R.*'
|
case 'R ' RM RD
|
||||||
# Renamed/Copied
|
# Renamed/Copied
|
||||||
# From the docs: "Renamed or copied entries have the following format:"
|
# These have the "from" name as the next batch.
|
||||||
# "2 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <X><score> <path><sep><origPath>"
|
# TODO: Do we care about the new name?
|
||||||
# Since <sep> is NUL, the <origPath> (meaning the old name) is in the next batch.
|
|
||||||
# TODO: Do we care about the new one?
|
|
||||||
set use_next renamed
|
set use_next renamed
|
||||||
continue
|
continue
|
||||||
case '? .C*' '? C.*'
|
case 'C ' CM CD
|
||||||
set use_next copied
|
set use_next copied
|
||||||
continue
|
continue
|
||||||
case '? A.*'
|
case 'A ' AM AD
|
||||||
# Additions are only shown here if they are staged.
|
# Additions are only shown here if they are staged.
|
||||||
# Otherwise it's an untracked file.
|
# Otherwise it's an untracked file.
|
||||||
contains -- added $argv; or contains -- all-staged $argv
|
contains -- added $argv; or contains -- all-staged $argv
|
||||||
and printf '%s\t%s\n' "$line[9..-1]" (_ "Added file")
|
and printf '%s\t%s\n' "$file" (_ "Added file")
|
||||||
case '? .M*'
|
case '?M'
|
||||||
# Modified
|
# Modified
|
||||||
# From the docs: "Ordinary changed entries have the following format:"
|
|
||||||
# "1 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <path>"
|
|
||||||
# Since <path> can contain spaces, print from element 9 onwards
|
|
||||||
contains -- modified $argv
|
contains -- modified $argv
|
||||||
and printf '%s\t%s\n' "$line[9..-1]" (_ "Modified file")
|
and printf '%s\t%s\n' "$file" (_ "Modified file")
|
||||||
case '? M.*'
|
case 'M?'
|
||||||
# If the character is first ("M."), then that means it's "our" change,
|
# If the character is first ("M "), then that means it's "our" change,
|
||||||
# which means it is staged.
|
# which means it is staged.
|
||||||
# This is useless for many commands - e.g. `checkout` won't do anything with this.
|
# This is useless for many commands - e.g. `checkout` won't do anything with this.
|
||||||
# So it needs to be requested explicitly.
|
# So it needs to be requested explicitly.
|
||||||
contains -- modified-staged $argv; or contains -- all-staged $argv
|
contains -- modified-staged $argv; or contains -- all-staged $argv
|
||||||
and printf '%s\t%s\n' "$line[9..-1]" (_ "Staged modified file")
|
and printf '%s\t%s\n' "$file" (_ "Staged modified file")
|
||||||
case '? .D*'
|
case '?D'
|
||||||
contains -- deleted $argv
|
contains -- deleted $argv
|
||||||
and printf '%s\t%s\n' "$line[9..-1]" (_ "Deleted file")
|
and printf '%s\t%s\n' "$file" (_ "Deleted file")
|
||||||
case '? D.*'
|
case 'D?'
|
||||||
# TODO: The docs are unclear on this.
|
# TODO: The docs are unclear on this.
|
||||||
# There is both X unmodified and Y either M or D ("not updated")
|
# There is both X unmodified and Y either M or D ("not updated")
|
||||||
# and Y is D and X is unmodified or [MARC] ("deleted in work tree").
|
# and Y is D and X is unmodified or [MARC] ("deleted in work tree").
|
||||||
# For our purposes, we assume this is a staged deletion.
|
# For our purposes, we assume this is a staged deletion.
|
||||||
contains -- deleted-staged $argv; or contains -- all-staged $argv
|
contains -- deleted-staged $argv; or contains -- all-staged $argv
|
||||||
and printf '%s\t%s\n' "$line[9..-1]" (_ "Staged deleted file")
|
and printf '%s\t%s\n' "$file" (_ "Staged deleted file")
|
||||||
case '\? *'
|
case '\?\?'
|
||||||
# Untracked
|
# Untracked
|
||||||
# "? <path>" - print from element 2 on.
|
|
||||||
contains -- untracked $argv
|
contains -- untracked $argv
|
||||||
and printf '%s\t%s\n' "$line[2..-1]" (_ "Untracked file")
|
and printf '%s\t%s\n' "$file" (_ "Untracked file")
|
||||||
case '! *'
|
case '!!'
|
||||||
# Ignored
|
# Ignored
|
||||||
# "! <path>" - print from element 2 on.
|
|
||||||
contains -- ignored $argv
|
contains -- ignored $argv
|
||||||
and printf '%s\t%s\n' "$line[2..-1]" (_ "Ignored file")
|
and printf '%s\t%s\n' "$file" (_ "Ignored file")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue