John Richfield
John Richfield

Reputation: 141

Remap arrow keys onto JKLI whenever holding down a certain modifier key

I'm just wondering if there's a way that I can hold down the control key or something and use my jkli keys as arrow keys. I think it will be easier to program. Is that possible? Thanks.

Upvotes: 11

Views: 8863

Answers (10)

mister.durden
mister.durden

Reputation: 23

Here's how to do it with the V2 version of AHK:

#Requires AutoHotkey v2.0

; Alt + I for Up Arrow
Alt & i:: {
    Send("{Up}")
}

; Alt + J for Left Arrow
Alt & j:: {
    Send("{Left}")
}

; Alt + K for Down Arrow
Alt & k:: {
    Send("{Down}")
}

; Alt + L for Right Arrow
Alt & l:: {
    Send("{Right}")
}

Upvotes: 0

enjayes
enjayes

Reputation: 101

This solution is based on the helpful posts of nafzal, Hans Winterhalter and Edi Sugiarto. Though the OP specified any modifier, his examples referred to the ctrl key as the modifier. In the context of bulk text touch typing, a modifier in the home line would be the most convenient. Hans Winterhalter's solution used a function in Hotkeys to 'map' the Capslock key to a valid modifier key. Following mapping in Powertoy's Keyboard Manager (Suggested by Edi Sugiarto) worked for me. New to Keyboard Manager, I was pleasantly surprised by the following. 1. A non-modifier key (say CapsLock) can be mapped to a Modifier key (say Alt). 2. If the pseudo modifier key's original functionality(CapsLock) is useful in some context it can be mapped to an unused key (in my case the Apps/Menu key). 3. Keyboard short cuts can now setup using the (Modifier)+(letter) shortcut template (Say Alt+j to move cursor left). 4. The Apps/Menu key can be used to instigate CapsLock functionality if and when required. Edit- Addendum: In AutoHotkey capslock & j::Send {Left} capslock & l::Send {Right} capslock & i::Send {Up} capslock & k::Send {Down} seems to work, and CapsLock toggle key function on its own is not affected. I am a novice, so am I missing something?

Upvotes: 0

webdev4422
webdev4422

Reputation: 157

This autohotkey script mostly based on nafzal and Hans Winterhalter answers (great appreciation). Crucial difference is in "modifier key". If you map "modifier key" to Alt or Ctrl, sometimes it cause misuse functionality in apps that rely on this keys, so you will encounter unexpected behaviour. Remmaping "modifier key" to "unreal key", key that does not physically exists on current keyboard, makes it work like "Fn key" (1). Pressing this key will not modify, nor interrupt any other keys (like Win, Alt, Ctrl, Shift, etc) and you will be able to use any combination of keys. To remap "modifier key" you need SharpKeys or manual edit Windows Registry (2).

Here is example of "unreal key" (AHK special key (3) ), the one - that not exists on my keyboard, remapped to Right Alt.

It is conviniet to put arrow keys similar to vim "hjkl", but with shift to right - "jkl;" so fingers are always on typing position, plus additional keys.

With autostartup (4) - it work like a charm and reduce overhead of configuring different text editors, browsers, terminals, etc.

There is exception - it will not work in some administrative apps (5).

