Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do the <M-S-hjkl> mappings work natively on Mac? #18

Open
gsavovski opened this issue Oct 24, 2015 · 7 comments
Open

Do the <M-S-hjkl> mappings work natively on Mac? #18

gsavovski opened this issue Oct 24, 2015 · 7 comments

Comments

@gsavovski
Copy link

Thanks for the great plugin.

I'm trying hard to get it to work on a mac in iterm2 with vim version 7.4.488.
My .vimrc is pretty big so I'm eliminating any possible conflicts by using a plain vanila .vimrc
with nothing in it but your plugin.
None of the <M mappings work for me.

Am I missing some obvious thing specific to Mac. Anybody else has/had this issue?

I saw that there is a possibility to set your own mappings using the 'sexp-explicit-mappings' directive.
But I like the default mappings so want to stick to those..

Thanks

@justinmk
Copy link

Mapping meta does not work in the terminal because Vim cannot tell the difference between meta and esc. Neovim in the terminal works fine with meta maps (as well as <esc> map), but it means that the opposite issue occurs: neovim/neovim#2017

@guns
Copy link
Owner

guns commented Oct 24, 2015

Hi @gsavovski,

I make Meta mappings work in my terminal by explicitly setting them on
startup.

For example, if your terminal sends \033a when you press <M-a> on your
keyboard, you can teach vim this keystroke with:

execute "set <M-a>=\<Esc>a"

Therefore, to make <M-…> work in a terminal that sends \033:

" Timeout quickly on key codes to differentiate from normal <Esc>
set ttimeout ttimeoutlen=0

" Special named keys that cause problems when used literally
let namedkeys = { ' ': 'Space', '\': 'Bslash', '|': 'Bar', '<': 'lt' }

" Map Alt + ASCII printable chars
for n in range(0x20, 0x7e)
    let char = nr2char(n)
    let key  = char

    if has_key(namedkeys, char)
        let char = namedkeys[char]
        let key  = '<' . char . '>'
    endif

    " Escaped Meta (i.e. not 8-bit mode)
    "  * Esc-[ is the CSI prefix (Control Sequence Introducer)
    "  * Esc-O is the SS3 prefix (Single Shift Select of G3 Character Set)
    if char !=# '[' && char !=# 'O'
        try
            execute 'set <M-' . char . ">=\<Esc>" . key
        catch
        endtry
    endif
endfor

unlet namedkeys n key char

I've always meant to package this bit of vim voodoo into a plugin, but never
got around to it. In fact, when I originally wrote vim-sexp, I had been using
this setup for so long that I forgot that <M-…> does not work in vim by
default.

Hence https://github.com/tpope/vim-sexp-mappings-for-regular-people

:)

EDIT (removed discussion of binding <4-…>, simplified code example):

@justinmk just brought up a good point: this will cause <Esc> to behave
badly unless we set ttimeout and ttimeoutlen:

set ttimeout ttimeoutlen=0

Setting ttimeout{,len} can have its own issues, but I don't find it to be a
problem in practice. You can increase ttimeoutlen if you are using Vim over
an especially slow network connection.

In truth, none of this has personally never bothered me as I use <C-c> in
place of <Esc>.

Hope this helps!

Thanks for the reminder @justinmk!

@guns
Copy link
Owner

guns commented Oct 24, 2015

@justinmk

Oops, forgot about that side effect. Appending my first post now...

@guns
Copy link
Owner

guns commented Oct 24, 2015

Okay, I've updated my comment with discussion of ttimeout{,len}.

It's surely a hack, but a serviceable one nonetheless.

@guns
Copy link
Owner

guns commented Oct 24, 2015

@gsavovski

One more thing I forgot to mention: Meta mappings work by default in vim if
you can configure your terminal to set the 8th bit on meta/alt.

Most terminals can be configured to do this, but often do not do it by
default. I imagine iTerm has this option as well. IIRC, the default OS X
Terminal also has this option.

@gsavovski
Copy link
Author

Hi @justinmk

Thanks for the kind explanation.

I actually remembered that I never could
use the Alt/Meta and Command keys since
I didn’t have any mappings for them in vimrc.

Hi @guns,

Thanks for opening this new door :-)

I already had set in my iTerm2 that the left option
acts as (+Esc).
When I press any of the combination
in terminal by catting the output I get:

