├── .gitattributes ├── .gitignore ├── ViNavigation.ahk └── readme.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | [Dd]ebug/ 46 | [Rr]elease/ 47 | *_i.c 48 | *_p.c 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.vspscc 63 | .builds 64 | *.dotCover 65 | 66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 67 | #packages/ 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | 76 | # Visual Studio profiler 77 | *.psess 78 | *.vsp 79 | 80 | # ReSharper is a .NET coding add-in 81 | _ReSharper* 82 | 83 | # Installshield output folder 84 | [Ee]xpress 85 | 86 | # DocProject is a documentation generator add-in 87 | DocProject/buildhelp/ 88 | DocProject/Help/*.HxT 89 | DocProject/Help/*.HxC 90 | DocProject/Help/*.hhc 91 | DocProject/Help/*.hhk 92 | DocProject/Help/*.hhp 93 | DocProject/Help/Html2 94 | DocProject/Help/html 95 | 96 | # Click-Once directory 97 | publish 98 | 99 | # Others 100 | [Bb]in 101 | [Oo]bj 102 | sql 103 | TestResults 104 | *.Cache 105 | ClientBin 106 | stylecop.* 107 | ~$* 108 | *.dbmdl 109 | Generated_Code #added for RIA/Silverlight projects 110 | 111 | # Backup & report files from converting an old project file to a newer 112 | # Visual Studio version. Backup files are not needed, because we have git ;-) 113 | _UpgradeReport_Files/ 114 | Backup*/ 115 | UpgradeLog*.XML 116 | 117 | 118 | 119 | ############ 120 | ## Windows 121 | ############ 122 | 123 | # Windows image file caches 124 | Thumbs.db 125 | 126 | # Folder config file 127 | Desktop.ini 128 | 129 | # Binary 130 | *.exe 131 | 132 | 133 | ############# 134 | ## Python 135 | ############# 136 | 137 | *.py[co] 138 | 139 | # Packages 140 | *.egg 141 | *.egg-info 142 | dist 143 | build 144 | eggs 145 | parts 146 | bin 147 | var 148 | sdist 149 | develop-eggs 150 | .installed.cfg 151 | 152 | # Installer logs 153 | pip-log.txt 154 | 155 | # Unit test / coverage reports 156 | .coverage 157 | .tox 158 | 159 | #Translations 160 | *.mo 161 | 162 | #Mr Developer 163 | .mr.developer.cfg 164 | 165 | # Mac crap 166 | .DS_Store 167 | 168 | ########## 169 | # VIM 170 | ########## 171 | 172 | # Swap files 173 | *.*~ 174 | -------------------------------------------------------------------------------- /ViNavigation.ahk: -------------------------------------------------------------------------------- 1 | ; ahk-vim-navigation.ahk 2 | ; Written by Jongbin Jung 3 | ; 4 | ; Incorporated some script from Model_Vim.ahk 5 | ; Written by Rich Alesi 6 | ; and Modified for AHK_L by Andrej Mitrovic 7 | ; (http://www.autohotkey.com/board/topic/41206-modal-vim/) 8 | ; 9 | ; Update (08/16/2014) 10 | ; Simplified script to take modifiers into account 11 | ; (see, http://www.autohotkey.com/board/topic/83755 12 | ; -using-an-arbitrary-key-as-a-modifier-without-sacrificing-it/) 13 | 14 | #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. 15 | SendMode Input ; Recommended for new scripts due to its superior speed and reliability. 16 | SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. 17 | 18 | ; Global variables 19 | inputNumber := " " 20 | lastCommand = {ShiftDown}{ShiftUp} 21 | 22 | ; Notification GUI {{{ 23 | notify(text, time = 2000) 24 | { 25 | #IfWinExist VIM-Mode commands 26 | resetGUI() 27 | #IfWinExist 28 | ; Set the flags for OSD 29 | Gui, 90:+AlwaysOnTop -Caption +ToolWindow +Disabled -SysMenu +Owner 30 | ; Add and set the OSD Text 31 | Gui, 90:Font, s10 bold 32 | Gui, 90:Add, Text, cAA0000, %text% 33 | ; OSD Background Color (Black) 34 | Gui, 90:Color, 000000 35 | Gui, 90:Show,NoActivate xCenter yCenter, VIM-Mode commands 36 | Sleep, %time% 37 | Gui, 90:Destroy 38 | return 39 | } ;}}} 40 | 41 | ; HotKey to Initiate VI-mode with Double-tap of Esc {{{ 42 | $Esc:: 43 | If (A_PriorHotKey = "$Esc" AND A_TimeSincePriorHotKey < 500) 44 | { 45 | ; Set the flags for OSD 46 | Gui, 99:+AlwaysOnTop -Caption +ToolWindow +Disabled -SysMenu +Owner 47 | ; Add and set the OSD Text 48 | Gui, 99:Font, s15 bold 49 | Gui, 99:Add, Text, cAA0000, VI-NORMAL (Esc to Exit) 50 | ; OSD Background Color (Black) 51 | Gui, 99:Color, 000000 52 | Gui, 99:Show,NoActivate x0 y10, VIM-Mode Activated 53 | } 54 | Else 55 | { 56 | SendInput {Esc} 57 | } 58 | Return ; }}} 59 | 60 | #IfWinExist VIM-Mode Activated ; {{{ 61 | 62 | ; ESC ends VIM-mode 63 | ESC:: 64 | { 65 | if (inputNumber != " ") 66 | { 67 | resetInputNumber() 68 | return 69 | } 70 | else 71 | { 72 | endVIM() 73 | return 74 | } 75 | } 76 | 77 | ; i(nput) end VIM-mode 78 | i:: 79 | { 80 | endVIM() 81 | return 82 | } 83 | 84 | ; Other input modes ... 85 | +i:: 86 | { 87 | SendInput {Home} 88 | endVIM() 89 | return 90 | } 91 | a:: 92 | { 93 | SendInput {Right} 94 | endVIM() 95 | return 96 | } 97 | +a:: 98 | { 99 | SendInput {End} 100 | endVIM() 101 | return 102 | } 103 | 104 | ; cursor movements 105 | h:: 106 | { 107 | SendInput {Left %inputNumber%} 108 | resetInputNumber() 109 | return 110 | } 111 | j:: 112 | { 113 | SendInput {Down %inputNumber%} 114 | resetInputNumber() 115 | return 116 | } 117 | k:: 118 | { 119 | SendInput {Up %inputNumber%} 120 | resetInputNumber() 121 | return 122 | } 123 | l:: 124 | { 125 | SendInput {Right %inputNumber%} 126 | resetInputNumber() 127 | return 128 | } 129 | 130 | ; page movements 131 | w:: 132 | { 133 | SendInput ^{Right %inputNumber%} 134 | resetInputNumber() 135 | return 136 | } 137 | b:: 138 | { 139 | SendInput ^{Left %inputNumber%} 140 | resetInputNumber() 141 | return 142 | } 143 | x:: 144 | { 145 | lastCommand = {Delete %inputNumber%} 146 | SendInput, %lastCommand% 147 | resetInputNumber() 148 | return 149 | } 150 | >:: 151 | { 152 | lastCommand = {ShiftDown}{LeftArrow}{LeftArrow}{RightArrow}{ShiftUp}{Tab}{Esc} 153 | SendInput, %lastCommand% 154 | resetInputNumber() 155 | return 156 | } 157 | <:: 158 | { 159 | lastCommand = {ShiftDown}{LeftArrow}{LeftArrow}{RightArrow}{ShiftUp}{ShiftDown}{Tab}{ShiftUp}{Esc} 160 | SendInput, %lastCommand% 161 | resetInputNumber() 162 | return 163 | } 164 | 0:: ; Add to the inputNumber if inputNumber != null, otherwise HOME 165 | { 166 | if (inputNumber != " ") 167 | { 168 | inputNumber = %inputNumber%0 169 | normalize(0) 170 | notify(inputNumber) 171 | return 172 | } 173 | else 174 | { 175 | SendInput {Home} 176 | resetInputNumber() 177 | return 178 | } 179 | } 180 | -:: 181 | { 182 | SendInput {End} 183 | resetInputNumber() 184 | return 185 | } 186 | $:: 187 | { 188 | SendInput {End} 189 | resetInputNumber() 190 | return 191 | } 192 | 193 | ; repeat 194 | .:: 195 | { 196 | SendInput, %lastCommand% 197 | resetInputNumber() 198 | return 199 | } 200 | 201 | ; selection movements with Shift 202 | +h:: 203 | { 204 | SendInput +{Left %inputNumber%} 205 | resetInputNumber() 206 | return 207 | } 208 | +j:: 209 | { 210 | SendInput +{Down %inputNumber%} 211 | resetInputNumber() 212 | return 213 | } 214 | +k:: 215 | { 216 | SendInput +{Up %inputNumber%} 217 | resetInputNumber() 218 | return 219 | } 220 | +l:: 221 | { 222 | SendInput +{Right %inputNumber%} 223 | resetInputNumber() 224 | return 225 | } 226 | +w:: 227 | { 228 | SendInput +^{Right %inputNumber%} 229 | resetInputNumber() 230 | return 231 | } 232 | +b:: 233 | { 234 | SendInput +^{Left %inputNumber%} 235 | resetInputNumber() 236 | return 237 | } 238 | +x:: 239 | { 240 | lastCommand = +{Delete} 241 | SendInput, %lastCommand% 242 | resetInputNumber() 243 | return 244 | } 245 | ):: 246 | { 247 | SendInput +{Home} 248 | resetInputNumber() 249 | return 250 | } 251 | _:: 252 | { 253 | SendInput +{End} 254 | resetInputNumber() 255 | return 256 | } 257 | 258 | ; Copy (Yank) / Cut (Delete) / Paste (Put) 259 | y:: 260 | { 261 | SendInput ^c 262 | resetInputNumber() 263 | return 264 | } 265 | p:: 266 | { 267 | SendInput ^v 268 | resetInputNumber() 269 | return 270 | } 271 | d:: 272 | { 273 | lastCommand = ^x 274 | SendInput, %lastCommand% 275 | resetInputNumber() 276 | return 277 | } 278 | 279 | ; Search with / 280 | /:: 281 | { 282 | SendInput ^f 283 | resetInputNumber() 284 | return 285 | } 286 | 287 | ; HotKey to VIM maps 288 | u:: 289 | { 290 | SendInput ^z 291 | resetInputNumber() 292 | return 293 | } 294 | 295 | ; Catch numbers to repeat commands 296 | $1:: 297 | { 298 | inputNumber = %inputNumber%1 299 | normalize(1) 300 | notify(inputNumber) 301 | return 302 | } 303 | 304 | $2:: 305 | { 306 | inputNumber = %inputNumber%2 307 | normalize(2) 308 | notify(inputNumber) 309 | return 310 | } 311 | 312 | $3:: 313 | { 314 | inputNumber = %inputNumber%3 315 | normalize(3) 316 | notify(inputNumber) 317 | return 318 | } 319 | 320 | $4:: 321 | { 322 | inputNumber = %inputNumber%4 323 | normalize(4) 324 | notify(inputNumber) 325 | return 326 | } 327 | 328 | $5:: 329 | { 330 | inputNumber = %inputNumber%5 331 | normalize(5) 332 | notify(inputNumber) 333 | return 334 | } 335 | 336 | $6:: 337 | { 338 | inputNumber = %inputNumber%6 339 | normalize(6) 340 | notify(inputNumber) 341 | return 342 | } 343 | 344 | $7:: 345 | { 346 | inputNumber = %inputNumber%7 347 | normalize(7) 348 | notify(inputNumber) 349 | return 350 | } 351 | 352 | $8:: 353 | { 354 | inputNumber = %inputNumber%8 355 | normalize(8) 356 | notify(inputNumber) 357 | return 358 | } 359 | 360 | $9:: 361 | { 362 | inputNumber = %inputNumber%9 363 | normalize(9) 364 | notify(inputNumber) 365 | return 366 | } 367 | 368 | #IfWinExist ;}}} 369 | 370 | ;;; Ad-hoc Vi navigation with Space + key combo {{{ 371 | 372 | Space & F1::Return 373 | ; send explicitly when no other key is pressed before release 374 | *Space:: SendInput {Blind}{Space} 375 | ; KeyDown:=A_TickCount 376 | ; KeyWait / 377 | ; if (A_TickCount-KeyDown < 1000) 378 | ; Send {Space} 379 | ; Return 380 | 381 | #If GetKeyState("Space", "p") 382 | 383 | ; cursor movements 384 | h::left 385 | j::down 386 | k::up 387 | l::right 388 | 389 | ; page movements 390 | w::^right 391 | b::^left 392 | x::delete 393 | 0::home 394 | -::end 395 | $::end 396 | 397 | 398 | ; HotKey to VIM maps 399 | u:: SendInput ^z 400 | 401 | ; Change file name 402 | i:: SendInput {F2} 403 | 404 | #If 405 | 406 | ; }}} 407 | 408 | ; Validate the inputNumber and make sure that it's less than 500 {{{ 409 | normalize(resetNumber) 410 | { 411 | global inputNumber 412 | if (inputNumber > 500) 413 | { 414 | inputNumber := resetNumber 415 | } 416 | } ;}}} 417 | 418 | ; Reset the inputNumber to " " 419 | resetInputNumber() 420 | { 421 | global 422 | resetGUI() 423 | inputNumber := " " 424 | return 425 | } 426 | 427 | resetGUI() 428 | { 429 | Gui, 90:Destroy 430 | return 431 | } 432 | endVIM() 433 | { 434 | Gui, 99:Destroy 435 | resetInputNumber() 436 | return 437 | } 438 | 439 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | A Vim-like navigation script for AutoHotKey_L 2 | ==== 3 | 4 | Written by: Jongbin Jung (olorin86 at gmail dot com) 5 | 6 | Created on December 15, 2012 7 | 8 | # Introduction 9 | Activate Vi Mode (Normal Mode) by double-tapping the Esc key. 10 | Deactivate Vi Mode by pressing Esc key again. 11 | 12 | Simple navigations (hjkl, wb) can be acheived using a Space + key combo. 13 | 14 | # Commands 15 | ## regular movements 16 | - hjkl: cursor movements 17 | - w: move to next word 18 | - b: move to previous word 19 | 20 | - 0: go to beginning of line 21 | - -: go to end of line (this is just how I use it personally in VIM) 22 | - $: go to end of line (for general compatibility... :D) 23 | 24 | # editting commands 25 | - y: Copy 26 | - d: Cut 27 | - p: Paste 28 | - u: undo (Ctrl+z) 29 | 30 | - /: Search (Ctrl+f) 31 | 32 | ... and more to come! ;) 33 | 34 | # Change Logs 35 | ## 08/20/2014 36 | - Add hotkey for search (Ctrl+f) 37 | ## 08/17/2014 38 | - Changed ad-hoc navigation modifier to Space 39 | - ad-hoc navigation works with all modifiers 40 | - Changed hotkey for Vi-mode to double Esc (instead of Shift) 41 | --------------------------------------------------------------------------------