replit / codemirror-vim

Vim keybindings for CM6
https://www.npmjs.com/package/@replit/codemirror-vim
MIT License
268 stars 27 forks source link

Added Langmap Feature #151

Closed Opisek closed 6 months ago

Opisek commented 7 months ago

This pull request brings Vim's langmap feature over to CodeMirror. It resolves issue #145.

Short abstract of the reason behind this feature:

The purpose of a langmap is to allow typing in insert and replace mode using one's preferred keyboard layout, while still being able to use standard Vim mappings in normal and visual mode. This is crucial for people using other scripts like Greek and Cyrillic or using a different keyboard layout like Dvorak that would spread default bindings throughout the whole keyboard.

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.

The langmap(langmapString) function has been added to the Vim API. Calling it parses the provided string as specified by Vim's :help langmap. Additionally, a few unit tests have been written.

nightwing commented 6 months ago

Thank you, merged!

But only after merging did i notice the new code with remapControl. What is the reason of adding it, and how are users supposed to use it?

Opisek commented 6 months ago

Firstly, I initially forgot to also add the logic for remapping <C-β> into <C-b> for example, which is done by Vim by default.

Now, the reason why remapControl is in place, is to override this behaviour. This is sometimes needed, because Control is handled differently by certain browsers or other environments where CodeMirror runs, than by Vim.

A brief example: Some people who use layouts like Dvorak or Colemak tend to have system-wide Ctrl remapping so in my case Ctrl+k becomes Ctrl+v or Ctrl+j becomes Ctrl+c. How that's implemented is different per operating system. Still, it's basically the same idea as langmap but system-wide.

Vim handles this nicely, because it is not affected by that remapping. What Vim (from my experience at least) receives, is <C-k>, even though the system normally remaps that to Ctrl+v. Then it's langmapped internally to the expected <C-v>. So all in all, Vim does not "double remap" Control bindings.

The problem arises when browsers do interpret the Ctrl+k as Ctrl+v and pass it to CodeMirror as <C-v>, because in that case, it will be remapped again, causing double remapping.

Since it's a nieche and browser-dependent problem, I chose to default remapControl to true, because that's what you'd expect to happen 99.9% of the times. You would expect your <C-β> to be remapped to <C-b>. For the remaining cases, so for example if your system/browser already remaps it to <C-b> before it reaches CodeMirror, and you do not want it to be remapped again, you can turn that logic off.

Also, I just noticed that I left a console.log in line 1198 of vim.js.

nightwing commented 6 months ago

So it is ok that users won't have access to remapControl from vim command line, and it can be accessed only from javascript api?

In https://github.com/replit/codemirror-vim/pull/152 i have added support for set langmap=... from commandline and also, added automatic translation based on qwerty key code for non-ascii keys not included in langmap, (this was an old feature request for Russian).

Your opinion about this refactoring would be greatly appreciated.

Opisek commented 6 months ago

I think it's fine when it's only accessible though JavaScript API.

I'll check your changes by tomorrow.