mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-12 13:08:49 +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.
|
||||
|
||||
# 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
|
||||
# and "M " to denote a changed staged file, opting for a "." in place of the space.
|
||||
# So the v1 format would require something other than this `while read` loop.
|
||||
#
|
||||
# Unfortunately, the v2 format is really 4 different subformats
|
||||
# - see the explanation inline. (Or on https://git-scm.com/docs/git-status)
|
||||
# The v2 format has better documentation and doesn't use " " to denote anything,
|
||||
# but it's only been added in git 2.11.0, which was released November 2016.
|
||||
# Instead, we use the v1 format, without explicitly specifying it (since that errors out as well).
|
||||
#
|
||||
# Also, we ignore submodules because they aren't useful as arguments (generally),
|
||||
# and they slow things down quite significantly.
|
||||
# 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
|
||||
command git status --porcelain=2 -z --ignore-submodules=all \
|
||||
| while read -laz -d ' ' line
|
||||
command git status --porcelain -z --ignore-submodules=all \
|
||||
| while read -lz -d '' line
|
||||
# The entire line is the "from" from a rename.
|
||||
if set -q use_next[1]
|
||||
contains -- $use_next $argv
|
||||
|
@ -105,67 +103,66 @@ function __fish_git_files
|
|||
continue
|
||||
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),
|
||||
# and "Y" is "their" state.
|
||||
# A "." means it's unmodified.
|
||||
switch "$line[1..2]"
|
||||
case 'u *'
|
||||
# and "Y" is "their" state (meaning the work tree).
|
||||
# A " " means it's unmodified.
|
||||
switch "$stat"
|
||||
case DD AU UD UA DU AA UU
|
||||
# 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
|
||||
and printf '%s\t%s\n' "$line[11..-1]" (_ "Unmerged file")
|
||||
case '? .R*' '? R.*'
|
||||
and printf '%s\t%s\n' "$file" (_ "Unmerged file")
|
||||
case 'R ' RM RD
|
||||
# Renamed/Copied
|
||||
# From the docs: "Renamed or copied entries have the following format:"
|
||||
# "2 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <X><score> <path><sep><origPath>"
|
||||
# Since <sep> is NUL, the <origPath> (meaning the old name) is in the next batch.
|
||||
# TODO: Do we care about the new one?
|
||||
# These have the "from" name as the next batch.
|
||||
# TODO: Do we care about the new name?
|
||||
set use_next renamed
|
||||
continue
|
||||
case '? .C*' '? C.*'
|
||||
case 'C ' CM CD
|
||||
set use_next copied
|
||||
continue
|
||||
case '? A.*'
|
||||
case 'A ' AM AD
|
||||
# Additions are only shown here if they are staged.
|
||||
# Otherwise it's an untracked file.
|
||||
contains -- added $argv; or contains -- all-staged $argv
|
||||
and printf '%s\t%s\n' "$line[9..-1]" (_ "Added file")
|
||||
case '? .M*'
|
||||
and printf '%s\t%s\n' "$file" (_ "Added file")
|
||||
case '?M'
|
||||
# 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
|
||||
and printf '%s\t%s\n' "$line[9..-1]" (_ "Modified file")
|
||||
case '? M.*'
|
||||
# If the character is first ("M."), then that means it's "our" change,
|
||||
and printf '%s\t%s\n' "$file" (_ "Modified file")
|
||||
case 'M?'
|
||||
# If the character is first ("M "), then that means it's "our" change,
|
||||
# which means it is staged.
|
||||
# This is useless for many commands - e.g. `checkout` won't do anything with this.
|
||||
# So it needs to be requested explicitly.
|
||||
contains -- modified-staged $argv; or contains -- all-staged $argv
|
||||
and printf '%s\t%s\n' "$line[9..-1]" (_ "Staged modified file")
|
||||
case '? .D*'
|
||||
and printf '%s\t%s\n' "$file" (_ "Staged modified file")
|
||||
case '?D'
|
||||
contains -- deleted $argv
|
||||
and printf '%s\t%s\n' "$line[9..-1]" (_ "Deleted file")
|
||||
case '? D.*'
|
||||
and printf '%s\t%s\n' "$file" (_ "Deleted file")
|
||||
case 'D?'
|
||||
# TODO: The docs are unclear on this.
|
||||
# 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").
|
||||
# For our purposes, we assume this is a staged deletion.
|
||||
contains -- deleted-staged $argv; or contains -- all-staged $argv
|
||||
and printf '%s\t%s\n' "$line[9..-1]" (_ "Staged deleted file")
|
||||
case '\? *'
|
||||
and printf '%s\t%s\n' "$file" (_ "Staged deleted file")
|
||||
case '\?\?'
|
||||
# Untracked
|
||||
# "? <path>" - print from element 2 on.
|
||||
contains -- untracked $argv
|
||||
and printf '%s\t%s\n' "$line[2..-1]" (_ "Untracked file")
|
||||
case '! *'
|
||||
and printf '%s\t%s\n' "$file" (_ "Untracked file")
|
||||
case '!!'
|
||||
# Ignored
|
||||
# "! <path>" - print from element 2 on.
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue