lyokha / vim-xkbswitch

vim plugin for automatic keyboard layout switching in insert mode
MIT License
480 stars 23 forks source link

Discussion: Why do I need this plugin if I have `&keymap`? #35

Open doronbehar opened 7 years ago

doronbehar commented 7 years ago

Hello @lyokha,

I encountered your plugin while I saw it's extension on airline and I'm very impressed by it's features and documentation but I'm not sure I totally understand why would I need it.

Up until now, I used the vanilla &keymap setting of Vim and it was always enough for me. It even provides assistance in Normal mode as your plugin suggests to provide it as well (haven't succeeded yet in configuring it on my machine and with il keyboard layout).

One feature though which seems to be very promising is Custom keyboard layout switching rules. Vanilla Vim doesn't provides it I'm sure.

What am I missing?

lyokha commented 7 years ago

Hi @doronbehar, I cannot really list advantages (if there are any) of this plugin before keymap because I never used the latter :) But there is an important difference: vim-xkbswitch makes use of the system keyboard layout switcher, and this has valuable consequences:

  1. You switch layouts in the system way like any other application in your system does.
  2. Your current layout flag in the system tray shows current vim's layout always correctly.
  3. All layouts configured in the system (for example, I always have three: USA, Russian and Deutsch) are available in the vim out of the box (except Insert mode mappings, that can be configured in a number of ways if you need them).

And of course custom rules for layout switching, but I am afraid that nobody really uses them, except me :) I use them to seamlessly edit custom dictionaries like it's shown in the docs.

doronbehar commented 7 years ago

O.K, I have been thinking a lot about this subject, I read :h iminsert and I briefly read the code of this plugin and I have several questions:

lyokha commented 7 years ago
  1. Yes, exactly. IMappings stands for Insert Mode Mappings, and yes there are duplicates in the sense that when you, for example, have an Insert Mode mapping Ctrl-Q, then you'll want to use the same keystroke in the alternative layout (Vim won't translate this for you automatically as it does for its own keymap approach). And so...
  2. As soon as Vim won't translate them, this plugin does it on its own, creating a duplicate map Ctrl-Й for Russian winkeys layout (letter Q corresponds to letter Й there). The plugin translates all existing Insert Mode mappings for all alternative layouts listed in g:XkbSwitchIMappingsTr. The plugin has embedded support only for Russian winkeys layout. For other layouts you can define own mappings. To see configured Insert Mode mappings enter command

    :imap

    in the Vim command prompt. And yes, g:XkbSwitchIMappingsTr is for Insert Mode only. This plugin's aim is to keep the basic layout (normally, USA) in Normal mode, so it has very basic support there (see keymap assistance).

doronbehar commented 7 years ago

Great, now I understand.

As for Normal mode assistance, I'm not sure I understand how it's supposed to work. Take the following example:

If my understanding is correct, and my configuration is O.K, than I should be able to do so without switch layout after pressing f because &keymap is set to hebrew right? Here's what I added to my vimrc file:

let g:XkbSwitchKeymapNames = {'il' : 'hebrew'}
let g:XkbSwitchAssistNKeymap = 1
let g:XkbSwitchAssistSKeymap = 1

But I doesn't work, hope you could help me set it up.

lyokha commented 7 years ago

Try with

let g:XkbSwitchDynamicKeymap = 1

added. By some reason it does not work for me too, when it's not set.

lyokha commented 7 years ago

Ok, now I see how keymap assistance must work. Actually it's written in docs but it was surprisingly uneasy to remember how I implemented it and how it must work. There are two cases:

  1. Basic case. You have only one alternative layout: hebrew. Your settins in .vimrc are:

    set keymap=hebrew
    set iminsert=0
    set imsearch=0
    let g:XkbSwitchAssistNKeymap = 1    " for commands r and f
    let g:XkbSwitchAssistSKeymap = 1    " for search lines
    let g:XkbSwitchKeymapNames = {'il' : 'heb'}

    Here 'heb' is value of Vim's intrenal variable b:keymap_name. You can find its value in Vim's runtime files, e.g.

    grep -r keymap_name /usr/share/vim/vim80/
  2. Case of multiple layouts. For example, you're also using Russian or Deutch or whatever. In this case you need dynamic keymap assistance (as to me, I am using this even for one alternative layout).

    let g:XkbSwitchAssistNKeymap = 1    " for commands r and f
    let g:XkbSwitchAssistSKeymap = 1    " for search lines
    let g:XkbSwitchDynamicKeymap = 1
    let g:XkbSwitchKeymapNames = {'il' : 'hebrew'}

    Now you need 'hebrew' instead of 'heb' as it is now keymap name, not the b:keymap_name. You can find the keymap name as follows:

    grep keymap= /usr/share/vim/vim80/doc/hebrew.txt

I do not remember why these approaches map to different objects, probably it was the simplest possible implementation, or I just slightly mis-implemented this.

doronbehar commented 7 years ago

Great, let g:XkbSwitchDynamicKeymap = 1 worked for me too. Now, I do have another question though, it requires sometime to explain so allow me to divide it to 2 parts:

Experiment 1: Vanilla Vim

Let's take a look at what happens when you perform the following when no plugins or settings are loaded:

  1. Launch Vim with -u NONE.
  2. Switch the system's keyboard layout to ru.
  3. Insert a line with mostly Russian characters.
  4. Exit Insert mode.
  5. Switch the system's keyboard layout back to us.
  6. set keymap=russian-jcukenwin or whatever Russian Vim keymap you choose..
  7. Enter Insert mode again.
  8. Before putting any new Russian letters, switch the system's keyboard layout to ru even though you don't need to because &keymap is russion-*. Note: This is a crucial point to understand my question
  9. Try to insert the character ..