Remarks:

  1. There are no possible ways to remap real Fn key, at least without modifing keyboard driver or PCB. https://superuser.com/questions/65/remap-fn-to-another-key

  2. Detailed guide for editing Windows Registry manually. https://isenselabs.com/posts/keyboard-key-kills-and-remaps-for-windows-users

  3. Detailed guide for using AHK special keys. https://www.autohotkey.com/docs/KeyList.htm#SpecialKeys

  4. Make script to autostartup. https://www.autohotkey.com/docs/FAQ.htm#Startup

  5. Task Manger, Regedit Editor, Admin PowerShell, etc are administrative apps. Run ahk with admin right to work. Run as Administrator

     MoveCursor(key) {
       control := GetKeyState("CONTROL","P")
       shift := GetKeyState("SHIFT","P")
       alt := GetKeyState("ALT","P")
       win := GetKeyState("LWIN","P")
       ctrlShift := control && shift
       ctrlAlt := control && alt 
       altShift := alt && shift
       ctrlAltShift := control && alt && shift    
    if ctrlAltShift {
       Send, ^!+%key%
    } else if altShift {
       Send, !+%key%
    } else if ctrlShift {
       Send, ^+%key%
    } else if ctrlAlt {
       Send, ^!%key%
    } else if control {
       Send, ^%key%
    } else if shift {
       Send, +%key%
    } else if alt {
       Send, !%key%
    } else if win {
       Send, #%key%
    } else {
       Send, %key%
    }}
    SC163 & j::MoveCursor("{LEFT}")
    SC163 & k::MoveCursor("{DOWN}")
    SC163 & l::MoveCursor("{UP}")
    SC163 & `;::MoveCursor("{RIGHT}")
    SC163 & m::MoveCursor("{HOME}")
    SC163 & ,::MoveCursor("{PGDN}")
    SC163 & .::MoveCursor("{PGUP}")
    SC163 & /::MoveCursor("{END}")
    SC163 & BS::MoveCursor("{DEL}")
    ;SC163 & u::BS.SetBrightness(-10)
    ;SC163 & i::BS.SetBrightness(10)
    ;SC163 & o::Volume_Down
    ;SC163 & p::Volume_Up
    
  • List item

Upvotes: 0

Edi Sugiarto
Edi Sugiarto

Reputation: 71

My best way of doing this in Windows OS is by installing Microsoft PowerToys. In the keyboard section, remap shortcut: Left ALT + "I J K L" as Up, Left, Down, Right

This way, whenever Left ALT is Held, IJKL will function as arrow keys

Further customization, I also liked to use: Left ALT + ", . /" as Home, End, and Apps/Menu

Upvotes: 0

RobotCharlie
RobotCharlie

Reputation: 1278

I re-mapped my arrow keys (on Mac) using Hammerspoon and documented in a GitHub repo https://github.com/RobotCharlie/key-remapping-hammerspoon

Upvotes: 0

Andrei Tonkikh
Andrei Tonkikh

Reputation: 11

I tried numerous AutoHotKey scripts from the internet to solve this issue, including all versions mentioned in previous answers to this question. Unfortunately, none of them worked properly. Some of them appear to work at first, but have subtle issues.

After spending quite some time on this issue, I finally managed to create a version that seems to work (kind of).

Posting the code here for those who will find this page by googling.

With this script, ijkl will work as the arrow keys as long as right alt is pressed. It seems to work well in combination with shift and control.

However, the downside is that right alt loses its original function. It is not a problem for me because I only use left alt. If you don't want to sacrifice right alt, you can replace "RAlt" with "CapsLock" and it will work as well.

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

; Arrows & navigation

Hotkey, *i, Off
Hotkey, *j, Off
Hotkey, *k, Off
Hotkey, *l, Off

*RAlt::
    Hotkey, *i, on
    Hotkey, *j, on
    Hotkey, *k, on
    Hotkey, *l, on
return

*RAlt up::
    Hotkey, *i, off
    Hotkey, *j, off
    Hotkey, *k, off
    Hotkey, *l, off
return

*i::send {blind}{up}
*j::send {blind}{left}
*k::send {blind}{down}
*l::send {blind}{right}

Hans Winterhalter's version almost works. However, at least on my pc, if I press and hold alt+shift+j, then it starts selecting text (as expected), but if I hold it long enough, at some point, the shortcut doesn't work and it just prints letter J, destroying the selected text, which is definitely not desirable.

Upvotes: 1

Hans Winterhalter
Hans Winterhalter

Reputation: 51

Also using AutoHotKey, I really wanted to have key navigation for CAPSLOCK, which is trickier than the special modifier keys (Ctrl, Alt, etc). The trick ended up being using the built-in function GetKeyState(...).

I am sharing my results below. The autohotkey script below is based off of nafzal's answer here, but I made it a bit cleaner :)

; Main Navigation
CAPSLOCK & j::MoveCursor("{LEFT}")
CAPSLOCK & l::MoveCursor("{RIGHT}")
CAPSLOCK & i::MoveCursor("{UP}")
CAPSLOCK & k::MoveCursor("{DOWN}")
CAPSLOCK & h::MoveCursor("{HOME}")
CAPSLOCK & `;::MoveCursor("{END}")
CAPSLOCK & BACKSPACE::Send {DELETE}

; Navigation Combos
MoveCursor(key) {
    shift := GetKeyState("SHIFT","P")
    control := GetKeyState("CONTROL","P")
    controlShift := control && shift

    if controlShift {
        Send, ^+%key%
    }
    else if shift {
        Send, +%key%
    }
    else if control {
        Send, ^%key%
    }
    else {
        Send, %key%
    }
}

