From 58b013a6ffd6acb7d6355109d2280d2c67791237 Mon Sep 17 00:00:00 2001 From: Noah Masur Date: Sun, 26 Jul 2020 17:31:31 -0400 Subject: [PATCH] Fixed vi mode cursor shape! --- fish.configlink/config.fish | 10 +- fish.configlink/functions/fish_vi_cursor.fish | 122 ++++++++++++++++++ 2 files changed, 127 insertions(+), 5 deletions(-) create mode 100644 fish.configlink/functions/fish_vi_cursor.fish diff --git a/fish.configlink/config.fish b/fish.configlink/config.fish index a496f12..a08d8fe 100644 --- a/fish.configlink/config.fish +++ b/fish.configlink/config.fish @@ -11,12 +11,12 @@ if status --is-interactive # Use `vi` in the shell fish_vi_key_bindings - set XTERM_VERSION hello + set -g fish_vi_force_cursor + set -g fish_cursor_default block + set -g fish_cursor_insert line + set -g fish_cursor_visual block + set -g fish_cursor_replace_one underscore fish_vi_cursor - set fish_cursor_default block - set fish_cursor_insert line - set fish_cursor_replace_one underscore - set fish_cursor_visual block # Turn off greeting set fish_greeting "" diff --git a/fish.configlink/functions/fish_vi_cursor.fish b/fish.configlink/functions/fish_vi_cursor.fish new file mode 100644 index 0000000..dc1d16b --- /dev/null +++ b/fish.configlink/functions/fish_vi_cursor.fish @@ -0,0 +1,122 @@ +#!/usr/local/bin/fish + +function fish_vi_cursor -d 'Set cursor shape for different vi modes' + # If we're not interactive, there is effectively no bind mode. + if not status is-interactive + return + end + + # This is hard to test in expect, since the exact sequences depend on the environment. + # Instead disable it. + if set -q FISH_UNIT_TESTS_RUNNING + return + end + + # If this variable is set, skip all checks + if not set -q fish_vi_force_cursor + + # Emacs Makes All Cursors Suck + if set -q INSIDE_EMACS + return + end + + # vte-based terms set $TERM = xterm*, but only gained support in 2015. + # From https://bugzilla.gnome.org/show_bug.cgi?id=720821, it appears it was version 0.40.0 + if set -q VTE_VERSION + and test "$VTE_VERSION" -lt 4000 2>/dev/null + return + end + + # Similarly, genuine XTerm can do it since v280. + if set -q XTERM_VERSION + and not test (string replace -r "XTerm\((\d+)\)" '$1' -- "$XTERM_VERSION") -ge 280 2>/dev/null + return + end + + # We need one of these terms. + # It would be lovely if we could rely on terminfo, but: + # - The "Ss" entry isn't a thing in macOS' old and crusty terminfo + # - It is set for xterm, and everyone and their dog claims to be xterm + # + # So we just don't care about $TERM, unless it is one of the few terminals that actually have their own entry. + # + # Note: Previous versions also checked $TMUX, and made sure that then $TERM was screen* or tmux*. + # We don't care, since we *cannot* handle term-in-a-terms 100% correctly. + if not set -q KONSOLE_PROFILE_NAME + and not test -n "$KONSOLE_VERSION" -a "$KONSOLE_VERSION" -ge 200400 # konsole, but new. + and not set -q ITERM_PROFILE + and not set -q VTE_VERSION # which version is already checked above + and not set -q WT_PROFILE_ID + and not set -q XTERM_VERSION + and not string match -rq '^st(-.*)$' -- $TERM + and not string match -q 'xterm-kitty*' -- $TERM + and not string match -q 'rxvt*' -- $TERM + and not string match -q 'alacritty*' -- $TERM + return + end + + # HACK: Explicitly disable on ITERM because of #3696, which is weirdness with multi-line prompts. + # --force-iterm is now deprecated; set $fish_vi_force_cursor instead + if contains -- $argv[1] --force-iterm + set -e argv[1] + else if set -q ITERM_PROFILE + return + end + end + + set -l terminal $argv[1] + set -q terminal[1] + or set terminal auto + + set -l function + switch "$terminal" + case auto + # Nowadays, konsole does not set $KONSOLE_PROFILE_NAME anymore, + # and it uses the xterm sequences. + if set -q KONSOLE_PROFILE_NAME + set function __fish_cursor_konsole + else if set -q ITERM_PROFILE + set function __fish_cursor_1337 + else + set function __fish_cursor_xterm + end + case konsole + set function __fish_cursor_konsole + case xterm + set function __fish_cursor_xterm + end + + set -l tmux_prefix + set -l tmux_postfix + if set -q TMUX + set tmux_prefix echo -ne "'\ePtmux;\e'" + set tmux_postfix echo -ne "'\e\\\\'" + end + + set -q fish_cursor_unknown + or set -g fish_cursor_unknown block blink + + echo " + function fish_vi_cursor_handle --on-variable fish_bind_mode --on-event fish_postexec --on-event fish_focus_in + set -l varname fish_cursor_\$fish_bind_mode + if not set -q \$varname + set varname fish_cursor_unknown + end + $tmux_prefix + $function \$\$varname + $tmux_postfix + end + " | source + + echo " + function fish_vi_cursor_handle_preexec --on-event fish_preexec + set -l varname fish_cursor_default + if not set -q \$varname + set varname fish_cursor_unknown + end + $tmux_prefix + $function \$\$varname + $tmux_postfix + end + " | source +end