-=} cat
^[H^[J^[K^[L

So I tried explicitly setting:

execute "set =^[J"
execute "set =^[K"
execute "set =^[H"
execute "set =^[L”

The ASCII code for ‘^[‘ is ‘\094 \091’.

Then I just put your code snippet in my vimrc and
it really worked. I can not even believe it :-)
Thank you so much!

Few more questions bug me..

Why did the explicit setting I mention above didn’t work?
Out of curiosity looking at your modifiers.vim code you have a lots
of mappings using the arrow keys, what do you accomplish doing that?
And lastly what do you mean by rarely used <4-…> mapping to be used as super?
Is that the actual number 4?

Thanks again this is great :-)

By the way the plugin already worked great in MacVim but
I'm much more of terminal user, therefore this is super exciting..

@guns
Copy link
Owner

guns commented Oct 24, 2015

I already had set in my iTerm2 that the left option acts as (+Esc).

Sounds like turning this off might enable meta-sets-top-bit mode, which is
really the best no-hack option if you just want to enable meta keys in your
terminal. You should give it a try!

So I tried explicitly setting:

execute "set =^[J"
execute "set =^[K"
execute "set =^[H"
execute "set =^[L”

The ASCII code for ‘^[‘ is ‘\094 \091’.

Why did the explicit setting I mention above didn’t work?

The ^[ is actually the standard printable representation for ASCII 033
(Escape). This character can be produced with the Escape key, or by pressing
<C-[>. Actually, the first 32 unprintable ASCII control characters can be
produced by pressing Ctrl and the corresponding ASCII equivalent 0x40 up the
table:

Ctrl + @ (0x40) -> 0x00 (Other keys can send NUL; I like Ctrl + Space)
Ctrl + A (0x41) -> 0x01
Ctrl + B (0x42) -> 0x02
Ctrl + C (0x43) -> 0x03
…
Ctrl + _ (0x5f) -> 0x1f

Of course, we don't type Ctrl-Shift-C when we want to send interrupt
through a terminal, so the actual key sent is upper cased when the Control
modifier is active. This convenience is why Ctrl-a and Ctrl-Shift-a
are indistinguishable in most terminal programs. Lots of people find this
annoying, but I personally enjoy this feature.

Here is the relevant bit in vim:

https://github.com/vim/vim/blob/60cce2f/src/ascii.h#L40-L41

#define Ctrl_chr(x) (TOUPPER_ASC(x) ^ 0x40) /* '?' -> DEL, '@' -> ^@, etc. */
#define Meta(x)     ((x) | 0x80)

Here we can also see why configuring your terminal to set the top bit when
Meta is active makes Meta mappings work out of the box.

Then I just put your code snippet in my vimrc and
it really worked. I can not even believe it :-)

I've edited my comment again to remove an errant debugging echo string(), so
you may want to remove that from your vimrc.

You've convinced me to start work on packaging this up as a plugin since it
does not seem to be common knowledge. It is in the documentation, but it's
easy to miss: :help :set-termcap.

Out of curiosity looking at your modifiers.vim code you have a lots of
mappings using the arrow keys, what do you accomplish doing that?

It allows mapping Modifier + Arrow keys. I don't ever find myself touching the
arrow keys, so it was mostly a way to experiment with setting key codes.

And lastly what do you mean by rarely used <4-…> mapping to be used as super?
Is that the actual number 4?

Yes, the <4- modifier is actually a mouse event modifier, but you can
bind it in regular mappings. For example, I configure my terminal to send
\033\007… when I type Super + …, then I map this sequence to produce the
corresponding <4-…>:

execute "map  <special> \<Esc>\<C-g>… <4-…>"
execute "map! <special> \<Esc>\<C-g>… <4-…>"

Now this <4-…> key can represent Super + … in your vimrc:

map <4-s> :<C-u>update<CR>

This is my favorite Vim hack, but it has the nasty side effect of borking
<Esc>, which is why I retracted my discussion of it.

Like I mentioned before, I use Ctrl-C as my escape anyway, so this does not
bother me.

I suspect there is a way to abuse the termcap key code system to accomplish
the same without this downside. If I find one I'll report back here.

By the way the plugin already worked great in MacVim but I'm much more of
terminal user, therefore this is super exciting..

Good to know. I compile vim with --disable-gui, so I am very unfamiliar with
GUI vim builds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants