├── LICENSE.md ├── README.md ├── conf.d └── hydro.fish └── functions ├── fish_mode_prompt.fish └── fish_prompt.fish /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © Jorge Bucaran <> 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hydro 2 | 3 | > Ultra-pure, lag-free prompt with async Git status. Designed only for [Fish](https://fishshell.com). 4 | 5 | [![](https://user-images.githubusercontent.com/56996/103166797-f807ee00-4868-11eb-9818-c661584274c8.gif)](#hydro) 6 | 7 | ## Installation 8 | 9 | Install with [Fisher](https://github.com/jorgebucaran/fisher): 10 | 11 | ```console 12 | fisher install jorgebucaran/hydro 13 | ``` 14 | 15 | ## Features 16 | 17 | One prompt symbol to rule them all. [Change it](#configuration)? 18 | 19 |
 20 | ~ ❱ ⎢
 21 | 
22 | 23 | Display Git branch name and status—prompt repaints asynchronously! ✨ 24 | 25 |
 26 | ~/p/hydro main ❱ touch Solution
 27 | ~/p/hydro main• ❱ ⎢
 28 | 
29 | 30 | > `•` indicates that there are staged, unstaged or untracked files. 31 | 32 | Display how many commits ahead and/or behind you are of your upstream—prompt repaints asynchronously! 33 | 34 |
 35 | ~/p/hydro main• ↓2 ❱ git commit -am Hotfix
 36 | ~/p/hydro main ↑1 ↓2 ❱ git pull --rebase && git push
 37 | ~/p/hydro main ❱ ⎢
 38 | 
39 | 40 | Display [`$CMD_DURATION`](https://fishshell.com/docs/current/language.html?highlight=cmd_duration#envvar-CMD_DURATION) when > `1` second. [Configurable](#configuration). 41 | 42 |
 43 | ~/p/hydro main ❱ git push --quiet
 44 | ~/p/hydro main 1.1s ❱ ⎢
 45 | 
46 | 47 | Display the last non-zero [exit status](https://fishshell.com/docs/current/tutorial.html#exit-status) (or statuses) using [`$pipestatus`](https://fishshell.com/docs/current/language.html?highlight=cmd_duration#envvar-pipestatus). 48 | 49 |
 50 | ~/p/hydro main ❱ false
 51 | ~/p/hydro main | 1 ❱ ⎢
 52 | ~/p/hydro main ❱ true | false | false
 53 | ~/p/hydro main | 0 1 1 ❱ ⎢
 54 | 
55 | 56 | Truncate [`$PWD`](https://fishshell.com/docs/current/language.html?highlight=cmd_duration#envvar-PWD) segments except for the basename and root of Git repos. 57 | 58 |
 59 | ~ ❱ projects/hydro/
 60 | ~/p/hydro ❱ functions/share/
 61 | ~/p/hydro/f/share ❱ ⎢
 62 | 
63 | 64 | Display the current bindings mode. 65 | 66 |
 67 | I ~Esc
 68 | N ~R
 69 | R ~ ❱ ⎢
 70 | 
71 | 72 | ## Performance 73 | 74 | Blazing fast would be an understatement considering that the [LLVM repo](https://github.com/llvm/llvm-project) has over 375,000 commits! 75 | 76 |
 77 | ~/llvm-project main ❱ time fish_prompt
 78 | ~/llvm-project main ❱
 79 | ________________________________________________________
 80 | Executed in   79.00 micros    fish           external
 81 |    usr time   71.00 micros   71.00 micros    0.00 micros
 82 |    sys time    9.00 micros    9.00 micros    0.00 micros
 83 | 
84 | 85 | ## Configuration 86 | 87 | Modify variables using `set --universal` from the command line or `set --global` in your `config.fish` file. 88 | 89 | ### Symbols 90 | 91 | | Variable | Type | Description | Default | 92 | | ------------------------- | ------ | ------------------------------- | ------- | 93 | | `hydro_symbol_start` | string | Prompt start symbol. | | 94 | | `hydro_symbol_prompt` | string | Prompt symbol. | `❱` | 95 | | `hydro_symbol_git_dirty` | string | Dirty repository symbol. | `•` | 96 | | `hydro_symbol_git_ahead` | string | Ahead of your upstream symbol. | `↑` | 97 | | `hydro_symbol_git_behind` | string | Behind of your upstream symbol. | `↓` | 98 | 99 | ### Colors 100 | 101 | > Any argument accepted by [`set_color`](https://fishshell.com/docs/current/cmds/set_color.html). 102 | 103 | | Variable | Type | Description | Default | 104 | | ---------------------- | ----- | ------------------------------ | -------------------- | 105 | | `hydro_color_pwd` | color | Color of the pwd segment. | `$fish_color_normal` | 106 | | `hydro_color_git` | color | Color of the git segment. | `$fish_color_normal` | 107 | | `hydro_color_start` | color | Color of the start symbol. | `$fish_color_normal` | 108 | | `hydro_color_error` | color | Color of the error segment. | `$fish_color_error` | 109 | | `hydro_color_prompt` | color | Color of the prompt symbol. | `$fish_color_normal` | 110 | | `hydro_color_duration` | color | Color of the duration section. | `$fish_color_normal` | 111 | 112 | ### Flags 113 | 114 | | Variable | Type | Description | Default | 115 | | ----------------- | ------- | -------------------------------------------- | ------- | 116 | | `hydro_fetch` | boolean | Fetch git remote in the background. | `false` | 117 | | `hydro_multiline` | boolean | Display prompt character on a separate line. | `false` | 118 | 119 | ### Misc 120 | 121 | | Variable | Type | Description | Default | 122 | | ------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------ | ------- | 123 | | `fish_prompt_pwd_dir_length` | numeric | The number of characters to display when path shortening. Set it to `0` to display only the topmost (current) directory. | `1` | 124 | | `hydro_ignored_git_paths` | strings | Space separated list of paths where no git info should be displayed. | `""` | 125 | | `hydro_cmd_duration_threshold` | numeric | Minimum command duration, in milliseconds, after which command duration is displayed. | `1000` | 126 | 127 | ## License 128 | 129 | [MIT](LICENSE.md) 130 | -------------------------------------------------------------------------------- /conf.d/hydro.fish: -------------------------------------------------------------------------------- 1 | status is-interactive || exit 2 | 3 | set --global _hydro_git _hydro_git_$fish_pid 4 | 5 | function $_hydro_git --on-variable $_hydro_git 6 | commandline --function repaint 7 | end 8 | 9 | function _hydro_pwd --on-variable PWD --on-variable hydro_ignored_git_paths --on-variable fish_prompt_pwd_dir_length 10 | set --local git_root (command git --no-optional-locks rev-parse --show-toplevel 2>/dev/null) 11 | set --local git_base (string replace --all --regex -- "^.*/" "" "$git_root") 12 | set --local path_sep / 13 | 14 | test "$fish_prompt_pwd_dir_length" = 0 && set path_sep 15 | 16 | if set --query git_root[1] && ! contains -- $git_root $hydro_ignored_git_paths 17 | set --erase _hydro_skip_git_prompt 18 | else 19 | set --global _hydro_skip_git_prompt 20 | end 21 | 22 | set --global _hydro_pwd ( 23 | string replace --ignore-case -- ~ \~ $PWD | 24 | string replace -- "/$git_base/" /:/ | 25 | string replace --regex --all -- "(\.?[^/]{"( 26 | string replace --regex --all -- '^$' 1 "$fish_prompt_pwd_dir_length" 27 | )"})[^/]*/" "\$1$path_sep" | 28 | string replace -- : "$git_base" | 29 | string replace --regex -- '([^/]+)$' "\x1b[1m\$1\x1b[22m" | 30 | string replace --regex --all -- '(?!^/$)/|^$' "\x1b[2m/\x1b[22m" 31 | ) 32 | end 33 | 34 | function _hydro_postexec --on-event fish_postexec 35 | set --local last_status $pipestatus 36 | set --global _hydro_status "$_hydro_newline$_hydro_color_prompt$hydro_symbol_prompt" 37 | 38 | for code in $last_status 39 | if test $code -ne 0 40 | set --global _hydro_status "$_hydro_color_error| "(echo $last_status)" $_hydro_newline$_hydro_color_prompt$_hydro_color_error$hydro_symbol_prompt" 41 | break 42 | end 43 | end 44 | 45 | test "$CMD_DURATION" -lt $hydro_cmd_duration_threshold && set _hydro_cmd_duration && return 46 | 47 | set --local secs (math --scale=1 $CMD_DURATION/1000 % 60) 48 | set --local mins (math --scale=0 $CMD_DURATION/60000 % 60) 49 | set --local hours (math --scale=0 $CMD_DURATION/3600000) 50 | 51 | set --local out 52 | 53 | test $hours -gt 0 && set --local --append out $hours"h" 54 | test $mins -gt 0 && set --local --append out $mins"m" 55 | test $secs -gt 0 && set --local --append out $secs"s" 56 | 57 | set --global _hydro_cmd_duration "$out " 58 | end 59 | 60 | function _hydro_prompt --on-event fish_prompt 61 | set --query _hydro_status || set --global _hydro_status "$_hydro_newline$_hydro_color_prompt$hydro_symbol_prompt" 62 | set --query _hydro_pwd || _hydro_pwd 63 | 64 | command kill $_hydro_last_pid 2>/dev/null 65 | 66 | set --query _hydro_skip_git_prompt && set $_hydro_git && return 67 | 68 | fish --private --command " 69 | set branch ( 70 | command git symbolic-ref --short HEAD 2>/dev/null || 71 | command git describe --tags --exact-match HEAD 2>/dev/null || 72 | command git rev-parse --short HEAD 2>/dev/null | 73 | string replace --regex -- '(.+)' '@\$1' 74 | ) 75 | 76 | test -z \"\$$_hydro_git\" && set --universal $_hydro_git \"\$branch \" 77 | 78 | command git diff-index --quiet HEAD 2>/dev/null 79 | test \$status -eq 1 || 80 | count (command git ls-files --others --exclude-standard (command git rev-parse --show-toplevel)) >/dev/null && set info \"$hydro_symbol_git_dirty\" 81 | 82 | for fetch in $hydro_fetch false 83 | command git rev-list --count --left-right @{upstream}...@ 2>/dev/null | 84 | read behind ahead 85 | 86 | switch \"\$behind \$ahead\" 87 | case \" \" \"0 0\" 88 | case \"0 *\" 89 | set upstream \" $hydro_symbol_git_ahead\$ahead\" 90 | case \"* 0\" 91 | set upstream \" $hydro_symbol_git_behind\$behind\" 92 | case \* 93 | set upstream \" $hydro_symbol_git_ahead\$ahead $hydro_symbol_git_behind\$behind\" 94 | end 95 | 96 | set --universal $_hydro_git \"\$branch\$info\$upstream \" 97 | 98 | test \$fetch = true && command git fetch --no-tags 2>/dev/null 99 | end 100 | " & 101 | 102 | set --global _hydro_last_pid $last_pid 103 | end 104 | 105 | function _hydro_fish_exit --on-event fish_exit 106 | set --erase $_hydro_git 107 | end 108 | 109 | function _hydro_uninstall --on-event hydro_uninstall 110 | set --names | 111 | string replace --filter --regex -- "^(_?hydro_)" "set --erase \$1" | 112 | source 113 | functions --erase (functions --all | string match --entire --regex "^_?hydro_") 114 | end 115 | 116 | set --global hydro_color_normal (set_color normal) 117 | 118 | for color in hydro_color_{pwd,git,error,prompt,duration,start} 119 | function $color --on-variable $color --inherit-variable color 120 | set --query $color && set --global _$color (set_color $$color) 121 | end && $color 122 | end 123 | 124 | function hydro_multiline --on-variable hydro_multiline 125 | if test "$hydro_multiline" = true 126 | set --global _hydro_newline "\n" 127 | else 128 | set --global _hydro_newline "" 129 | end 130 | end && hydro_multiline 131 | 132 | set --query hydro_color_error || set --global hydro_color_error $fish_color_error 133 | set --query hydro_symbol_prompt || set --global hydro_symbol_prompt ❱ 134 | set --query hydro_symbol_git_dirty || set --global hydro_symbol_git_dirty • 135 | set --query hydro_symbol_git_ahead || set --global hydro_symbol_git_ahead ↑ 136 | set --query hydro_symbol_git_behind || set --global hydro_symbol_git_behind ↓ 137 | set --query hydro_multiline || set --global hydro_multiline false 138 | set --query hydro_cmd_duration_threshold || set --global hydro_cmd_duration_threshold 1000 139 | -------------------------------------------------------------------------------- /functions/fish_mode_prompt.fish: -------------------------------------------------------------------------------- 1 | function fish_mode_prompt 2 | if test "$fish_key_bindings" != fish_default_key_bindings 3 | set --local vi_mode_color 4 | set --local vi_mode_symbol 5 | switch $fish_bind_mode 6 | case default 7 | set vi_mode_color (set_color $fish_color_selection) 8 | set vi_mode_symbol N 9 | case insert 10 | set vi_mode_color (set_color $fish_color_selection) 11 | set vi_mode_symbol I 12 | case replace replace_one 13 | set vi_mode_color (set_color $fish_color_match) 14 | set vi_mode_symbol R 15 | case visual 16 | set vi_mode_color (set_color $fish_color_match) 17 | set vi_mode_symbol V 18 | end 19 | echo -e "$vi_mode_color $vi_mode_symbol \x1b[0m " 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /functions/fish_prompt.fish: -------------------------------------------------------------------------------- 1 | function fish_prompt --description Hydro 2 | echo -e "$_hydro_color_start$hydro_symbol_start$hydro_color_normal$_hydro_color_pwd$_hydro_pwd$hydro_color_normal $_hydro_color_git$$_hydro_git$hydro_color_normal$_hydro_color_duration$_hydro_cmd_duration$hydro_color_normal$_hydro_status$hydro_color_normal " 3 | end 4 | --------------------------------------------------------------------------------