diff --git a/share/functions/fish_print_git_action.fish b/share/functions/fish_print_git_action.fish new file mode 100644 index 000000000..4810dc59d --- /dev/null +++ b/share/functions/fish_print_git_action.fish @@ -0,0 +1,71 @@ +# Given the path to a .git directory this function prints a human-readable name +# for the git action in progress (e.g. "merge") or returns 1. +function fish_print_git_action --argument-names git_dir + if test -z "$git_dir" + if not command -sq git + return 1 + end + if not set git_dir (command git rev-parse --git-dir 2>/dev/null) + return 1 + end + end + + for action_dir in "$git_dir/rebase-apply" "$git_dir/rebase" + if test -d "$action_dir" + if test -f "$action_dir/rebasing" + echo -n 'rebase' + else if test -f "$action_dir/applying" + echo -n 'apply' + else + echo -n 'rebase/apply' + end + return 0 + end + end + + for action_dir in "$git_dir/rebase-merge/interactive" "$git_dir/.dotest-merge/interactive" + if test -f "$action_dir" + echo -n 'rebase-interactive' + return 0 + end + end + + for action_dir in "$git_dir/rebase-merge" "$git_dir/.dotest-merge" + if test -d "$action_dir" + echo -n 'rebase-merge' + return 0 + end + end + + if test -f "$git_dir/MERGE_HEAD" + echo -n 'merge' + return 0 + end + + if test -f "$git_dir/CHERRY_PICK_HEAD" + if test -d "$git_dir/sequencer" + cherry_pick_sequence_formatted='cherry-pick-sequence' + echo -n 'cherry-pick-sequence' + else + cherry_pick_formatted='cherry-pick' + echo -n 'cherry-pick' + end + return 0 + end + + if test -f "$git_dir/REVERT_HEAD" + if test -d "$git_dir/sequencer" + echo -n 'revert-sequence' + else + echo -n 'revert' + end + return 0 + end + + if test -f "$git_dir/BISECT_LOG" + echo -n 'bisect' + return 0 + end + + return 1 +end diff --git a/share/tools/web_config/sample_prompts/sorin.fish b/share/tools/web_config/sample_prompts/sorin.fish index 69fff2d14..0efd4c310 100644 --- a/share/tools/web_config/sample_prompts/sorin.fish +++ b/share/tools/web_config/sample_prompts/sorin.fish @@ -1,61 +1,188 @@ # name: Sorin -# author: Ivan Tham +# author: Leonard Hecker + +# Sources: +# - General theme setup: https://github.com/sorin-ionescu/prezto/blob/d275f316ffdd0bbd075afbff677c3e00791fba16/modules/prompt/functions/prompt_sorin_setup +# - Extraction of git info: https://github.com/sorin-ionescu/prezto/blob/d275f316ffdd0bbd075afbff677c3e00791fba16/modules/git/functions/git-info#L180-L441 function fish_prompt - test $SSH_TTY - and printf (set_color red)$USER(set_color brwhite)'@'(set_color yellow)(prompt_hostname)' ' - test "$USER" = 'root' - and echo (set_color red)"#" + if test -n "$SSH_TTY" + echo -n (set_color brred)"$USER"(set_color white)'@'(set_color yellow)(prompt_hostname)' ' + end - # Main - echo -n (set_color cyan)(prompt_pwd) (set_color red)'❯'(set_color yellow)'❯'(set_color green)'❯ ' + echo -n (set_color blue)(prompt_pwd)' ' + + set_color -o + if test "$USER" = 'root' + echo -n (set_color red)'# ' + end + echo -n (set_color red)'❯'(set_color yellow)'❯'(set_color green)'❯ ' + set_color normal end function fish_right_prompt - # last status - test $status != 0 - and printf (set_color red)"⏎ " + set -l cmd_status $status + if test $cmd_status -ne 0 + echo -n (set_color red)"✘ $cmd_status" + end - if set -l git_dir (git rev-parse --git-dir 2>/dev/null) - # Magenta if branch detached else green - set -l branch (command git branch -qv | string match "\**") - string match -rq detached -- $branch - and set_color brmagenta - or set_color brgreen + if not command -sq git + set_color normal + return + end - git name-rev --name-only HEAD + # Get the git directory for later use. + # Return if not inside a Git repository work tree. + if not set -l git_dir (command git rev-parse --git-dir 2>/dev/null) + set_color normal + return + end - # Merging state - test -f "$git_dir/MERGE_HEAD" - and printf ':'(set_color red)'merge' - printf ' ' + # Get the current action ("merge", "rebase", etc.) + # and if there's one get the current commit hash too. + set -l commit '' + if set -l action (__fish_git_action "$git_dir") + set commit (command git rev-parse HEAD 2> /dev/null | string sub -l 7) + end - # Symbols - if set -l count (command git rev-list --count --left-right $upstream...HEAD 2>/dev/null) - echo $count | read -l ahead behind - if test "$ahead" -gt 0 - printf (set_color magenta)⬆' ' - end - if test "$behind" -gt 0 - printf (set_color magenta)⬇' ' - end - end + # Get either the branch name or a branch descriptor. + set -l branch_detached 0 + if not set -l branch (command git symbolic-ref --short HEAD 2>/dev/null) + set branch_detached 1 + set branch (command git describe --contains --all HEAD 2>/dev/null) + end - for i in (git status --porcelain | string sub -l 2 | uniq) - switch $i - case "." - printf (set_color green)✚' ' - case " D" - printf (set_color red)✖' ' - case "*M*" - printf (set_color blue)✱' ' - case "*R*" - printf (set_color brmagenta)➜' ' - case "*U*" - printf (set_color bryellow)═' ' - case "??" - printf (set_color brwhite)◼' ' - end + # Get the commit difference counts between local and remote. + command git rev-list --count --left-right 'HEAD...@{upstream}' 2>/dev/null \ + | read -d \t -l status_ahead status_behind + if test $status -ne 0 + set status_ahead 0 + set status_behind 0 + end + + # Get the stash status. + # (git stash list) is very slow. => Avoid using it. + set -l status_stashed 0 + if test -f "$git_dir/refs/stash" + set status_stashed 1 + else if test -r "$git_dir/commondir" + read -l commondir <"$git_dir/commondir" + if test -f "$commondir/refs/stash" + set status_stashed 1 end end + + # git-status' porcelain v1 format starts with 2 letters on each line: + # The first letter (X) denotes the index state. + # The second letter (Y) denotes the working directory state. + # + # The following table presents the possible combinations: + # * The underscore character denotes whitespace. + # * The cell values stand for the following file states: + # a: added + # d: deleted + # m: modified + # r: renamed + # u: unmerged + # t: untracked + # * Cells with more than one letter signify that both states + # are simultaneously the case. This is possible since the git index + # and working directory operate independently of each other. + # * Cells which are empty are unhandled by this code. + # * T (= type change) is undocumented. + # See Git v1.7.8.2 release notes for more information. + # + # \ Y→ + # X \ + # ↓ | A | C | D | M | R | T | U | X | B | ? | _ + # ----+----+----+----+----+----+----+----+----+----+----+---- + # A | u | | ad | am | r | am | u | | | | a + # C | | | ad | am | r | am | u | | | | a + # D | | | u | am | r | am | u | | | | a + # M | | | ad | am | r | am | u | | | | a + # R | r | r | rd | rm | r | rm | ur | r | r | r | r + # T | | | ad | am | r | am | u | | | | a + # U | u | u | u | um | ur | um | u | u | u | u | u + # X | | | | m | r | m | u | | | | + # B | | | | m | r | m | u | | | | + # ? | | | | m | r | m | u | | | t | + # _ | | | d | m | r | m | u | | | | + + set -l status_added 0 + set -l status_deleted 0 + set -l status_modified 0 + set -l status_renamed 0 + set -l status_unmerged 0 + set -l status_untracked 0 + for line in (command git status --porcelain | string sub -l 2) + # Check unambiguous cases first which allows us + # to skip running all the other regexps. + if test "$line" = '??' + set status_untracked 1 + continue + end + if string match -r '^(?:AA|DD|U.|.U)$' "$line" >/dev/null + set status_unmerged 1 + continue + end + if string match -r '^(?:[ACDMT][ MT]|[ACMT]D)$' "$line" >/dev/null + set status_added 1 + end + if string match -r '^[ ACMRT]D$' "$line" >/dev/null + set status_deleted 1 + end + if string match -r '^.[MT]$' "$line" >/dev/null + set status_modified 1 + end + if string match -e 'R' "$line" >/dev/null + set status_renamed 1 + end + end + + set_color -o + + if test -n "$branch" + if test $branch_detached -ne 0 + set_color brmagenta + else + set_color green + end + echo -n " $branch" + end + if test -n "$commit" + echo -n ' '(set_color yellow)"$commit" + end + if test -n "$action" + set_color normal + echo -n (set_color white)':'(set_color -o brred)"$action" + end + if test $status_ahead -ne 0 + echo -n ' '(set_color brmagenta)'⬆' + end + if test $status_behind -ne 0 + echo -n ' '(set_color brmagenta)'⬇' + end + if test $status_stashed -ne 0 + echo -n ' '(set_color cyan)'✭' + end + if test $status_added -ne 0 + echo -n ' '(set_color green)'✚' + end + if test $status_deleted -ne 0 + echo -n ' '(set_color red)'✖' + end + if test $status_modified -ne 0 + echo -n ' '(set_color blue)'✱' + end + if test $status_renamed -ne 0 + echo -n ' '(set_color magenta)'➜' + end + if test $status_unmerged -ne 0 + echo -n ' '(set_color yellow)'═' + end + if test $status_untracked -ne 0 + echo -n ' '(set_color white)'◼' + end + + set_color normal end