You should encounter the following confusion: you get Ю instead of . (according to my calculations) because vanilla Vim doesn't know/care your system's keyboard layout is ru, it just remaps keys. [1]

Experiment 2: Vim with xkbswitch

Up until here I hope you followed me. Before we continue, I don't know if you use airline but if so, you might want to enable the keymap extension: let g:airline#extensions#keymap#enabled = 1 for the following experiment. This way you can see the value of &keymap in your statusline all the time.

Now, let's do a similar process like in the steps described above but with your plugin enabled and g:XkbSwitchDynamicKeymap = 1:

  1. Launch Vim normally.
  2. Switch the system's keyboard layout to ru.
  3. Insert a line with mostly Russian characters.
  4. Exit Insert mode. At this point, you should be able to spot (with airline keymap extension enabled or with set keymap?) that &keymap is russian-* and your system's keyboard layout is us, that's great because this way we avoid the confusion explained above.
  5. Return to Insert mode.

The problem is this:

At this point, you should notice that your system's keyboard layout is ru [2]. But what about &keymap? It's still russian-* (you can check it without airline with <C-\><C-o>:set keymap?). As I understand it, &keymap should be empty when we return to Insert mode and our system's keyboard layout is ru, just like when we first started to write in Russian and &keymap was empty. And thus so we won't end up in a confusion as described in the 1st experiment.

Am I right?

The thing which seems even weirder to me, is that the problem/confusion (where you try to insert . and get Ю) doesn't happen, which us bringing to the conclusion that &keymap is infect empty after all, as it should.

Let's summarize

Notes

[1] Infect, it's a great example of somewhat common but easily solved confusion that your plugin solves. [2] meaning that your plugin does it's job :)

lyokha commented 7 years ago

What you have described is what I am really getting in my Vim too (except I have custom signalling for old Powerline plugin, not airline, but see below). And, surprisingly... what I am expecting to be. Actually, I do not see any confusion... Because the main indicator for me is not any plugin-based flag, but system tray! When you're talking about confusion with Ю and no ru indicator on the airline status bar, see at the system tray icon: it shows ru!

So I'm using the system tray icon as the main source of the layout info. Moreover, in my version of Powerline status icon (see an article in my blog about its implementation, though it's written in Russian) the icon is not shown in Insert Mode, because it is not relevant, as you correctly stated this! In other words, I regard the keymap icon in the Powerline/airline only as a hint what layout will be used for searching chars/words in Normal Mode only. The main info about layout is still the system tray icon. So I think that airline would better switch this off too in Insert Mode.

However, probably it makes sense to reset keymap when inserting Insert Mode as you proposed. So I'll look at this, however it won't anyway fix initial state in Insert Mode when layout is still unknown.

lyokha commented 7 years ago

Some addition. Answers to the 2 questions:

  1. The plugin does not reset keymap but it resets iminsert and imsearch that effectively disables keymap. Anyway, the value shown in the airline tray must be not value of keymap but rather system layout returned by the plugin method. When user first time enters Insert Mode, the plugin knows nothing about Insert Mode layout (this is an implementation detail): it only sets it when leaving Insert Mode.
  2. As I said, the airline indicator must show not keymap value (which is russian-jcukenwin actually), but the system layout, provided by this plugin API (ru, or il for Hebrew).
doronbehar commented 7 years ago

I'm afraid you misunderstood me regarding the &keymap airline status. It's a rather new extension contributed only lately to the airline project. See keymap.vim and the 5 top commits in this search.

What I meant was, that during the experiments above, you will be checking both the system tray indicating the system's keyboard layout (ru/us/il) and the airline's status with g:airline#extensions#keymap#enabled = 1 indicating hebrew/russion-jcukenwin or nothing at all. I didn't mean to enable g:airline#extensions#xkblayout#enabled = 1.

As for your answer to my 1st question:

lyokha commented 7 years ago

Now I remember why I supposed Vim's status line indicator to be useless in Insert Mode. Because it must show system layout, which can be changed during user's input, but Vim is unable to catch this system event and the indicator won't change. The only reasonable solution here seems to be timer-based polling, but this is ugly. However they could implement polling in airline. I have little time now, so I'll try briefly to answer your questions (I will get back to this after weekends):

  1. About switching off iminsert and keymap. Actually I am not an expert in keymap because I never actually used this. But Vim's doc says that setting keymap implies setting iminsert, so I hope that back way is also true. And I never experienced problems with my settings (I have keymap assistance on).
  2. Sorry.. Have to go. And my battery is almost down.
doronbehar commented 6 years ago

Sorry for the delay, would you like to keep on with the conversation?

lyokha commented 6 years ago

Yes! I remember that we were talking about keymap and vim-xkbswitch co-operation. To be honest, it looks like I did not understand your concerns well, because I have never used keymap in practice.

doronbehar commented 6 years ago

Well, when I first started this conversation I was confused regarding this plugin and whether it is actually filling a missing gap in vim's design but since you are now mentioning that you don't use the vanilla keymap option I guess it is a matter of taste. If someone is very used to his system-level switch input language keyboard shortcut and he doesn't want to remap another one for to change &keymap, then he'll enjoy your plugin very much. On the other hand, if one would like to use the unmodified features of Vim just as they are and perhaps spare a plugin from his configuration, he'll might choose not to use this plugin.

I think we both learned something from this conversation. Hope you enjoyed it is much as I did :).

lyokha commented 6 years ago

Yes, I learned a lot about keymap from our conversation, though I have never used this. I feel that your conclusions are very close to the truth, and the question of what to use: this plugin or keymap is mostly a matter of subjective choice.

But if you still have questions regarding implementation of this plugin (not how it compares to keymap!), please do not hesitate to ask me! Thank you!

doronbehar commented 6 years ago

You Too! Cheers :)