]> git.donarmstrong.com Git - qmk_firmware.git/blob - users/xtonhasvim/xtonhasvim.c
[Keymap] Jarred's Plaid keymap (#6049)
[qmk_firmware.git] / users / xtonhasvim / xtonhasvim.c
1  /* Copyright 2015-2017 Christon DeWan
2  *
3  * This program is free software: you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation, either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16
17 #include "xtonhasvim.h"
18 #include "fancylighting.h"
19
20 /************************************
21  * helper foo
22  ************************************/
23
24 #define PRESS(kc) register_code(kc)
25 #define RELEASE(kc) unregister_code(kc)
26
27 static void TAP(uint16_t keycode) {
28     PRESS(keycode);
29     RELEASE(keycode);
30 }
31
32 static void CMD(uint16_t keycode) {
33   PRESS(KC_LGUI);
34     TAP(keycode);
35   RELEASE(KC_LGUI);
36 }
37
38 static void CTRL(uint16_t keycode) {
39   PRESS(KC_LCTRL);
40     TAP(keycode);
41   RELEASE(KC_LCTRL);
42 }
43
44 static void SHIFT(uint16_t keycode) {
45   PRESS(KC_LSHIFT);
46     TAP(keycode);
47   RELEASE(KC_LSHIFT);
48 }
49
50 static void ALT(uint16_t keycode) {
51   PRESS(KC_LALT);
52     TAP(keycode);
53   RELEASE(KC_LALT);
54 }
55
56
57 uint16_t vstate = VIM_START;
58 static bool yank_was_lines = false;
59 static bool SHIFTED = false;
60 static uint32_t mod_override_layer_state = 0;
61 static uint16_t mod_override_triggering_key = 0;
62
63 static void edit(void) { vstate = VIM_START; layer_clear(); }
64 #define EDIT edit()
65
66
67 static void simple_movement(uint16_t keycode) {
68   switch(keycode) {
69     case VIM_B:
70       PRESS(KC_LALT);
71         SHIFT(KC_LEFT); // select to start of this word
72       RELEASE(KC_LALT);
73       break;
74     case VIM_E:
75       PRESS(KC_LALT);
76         SHIFT(KC_RIGHT); // select to end of this word
77       RELEASE(KC_LALT);
78       break;
79     case VIM_H:
80       SHIFT(KC_LEFT);
81       break;
82     case VIM_J:
83       CMD(KC_LEFT);
84       SHIFT(KC_DOWN);
85       SHIFT(KC_DOWN);
86       break;
87     case VIM_K:
88       CMD(KC_LEFT);
89       TAP(KC_DOWN);
90       SHIFT(KC_UP);
91       SHIFT(KC_UP);
92       break;
93     case VIM_L:
94       SHIFT(KC_RIGHT);
95       break;
96     case VIM_W:
97       PRESS(KC_LALT);
98       SHIFT(KC_RIGHT); // select to end of this word
99       SHIFT(KC_RIGHT); // select to end of next word
100       SHIFT(KC_LEFT);  // select to start of next word
101       RELEASE(KC_LALT);
102       break;
103   }
104 }
105
106 static void comma_period(uint16_t keycode) {
107   switch (keycode) {
108   case VIM_COMMA:
109     if (SHIFTED) {
110       // indent
111       CMD(KC_LBRACKET);
112     } else {
113       // toggle comment
114       CMD(KC_SLASH);
115     }
116     break;
117   case VIM_PERIOD:
118     if (SHIFTED) {
119       // outdent
120       CMD(KC_RBRACKET);
121     }
122     break;
123   }
124 }
125
126 __attribute__ ((weak))
127 bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
128   return true;
129 }
130
131 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
132   /* keymap gets first whack */
133   if(!process_record_keymap(keycode, record)) return false;
134
135   /****** FIREY_RETURN *****/
136   if(record->event.pressed && keycode == FIREY_RETURN) {
137     start_firey_return();
138     TAP(KC_ENT);
139   }
140
141   /****** mod passthru *****/
142   if(record->event.pressed && layer_state_is(vim_cmd_layer()) && (IS_MOD(keycode) || keycode == LSFT(KC_LALT))) {
143     mod_override_layer_state = layer_state;
144     mod_override_triggering_key = keycode;
145     // TODO: change this to track key location instead
146     layer_clear();
147     return true; // let the event fall through...
148   }
149   if(mod_override_layer_state && !record->event.pressed && keycode == mod_override_triggering_key) {
150     layer_state_set(mod_override_layer_state);
151     mod_override_layer_state = 0;
152     mod_override_triggering_key = 0;
153     return true;
154   }
155
156   if (VIM_START <= keycode && keycode <= VIM_ESC) {
157     if(keycode == VIM_SHIFT) {
158       SHIFTED = record->event.pressed;
159       return false;
160     }
161
162     if (record->event.pressed) {
163       if(keycode == VIM_START) {
164         // entry from anywhere
165         layer_on(vim_cmd_layer());
166         vstate = VIM_START;
167
168         // reset state
169         yank_was_lines = false;
170         SHIFTED = false;
171         mod_override_layer_state = 0;
172         mod_override_triggering_key = 0;
173
174         return false;
175       }
176       switch(vstate) {
177         case VIM_START:
178           switch(keycode){
179             /*****************************
180              * ground state
181              *****************************/
182             case VIM_A:
183               if(SHIFTED) {
184                 // CMD(KC_RIGHT);
185                 CTRL(KC_E);
186               } else {
187                 TAP(KC_RIGHT);
188               }
189               EDIT;
190               break;
191             case VIM_B:
192               PRESS(KC_LALT);
193               PRESS(KC_LEFT);
194               break;
195             case VIM_C:
196               if(SHIFTED) {
197                 PRESS(KC_LSHIFT);
198                   CMD(KC_RIGHT);
199                 RELEASE(KC_LSHIFT);
200                 CMD(KC_X);
201                 yank_was_lines = false;
202                 EDIT;
203               } else {
204                 vstate = VIM_C;
205               }
206               break;
207             case VIM_D:
208               if(SHIFTED) {
209                 CTRL(KC_K);
210               } else {
211                 vstate = VIM_D;
212               }
213               break;
214             case VIM_E:
215               PRESS(KC_LALT);
216               PRESS(KC_RIGHT);
217               break;
218             case VIM_G:
219               if(SHIFTED) {
220                 TAP(KC_END);
221               } else {
222                 vstate = VIM_G;
223               }
224               break;
225             case VIM_H:
226               PRESS(KC_LEFT);
227               break;
228             case VIM_I:
229               if(SHIFTED){
230                 CTRL(KC_A);
231               }
232               EDIT;
233               break;
234             case VIM_J:
235               if(SHIFTED) {
236                 CMD(KC_RIGHT);
237                 TAP(KC_DEL);
238               } else {
239                 PRESS(KC_DOWN);
240               }
241               break;
242             case VIM_K:
243               PRESS(KC_UP);
244               break;
245             case VIM_L:
246               PRESS(KC_RIGHT);
247               break;
248             case VIM_O:
249               if(SHIFTED) {
250                 CMD(KC_LEFT);
251                 TAP(KC_ENTER);
252                 TAP(KC_UP);
253                 EDIT;
254               } else {
255                 CMD(KC_RIGHT);
256                 TAP(KC_ENTER);
257                 EDIT;
258               }
259               break;
260             case VIM_P:
261               if(SHIFTED) {
262                 CMD(KC_LEFT);
263                 CMD(KC_V);
264               } else {
265                 if(yank_was_lines) {
266                   CMD(KC_RIGHT);
267                   TAP(KC_RIGHT);
268                   CMD(KC_V);
269                 } else {
270                   CMD(KC_V);
271                 }
272               }
273               break;
274             case VIM_S:
275               // s for substitute?
276               if(SHIFTED) {
277                 CMD(KC_LEFT);
278                 PRESS(KC_LSHIFT);
279                   CMD(KC_RIGHT);
280                 RELEASE(KC_LSHIFT);
281                 CMD(KC_X);
282                 yank_was_lines = false;
283                 EDIT;
284               } else {
285                 SHIFT(KC_RIGHT);
286                 CMD(KC_X);
287                 yank_was_lines = false;
288                 EDIT;
289               }
290               break;
291             case VIM_U:
292               if(SHIFTED) {
293                 PRESS(KC_LSFT);
294                   CMD(KC_Z);
295                 RELEASE(KC_LSHIFT);
296               } else {
297                 CMD(KC_Z);
298               }
299               break;
300             case VIM_V:
301               if(SHIFTED) {
302                 CMD(KC_LEFT);
303                 SHIFT(KC_DOWN);
304                 vstate = VIM_VS;
305               } else {
306                 vstate = VIM_V;
307               }
308               break;
309             case VIM_W:
310               PRESS(KC_LALT);
311                 TAP(KC_RIGHT);
312                 TAP(KC_RIGHT);
313                 TAP(KC_LEFT);
314               RELEASE(KC_LALT);
315               break;
316             case VIM_X:
317               // SHIFT(KC_RIGHT);
318               // CMD(KC_X);
319               PRESS(KC_DEL);
320               break;
321             case VIM_Y:
322               if(SHIFTED) {
323                 CMD(KC_LEFT);
324                 SHIFT(KC_DOWN);
325                 CMD(KC_C);
326                 TAP(KC_RIGHT);
327                 yank_was_lines = true;
328               } else {
329                 vstate = VIM_Y;
330               }
331               break;
332             case VIM_COMMA:
333             case VIM_PERIOD:
334               comma_period(keycode);
335               break;
336           }
337           break;
338         case VIM_C:
339           /*****************************
340            * c-  ...for change. I never use this...
341            *****************************/
342           switch(keycode) {
343           case VIM_B:
344           case VIM_E:
345           case VIM_H:
346           case VIM_J:
347           case VIM_K:
348           case VIM_L:
349           case VIM_W:
350             simple_movement(keycode);
351             CMD(KC_X);
352             yank_was_lines = false;
353             EDIT;
354             break;
355
356           case VIM_C:
357             CMD(KC_LEFT);
358             PRESS(KC_LSHIFT);
359               CMD(KC_RIGHT);
360             RELEASE(KC_LSHIFT);
361             CMD(KC_X);
362             yank_was_lines = false;
363             EDIT;
364             break;
365           case VIM_I:
366             vstate = VIM_CI;
367             break;
368           default:
369             vstate = VIM_START;
370             break;
371           }
372           break;
373         case VIM_CI:
374           /*****************************
375            * ci-  ...change inner word
376            *****************************/
377           switch(keycode) {
378             case VIM_W:
379               ALT(KC_LEFT);
380               PRESS(KC_LSHIFT);
381                 ALT(KC_RIGHT);
382               RELEASE(KC_LSHIFT);
383               CMD(KC_X);
384               yank_was_lines = false;
385               EDIT;
386             default:
387               vstate = VIM_START;
388               break;
389           }
390           break;
391         case VIM_D:
392           /*****************************
393            * d-  ...delete stuff
394            *****************************/
395           switch(keycode) {
396           case VIM_B:
397           case VIM_E:
398           case VIM_H:
399           case VIM_J:
400           case VIM_K:
401           case VIM_L:
402           case VIM_W:
403             simple_movement(keycode);
404             CMD(KC_X);
405             yank_was_lines = false;
406             vstate = VIM_START;
407             break;
408           case VIM_D:
409             CMD(KC_LEFT);
410             SHIFT(KC_DOWN);
411             CMD(KC_X);
412             yank_was_lines = true;
413             vstate = VIM_START;
414             break;
415           case VIM_I:
416             vstate = VIM_DI;
417             break;
418           default:
419             vstate = VIM_START;
420             break;
421           }
422           break;
423         case VIM_DI:
424           /*****************************
425            * ci-  ...delete a word... FROM THE INSIDE!
426            *****************************/
427           switch(keycode) {
428             case VIM_W:
429               ALT(KC_LEFT);
430               PRESS(KC_LSHIFT);
431                 ALT(KC_RIGHT);
432               RELEASE(KC_LSHIFT);
433               CMD(KC_X);
434               yank_was_lines = false;
435               vstate = VIM_START;
436             default:
437               vstate = VIM_START;
438               break;
439           }
440           break;
441         case VIM_V:
442           /*****************************
443            * visual!
444            *****************************/
445           switch(keycode) {
446             case VIM_D:
447             case VIM_X:
448               CMD(KC_X);
449               yank_was_lines = false;
450               vstate = VIM_START;
451               break;
452             case VIM_B:
453               PRESS(KC_LALT);
454               PRESS(KC_LSHIFT);
455               PRESS(KC_LEFT);
456               // leave open for key repeat
457               break;
458             case VIM_E:
459               PRESS(KC_LALT);
460               PRESS(KC_LSHIFT);
461               PRESS(KC_RIGHT);
462               // leave open for key repeat
463               break;
464             case VIM_H:
465               PRESS(KC_LSHIFT);
466               PRESS(KC_LEFT);
467               break;
468             case VIM_I:
469               vstate = VIM_VI;
470               break;
471             case VIM_J:
472               PRESS(KC_LSHIFT);
473               PRESS(KC_DOWN);
474               break;
475             case VIM_K:
476               PRESS(KC_LSHIFT);
477               PRESS(KC_UP);
478               break;
479             case VIM_L:
480               PRESS(KC_LSHIFT);
481               PRESS(KC_RIGHT);
482               break;
483             case VIM_W:
484               PRESS(KC_LALT);
485               SHIFT(KC_RIGHT); // select to end of this word
486               SHIFT(KC_RIGHT); // select to end of next word
487               SHIFT(KC_LEFT);  // select to start of next word
488               RELEASE(KC_LALT);
489               break;
490             case VIM_P:
491               CMD(KC_V);
492               vstate = VIM_START;
493               break;
494             case VIM_Y:
495               CMD(KC_C);
496               TAP(KC_RIGHT);
497               yank_was_lines = false;
498               vstate = VIM_START;
499               break;
500             case VIM_V:
501             case VIM_ESC:
502               TAP(KC_RIGHT);
503               vstate = VIM_START;
504               break;
505             case VIM_COMMA:
506             case VIM_PERIOD:
507               comma_period(keycode);
508               break;
509             default:
510               // do nothing
511               break;
512           }
513           break;
514         case VIM_VI:
515           /*****************************
516            * vi-  ...select a word... FROM THE INSIDE!
517            *****************************/
518           switch(keycode) {
519             case VIM_W:
520               ALT(KC_LEFT);
521               PRESS(KC_LSHIFT);
522                 ALT(KC_RIGHT);
523               RELEASE(KC_LSHIFT);
524               vstate = VIM_V;
525             default:
526               // ignore
527               vstate = VIM_V;
528               break;
529           }
530           break;
531         case VIM_VS:
532           /*****************************
533            * visual line
534            *****************************/
535           switch(keycode) {
536             case VIM_D:
537             case VIM_X:
538               CMD(KC_X);
539               yank_was_lines = true;
540               vstate = VIM_START;
541               break;
542             case VIM_J:
543               PRESS(KC_LSHIFT);
544               PRESS(KC_DOWN);
545               break;
546             case VIM_K:
547               PRESS(KC_LSHIFT);
548               PRESS(KC_UP);
549               break;
550             case VIM_Y:
551               CMD(KC_C);
552               yank_was_lines = true;
553               TAP(KC_RIGHT);
554               vstate = VIM_START;
555               break;
556             case VIM_P:
557               CMD(KC_V);
558               vstate = VIM_START;
559               break;
560             case VIM_V:
561             case VIM_ESC:
562               TAP(KC_RIGHT);
563               vstate = VIM_START;
564               break;
565             case VIM_COMMA:
566             case VIM_PERIOD:
567               comma_period(keycode);
568               break;
569             default:
570               // do nothing
571               break;
572           }
573           break;
574         case VIM_G:
575           /*****************************
576            * gg, and a grab-bag of other macros i find useful
577            *****************************/
578           switch(keycode) {
579             case VIM_G:
580               TAP(KC_HOME);
581               break;
582             // codes b
583             case VIM_H:
584               CTRL(KC_A);
585               break;
586             case VIM_J:
587               PRESS(KC_PGDN);
588               break;
589             case VIM_K:
590               PRESS(KC_PGUP);
591               break;
592             case VIM_L:
593               CTRL(KC_E);
594               break;
595             default:
596               // do nothing
597               break;
598           }
599           vstate = VIM_START;
600           break;
601         case VIM_Y:
602           /*****************************
603            * yoink!
604            *****************************/
605           switch(keycode) {
606           case VIM_B:
607           case VIM_E:
608           case VIM_H:
609           case VIM_J:
610           case VIM_K:
611           case VIM_L:
612           case VIM_W:
613             simple_movement(keycode);
614             CMD(KC_C);
615             TAP(KC_RIGHT);
616             yank_was_lines = false;
617             break;
618           case VIM_Y:
619             CMD(KC_LEFT);
620             SHIFT(KC_DOWN);
621             CMD(KC_C);
622             TAP(KC_RIGHT);
623             yank_was_lines = true;
624             break;
625           default:
626             // NOTHING
627             break;
628           }
629           vstate = VIM_START;
630           break;
631         }
632     } else {
633       /************************
634        * key release events
635        ************************/
636       clear_keyboard();
637     }
638     return false;
639   } else {
640     return true;
641   }
642 }
643