drmikehenry / vim-fixkey

https://github.com/drmikehenry/
125 stars 10 forks source link

Home/End key under tmux #7

Closed RobinJadoul closed 8 years ago

RobinJadoul commented 8 years ago

My home and end key under tmux don't function using this plugin. It exits to normal mode and transforms a letter to/from uppercase. The plugin works really well for most of my purposes, but this is really annoying.

They don't appear to work in combination with modifier keys either.

I figured that by call Fixkey_setKey("<Home>", "\e[1~") and call Fixkey_setKey("<End>", "\e[4~") instead of call Fixkey_setXtermHomeEnd(), it seems to work.

drmikehenry commented 8 years ago

Hello, Robin,

Sorry to hear the plugin isn't working out-of-the-box for you. In my testing, <Home> and <End> work correctly for both screen and tmux, with and without modifiers. The first thing I'd suggest to check is the value of the TERM environment variable before launching vim:

echo $TERM

This should be something that matches the regular expressions found in fixkey.vim:

    elseif $TERM =~# '\v^screen(-\d*color|-bce|-it|-s)*$'
    ....    
    elseif $TERM =~# '\v^tmux(-\d*color|-bce|-it|-s)*$'

The most common problem with detecting the terminal type correctly is a misconfigured TERM variable. If your TERM doesn't match the above patterns, fixkey won't correctly detect your use of tmux. fixkey is conservative in what it accepts, so if your TERM is something like tmux-some-new-words-here, please let me know so I can research how to support the new terminal type.

The next thing to check is whether fixkey has correctly detected your use of tmux. From within vim, you can check this variable:

:echo g:Fixkey_termType

This should yield screen or tmux (depending on your original TERM setting). If this is anything else, fixkey has not properly detected your terminal type.

When properly detected, fixkey provides two settings each for the <Home> and <End> keys. You can check them by entering the following four command in Vim:

:set <home>
:set <xhome>
:set <end>
:set <xend>

The results should be the following when fixkey has correctly detected your terminal:

