Vim icon indicating copy to clipboard operation
Vim copied to clipboard

Added Langmap Feature

Open Opisek opened this issue 2 years ago • 10 comments

What this PR does / why we need it This pull request implements the langmap feature of Vim. It's an essential accessibility feature for people who use an alternate keyboard layout like Dvorak, Colemak, or a layout specific to a language like Greek or Russian.

It works by specifying the map under vscode.langmap in Code's JSON settings. Example langmap for Greek:

ΑA,ΒB,ΨC,ΔD,ΕE,ΦF,ΓG,ΗH,ΙI,ΞJ,ΚK,ΛL,ΜM,ΝN,ΟO,ΠP,QQ,ΡR,ΣS,ΤT,ΘU,ΩV,WW,ΧX,ΥY,ΖZ,αa,βb,ψc,δd,εe,φf,γg,ηh,ιi,ξj,κk,λl,μm,νn,οo,πp,qq,ρr,σs,τt,θu,ωv,ςw,χx,υy,ζz

Example langmap for Dvorak:

'q,\\,w,.e,pr,yt,fy,gu,ci,ro,lp,/[,=],aa,os,ed,uf,ig,dh,hj,tk,nl,s\\;,-',\\;z,qx,jc,kv,xb,bn,mm,w\\,,v.,z/,[-,]=,\"Q,<W,>E,PR,YT,FY,GU,CI,RO,LP,?{,+},AA,OS,ED,UF,IG,DH,HJ,TK,NL,S:,_\",:Z,QX,JC,KV,XB,BN,MM,W<,V>,Z?

You may find the exact format under :help langmap in Vim.

Keystrokes are then remapped based on the passed langmap, unless they're to be interpreted as text. Most frequently, one would use this feature to at least remap the movement keys to be at the physical positions of the "hjkl" keys on the keyboard, whilst still being able to type with one's chosen layout.

Which issue(s) this PR fixes Feature Request #2217

Special notes for your reviewer I have made sure to keep the changes to working code minimal. Additionally, no remapping is called if the passed langmap is an empty string (default value). That way, no unexpected behaviour or performance penalty should be introduced, unless you actively override the default value in your settings. Furthermore, I'm willing to write unit tests for this feature in the future.

Opisek avatar Aug 15 '23 22:08 Opisek

It would be nice to also support the from:to syntax specified in help langmap:

2.  A list of "from" characters, a semi-colon and a list of "to"
           characters.  Example: "abc;ABC"
       Example: "aA,fgh;FGH,cCdDeE"```

Also being able to pull the setting from .vimrc if applicable would be very convenient!

Thanks for making this PR, been wanting this feature for a while! Hopefully it gets approved soon..

kiwirm avatar Sep 12 '23 03:09 kiwirm

It's completely compliant with how vim parses langmap, including the "from to" syntax. I also believe it should already work with .vimrc but let me test that when I'm back home in a few days.

Opisek avatar Sep 12 '23 06:09 Opisek

Hmm, my colemak from:to langmap doesn't seem to work here, but works fine in vim: "vim.langmap": "qwfpgjluy\\;arstdhneiozxcvbkmQWFPGJLUY:ARSTDHNEIOZXCVBKM;qwertyuiopasdfghjkl\\;zxcvbnmQWERTYUIOPASDFGHJKL:ZXCVBNM",

If I convert it to the other format however, it works fine: "vim.langmap": "qq,ww,fe,pr,gt,jy,lu,ui,yo,\\;p,aa,rs,sd,tf,dg,hh,nj,ek,il,o\\;,zz,xx,cc,vv,bb,kn,mm,QQ,WW,FE,PR,GT,JY,LU,UI,YO,:P,AA,RS,SD,TF,DG,HH,NJ,EK,IL,O:,ZZ,XX,CC,VV,BB,KN,MM",

kiwirm avatar Sep 12 '23 07:09 kiwirm

Will check the bug, thanks for reporting!

Opisek avatar Sep 12 '23 07:09 Opisek

I've identified and fixed the issue with parsing, but I'm yet to check if my code already works with .vimrc @ryan-mooore

Opisek avatar Sep 22 '23 19:09 Opisek

All works beautifully for me now 👍

kiwirm avatar Oct 10 '23 20:10 kiwirm

Is there any hope on getting this merged? @J-Fields

Opisek avatar Nov 22 '23 22:11 Opisek

Mind adding a few test cases?

Done.

One annoyance I'm not happy with yet is the need for 14eba0bd.

Basically, Vim handles registers separetly from other <character>-like directives when it comes to remapping:

  • When for example searching for a character, it must not be langmapped: Assuming a Greek langmap, θθ should become and not ff.
  • When using registers, the register must be langmapped, otherwise you'd be trying to use an invalid register (e.g. the register θ does not exist).

As is right now, there is no way to distinguish mappings like f<character> from @<character>, so I have to manually go to all the places that registers are used and do the mapping logic there.

If instead something like @<register> or @<r-character> could be introduced, then the central langmap logic could just handle it all. That's how we ended up doing it in codemirror-vim.

(Side note: Why does recording a macro use q<alpha>, but playing @<character>? What's the difference?)

Opisek avatar Apr 08 '24 12:04 Opisek

If instead something like @<register> or @<r-character> could be introduced, then the central langmap logic could just handle it all.

Yeah adding <register> sounds good to me.

(Side note: Why does recording a macro use q<alpha>, but playing @<character>? What's the difference?)

I'm not sure, only thing that really comes to mind is it may be a hacky way to ensure q/ and q? have the right mappings.

J-Fields avatar May 25 '24 21:05 J-Fields

@J-Fields I changed the code accordingly. I ended up having to introduce <register> and <macro> separately. This is due to some edge cases with macro recording, which used <alpha> and <number> instead of <character>, as previously mentioned. Using just <register> caused some issues with obscure tests concerning remapping that I could not decipher.

With the current setup, all tests are passing, and the branch is up-to-date with upstream.

Opisek avatar Aug 11 '24 08:08 Opisek