; Alternatively, using Alt...
ALT & j::MoveCursor("{LEFT}")
ALT & l::MoveCursor("{RIGHT}")
ALT & i::MoveCursor("{UP}")
ALT & k::MoveCursor("{DOWN}")
ALT & h::MoveCursor("{HOME}")
ALT & `;::MoveCursor("{END}")
ALT & BACKSPACE::Send {DELETE}

Upvotes: 5

nafzal
nafzal

Reputation: 131

Here's the .ahk script I use.

It remaps arrow keys to ALT + I / J / K / L.

NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

; AHK Command       ; key   = Effect        (Description)   

; ALT Keypress Implied for all below

!i::Send {UP}       ; i UP          (Cursor up line)
!k::Send {DOWN}     ; k DOWN            (Cursor down line)

!j::Send {LEFT}     ; j LEFT        (Cursor left one character)
!l::Send {RIGHT}    ; l RIGHT       (Cursor right one character)

!h::Send {HOME}     ; h     ALT + RIGHT (Cursor to beginning of line)
!;::Send {END}      ; ; ALT + LEFT  (Cursor to end of line)

!u::Send ^{HOME}    ; h     SHIFT + HOME    (Cursor to beginning of document)
!o::Send ^{END}     ; o SHIFT + END (Cursor to end of document)

; CTRL + ALT Keypress Implied for all below

!^j::Send ^{LEFT}   ; j     CTRL + LEFT (Cursor left per word)
!^l::Send ^{RIGHT}  ; l CTRL + RIGHT    (Cursor right per word)

; SHIFT + ALT Keypress Implied for all below

!+i::Send +{UP}     ; i SHIFT + UP  (Highlight per line)
!+k::Send +{DOWN}   ; k SHIFT + DOWN    (Highlight per line)

!+j::Send +{LEFT}   ; j SHIFT + LEFT    (Highlight per character)
!+l::Send +{RIGHT}  ; l SHIFT + RIGHT   (Highlight per character)

!+h::Send +{HOME}   ; h SHIFT + ALT + LEFT  (Highlight to beginning of line)
!+;::Send +{END}    ; ; SHIFT + ALT + RIGHT (Hightlight to end of line) 

!+u::Send ^+{HOME}  ; u SHIFT + CTRL + HOME (Highlight to beggininng of document)
!+o::Send ^+{END}   ; o SHIFT + CTRL + END  (Hightlight to end of document) 

; SHIFT + CTRL + ALT Keypress Implied for all below

!+^j::Send +^{LEFT}     ; j SHIFT + CTRL + LEFT (Highlight per word)
!+^l::Send +^{RIGHT}    ; l SHIFT + CTRL + RIGHT    (Hightlight per word)

!+^i::Send +!{UP}   ; i SHIFT + ALT + UP    (Multiply cursor up)
!+^k::Send +!{DOWN} ; k SHIFT + ALT + DOWN  (Multiply cursor down) 

; CTRL + SHIFT Keypress Implied for all below

+^i::Send +^{UP}
+^k::Send +^{DOWN}

Everything after a ; is a comment.

To decipher, use: https://autohotkey.com/docs/Hotkeys.htm

Upvotes: 13

RJFalconer
RJFalconer

Reputation: 11721

Simple autohotkey script.

Ctrl+T to turn on toggle, then IJKL behave as arrow keys until Ctrl+T is pressed again.

#SingleInstance ignore
Hotkey, I, Off
Hotkey, J, Off
Hotkey, K, Off
Hotkey, L, Off

^t::
    Hotkey, I, Toggle
    Hotkey, J, Toggle
    Hotkey, K, Toggle
    Hotkey, L, Toggle
return

I::
    Send {Up}
return

J::
    Send {Left}
return

K::
    Send {Down}    
return

L::
    Send {Right} 
return

(Although I'd recommend learning vim HJKL approach instead!)

Upvotes: 0

John Richfield
John Richfield

Reputation: 141

After a bit of trial and error, I was able to make this. I'm putting it on here so anyone who has the same question can use this code.

!j::Send {Left}
!k::Send {Down}
!l::Send {Right}
!i::Send {Up}

Upvotes: 3

Related Questions