t_kh <Home>      ^[[1;*H
     <xHome>     ^[[1~
t_@7 <End>       ^[[1;*F
     <xEnd>      ^[[4~

vim uses two separate settings for certain keys because of the wide variety of key encodings found on various terminals. The <xhome> and <home> settings accommodate tmux when pressing <Home>, and the setting for <home> accommodates that key when pressed with modifiers.

You can test out your terminal by following the steps found in doc/fixkey.txt in the section "3.9 Terminal testing", where you'll be able to see the actual codes your terminal is providing as well as whether fixkey is working (especially via `:runtime scripts/fixkeytest.vim).

RobinJadoul commented 8 years ago

TERM is set to tmux, as is Fixkey_termType. <home>, <xHome>, <End> and <xEnd> are indeed as described.

With the terminal testing, the modifier keys seem to work but not the unmodified home/end keys. The actual keycode that seems to get sent (by ^v then home/end in insert mode) for home is ^[[1~ and ^[[4~ for end.

drmikehenry commented 8 years ago

That's unexpected :-( Your key codes are what I'd expect, but if Fixkey:termType is set to tmux, I'd have expected everything to work. Do the values for <home>, <xhome>, <end>, and <xend> match those in my previous comment? Which version of vim are you running?

RobinJadoul commented 8 years ago

The values match your comment, but if home gives ^[[1~ and <home> is set to ^[[1;*H, that doesn't match, does it?

Vim 7.4.1907

drmikehenry commented 8 years ago

Vim maps the keycodes for both <home> and <xhome> to the actual key <Home>. It shouldn't matter which one holds which keycode. Because the unmodified and modified keys send such different codes, both <home> and <xhome> are required to support everything. You could try swapping their values to see what happens, but in my understanding that shouldn't help. I've got to head into work, and I won't have time for a couple of days to look at this. But please let me know what you find out, and I'll try to help you get to the bottom of it.

RobinJadoul commented 8 years ago

Swapping <home> with <xHome> results in home working but the home with modifier combinations no longer working. Setting both <home> and <xHome> to ^[[1~ has the same effect (normal keys working, but not with modifiers) Setting both to ^[[1;*H is the same as the original configuration (modifiers working, normal usage not)

Thanks for the help

RobinJadoul commented 8 years ago

Strangely enough, running with export TERM=screen-256color (inside of tmux, without modifying anything else) does work properly, but gives problems with italics in my color theme

drmikehenry commented 8 years ago

Thanks for pointing that out explicitly. I hadn't thought to double-check my own TERM variable. I just use the system defaults on my Ubuntu system, and it chooses screen for the value of TERM, which explains why things work for me. I suspect I never tried all of the keys when TERM=tmux, and instead just verified that fixkey would properly detect that case and configure the same as for screen. Something funny must be going on inside of vim itself. I ran a quick test this morning to disable all plugins like this: sh TERM=screen vim -u NONE '+set nocp' TERM=tmux vim -u NONE '+set nocp' When using TERM=screen, I was able to make the keys work, but with TERM=tmux, I couldn't. I'm again out of time today, but I wanted to at least know I'm seeing the problem as well.

drmikehenry commented 8 years ago

For some reason, using TERM=tmux causes Vim to set the terminal option <DecMouse> to ^[[, whereas when TERM=screen Vim leaves it unset. This sequence conflicts with the setting for <home>=^[[1;*H. When I delete the option via :set <DecMouse>=, things appear to work correctly for the <Home> key (with and without modifiers). I haven't yet had time to figure out what's different in the termcap database for the two values of TERM, and whether that accounts for Vim's choice to treat them differently. I found this difference by executing :set termcap to view all of the termcap-related settings in Vim. Those in the section "Terminal Keys" are the ones that ought to matter for key code interpretation. I get these values:

; For TERM=screen:
     <Mouse>     ^[[M

; For TERM=tmux:
     <DecMouse>  ^[[
     <NetMouse>  ^[}
     <Mouse>     ^[MG

I haven't tested actual mouse operation yet, but the setting for <Mouse> in the tmux case should probably also change to the value for the screen case, and <NetMouse> should also be deleted.

drmikehenry commented 8 years ago

Vim has some compiled-in knowledge that screen has an xterm-compatible mouse. In os_unix.c there is this logic:

    int
use_xterm_like_mouse(char_u *name)
{
    return (name != NULL
        && (term_is_xterm
        || STRNICMP(name, "screen", 6) == 0
        || STRICMP(name, "st") == 0
        || STRNICMP(name, "st-", 3) == 0
        || STRNICMP(name, "stterm", 6) == 0));
}

When TERM=screen, the above function causes Vim to :set ttymouse=xterm which changes the <Mouse> setting to the expected ^[[M and prevents the setting of both <DecMouse> and <NetMouse>.

A near-term work-around for this problem is to manually set ttymouse in your .vimrc whenever Vim is running within tmux:

if $TERM =~# '^tmux'
    set ttymouse=xterm
endif

Longer-term I'll ask on the Vim mailing list to see if Bram wants to add support for tmux in use_xterm_like_mouse(), then decide what kind of documentation and/or work-around to put into fixkey.

RobinJadoul commented 8 years ago

Well, at least it works, thanks

drmikehenry commented 8 years ago

I didn't get any traction on the Vim mailing list to get this fixed in Vim itself, but I've added the work-around logic into Fixkey 0.3.8.

drmikehenry commented 3 years ago

For reference, Vim v8.0.0030 (2016-10-12) added support for setting ttymouse=xterm for values of $TERM starting with tmux. Fixkey version v0.3.13 (2021-02-18) also changes the above-mentioned work-around slightly: instead of unconditionally setting ttymouse=term, Fixkey now does nothing if ttymouse is non-empty. This avoids clobbering a user-specified setting (e.g., ttymouse=sgr, which some users find preferable when using Tmux).