home-config/fish/functions/_fzf_preview_changed_file.fish
7b8185c6ca47a6b6d27cefcd816c49e2bd7cd591
· 2.4 KB · 49 lines
raw
| 1 | # helper for _fzf_search_git_status |
| 2 | # arg should be a line from git status --short, e.g. |
| 3 | # MM functions/_fzf_preview_changed_file.fish |
| 4 | # D README.md |
| 5 | # R LICENSE -> "New License" |
| 6 | function _fzf_preview_changed_file --argument-names path_status --description "Show the git diff of the given file." |
| 7 | # remove quotes because they'll be interpreted literally by git diff |
| 8 | # no need to requote when referencing $path because fish does not perform word splitting |
| 9 | # https://fishshell.com/docs/current/fish_for_bash_users.html |
| 10 | set -f path (string unescape (string sub --start 4 $path_status)) |
| 11 | # first letter of short format shows index, second letter shows working tree |
| 12 | # https://git-scm.com/docs/git-status/2.35.0#_short_format |
| 13 | set -f index_status (string sub --length 1 $path_status) |
| 14 | set -f working_tree_status (string sub --start 2 --length 1 $path_status) |
| 15 | |
| 16 | set -f diff_opts --color=always |
| 17 | |
| 18 | if test $index_status = '?' |
| 19 | _fzf_report_diff_type Untracked |
| 20 | _fzf_preview_file $path |
| 21 | else if contains {$index_status}$working_tree_status DD AU UD UA DU AA UU |
| 22 | # Unmerged statuses taken directly from git status help's short format table |
| 23 | # Unmerged statuses are mutually exclusive with other statuses, so if we see |
| 24 | # these, then safe to assume the path is unmerged |
| 25 | _fzf_report_diff_type Unmerged |
| 26 | git diff $diff_opts -- $path |
| 27 | else |
| 28 | if test $index_status != ' ' |
| 29 | _fzf_report_diff_type Staged |
| 30 | |
| 31 | # renames are only detected in the index, never working tree, so only need to test for it here |
| 32 | # https://stackoverflow.com/questions/73954214 |
| 33 | if test $index_status = R |
| 34 | # diff the post-rename path with the original path, otherwise the diff will show the entire file as being added |
| 35 | set -f orig_and_new_path (string split --max 1 -- ' -> ' $path) |
| 36 | git diff --staged $diff_opts -- $orig_and_new_path[1] $orig_and_new_path[2] |
| 37 | # path currently has the form of "original -> current", so we need to correct it before it's used below |
| 38 | set path $orig_and_new_path[2] |
| 39 | else |
| 40 | git diff --staged $diff_opts -- $path |
| 41 | end |
| 42 | end |
| 43 | |
| 44 | if test $working_tree_status != ' ' |
| 45 | _fzf_report_diff_type Unstaged |
| 46 | git diff $diff_opts -- $path |
| 47 | end |
| 48 | end |
| 49 | end |