mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-25 12:23:09 +00:00
[git completions] Speed up __fish_git_files with lots of files
- Cache translations instead of calling `gettext` once per file - Only do the ":/" thing if the file isn't in $PWD/** For a git repo created like ```fish git init touch a(seq 0 1000)b ``` this changes the time from about 2s to 0.3s.
This commit is contained in:
parent
4057cfdce5
commit
b2d887860a
1 changed files with 30 additions and 12 deletions
|
@ -74,6 +74,18 @@ function __fish_git_files
|
||||||
# Save the repo root to remove it from the path later.
|
# Save the repo root to remove it from the path later.
|
||||||
set -l root (command git rev-parse --show-toplevel ^/dev/null)
|
set -l root (command git rev-parse --show-toplevel ^/dev/null)
|
||||||
|
|
||||||
|
# Cache the translated descriptions so we don't have to get it
|
||||||
|
# once per file.
|
||||||
|
# This is slightly slower for < 8 files, but that is fast enough anyway.
|
||||||
|
set -l unmerged_desc (_ "Unmerged File")
|
||||||
|
set -l added_desc (_ "Added file")
|
||||||
|
set -l modified_desc (_ "Modified file")
|
||||||
|
set -l staged_modified_desc (_ "Staged modified file")
|
||||||
|
set -l deleted_desc (_ "Deleted file")
|
||||||
|
set -l staged_deleted_desc (_ "Staged deleted file")
|
||||||
|
set -l untracked_desc (_ "Untracked file")
|
||||||
|
set -l ignored_desc (_ "Ignored file")
|
||||||
|
|
||||||
# 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 has better documentation and doesn't use " " to denote anything,
|
# 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.
|
# but it's only been added in git 2.11.0, which was released November 2016.
|
||||||
|
@ -88,8 +100,10 @@ function __fish_git_files
|
||||||
| while read -lz -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
|
if contains -- $use_next $argv
|
||||||
and string replace -- "$PWD/" "" "$root/$line" | string replace "$root/" ":/"
|
string replace -- "$PWD/" "" "$root/$line"
|
||||||
|
or string replace "$root/" ":/" "$root/$line"
|
||||||
|
end
|
||||||
set -e use_next[1]
|
set -e use_next[1]
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
|
@ -102,18 +116,22 @@ function __fish_git_files
|
||||||
set -l stat (string sub -l 2 -- $line)
|
set -l stat (string sub -l 2 -- $line)
|
||||||
set -l file (string sub -s 4 -- $line)
|
set -l file (string sub -s 4 -- $line)
|
||||||
# Print files from the current $PWD as-is, prepend all others with ":/" (relative to toplevel in git-speak)
|
# Print files from the current $PWD as-is, prepend all others with ":/" (relative to toplevel in git-speak)
|
||||||
# This is a bit simplistic but finding the lowest common directory and then replacing everything else in $PWD with ".." is a bit annoying
|
# This is a bit simplistic but finding the lowest common directory
|
||||||
set file (string replace -- "$PWD/" "" "$root/$file" | string replace "$root/" ":/")
|
# and then replacing everything else in $PWD with ".." is a bit annoying
|
||||||
|
set file (string replace -- "$PWD/" "" "$root/$file"; or string replace -- "$root/" ":/" "$root/$file")
|
||||||
set -e IFS
|
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 (meaning the work tree).
|
# and "Y" is "their" state (meaning the work tree).
|
||||||
# A " " means it's unmodified.
|
# A " " means it's unmodified.
|
||||||
|
#
|
||||||
|
# Be careful about the ordering here!
|
||||||
switch "$stat"
|
switch "$stat"
|
||||||
case DD AU UD UA DU AA UU
|
case DD AU UD UA DU AA UU
|
||||||
# Unmerged
|
# Unmerged
|
||||||
|
# TODO: It might be useful to split this up.
|
||||||
contains -- unmerged $argv
|
contains -- unmerged $argv
|
||||||
and printf '%s\t%s\n' "$file" (_ "Unmerged file")
|
and printf '%s\t%s\n' "$file" $unmerged_desc
|
||||||
case 'R ' RM RD
|
case 'R ' RM RD
|
||||||
# Renamed/Copied
|
# Renamed/Copied
|
||||||
# These have the "from" name as the next batch.
|
# These have the "from" name as the next batch.
|
||||||
|
@ -127,36 +145,36 @@ function __fish_git_files
|
||||||
# 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' "$file" (_ "Added file")
|
and printf '%s\t%s\n' "$file" $added_desc
|
||||||
case '?M'
|
case '?M'
|
||||||
# Modified
|
# Modified
|
||||||
contains -- modified $argv
|
contains -- modified $argv
|
||||||
and printf '%s\t%s\n' "$file" (_ "Modified file")
|
and printf '%s\t%s\n' "$file" $modified_desc
|
||||||
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' "$file" (_ "Staged modified file")
|
and printf '%s\t%s\n' "$file" $staged_modified_desc
|
||||||
case '?D'
|
case '?D'
|
||||||
contains -- deleted $argv
|
contains -- deleted $argv
|
||||||
and printf '%s\t%s\n' "$file" (_ "Deleted file")
|
and printf '%s\t%s\n' "$file" $deleted_desc
|
||||||
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' "$file" (_ "Staged deleted file")
|
and printf '%s\t%s\n' "$file" $staged_deleted_desc
|
||||||
case '\?\?'
|
case '\?\?'
|
||||||
# Untracked
|
# Untracked
|
||||||
contains -- untracked $argv
|
contains -- untracked $argv
|
||||||
and printf '%s\t%s\n' "$file" (_ "Untracked file")
|
and printf '%s\t%s\n' "$file" $untracked_desc
|
||||||
case '!!'
|
case '!!'
|
||||||
# Ignored
|
# Ignored
|
||||||
contains -- ignored $argv
|
contains -- ignored $argv
|
||||||
and printf '%s\t%s\n' "$file" (_ "Ignored file")
|
and printf '%s\t%s\n' "$file" $ignored_desc
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue