aboutsummaryrefslogtreecommitdiff
path: root/users
diff options
context:
space:
mode:
authorxton <cmdpix@mac.com>2018-05-12 08:52:11 -0700
committerDrashna Jaelre <drashna@live.com>2018-05-12 08:52:11 -0700
commit05be1de1aa35f15b71ebfdf2f142fca50609ef31 (patch)
tree4db990cd5fcb659d3301b10a129b4d03bdc43ba5 /users
parent5b503cc5438fdc4f9b13ae3d697d28c3824f2b75 (diff)
downloadqmk_firmware-05be1de1aa35f15b71ebfdf2f142fca50609ef31.tar.gz
qmk_firmware-05be1de1aa35f15b71ebfdf2f142fca50609ef31.zip
Xton's first keymap! (#2941)
* FORK! * WIP - just how i like it * empty * more movement * mouse keys * more vimminess * append/insert shift * WIP - vim macros * blocked out layer below in cmd mode. also, about to restart my cmd approach. * WIP - new vim layer ripoff of the ergodox one, but rewritten as a state machine. * debugged some, got key repeat working * moooar coverage * moooar coverage * regular vis mode * basically done with basics. * some refactoring - common movement sequences into helper function - added some rgb controls * modkey passthru feature * stdized on cmd-left/right instead of ctrl-a/e sadly. as there's no reliable shift-ctrl-e * indicator lights * moved vim layer into userspace * cleaned up some yanking edge cases * docs and some tweaks to layerescapes * updated/added license strings * updated comments * moved config changes to keymap * spurious changes removed
Diffstat (limited to 'users')
-rw-r--r--users/xtonhasvim/readme.md10
-rw-r--r--users/xtonhasvim/rules.mk1
-rw-r--r--users/xtonhasvim/xtonhasvim.c599
-rw-r--r--users/xtonhasvim/xtonhasvim.h66
4 files changed, 676 insertions, 0 deletions
diff --git a/users/xtonhasvim/readme.md b/users/xtonhasvim/readme.md
new file mode 100644
index 000000000..e08e972f4
--- /dev/null
+++ b/users/xtonhasvim/readme.md
@@ -0,0 +1,10 @@
1
2# Xton has Vim!
3
4Contains common code for Xton's vim emulation (vimulation?) layer.
5
6Inspired/stolen from the `ergodox_ez/vim` keymap. Rewritten to be a more straightforward state machine and support more macros. Vim layers `_CMD` and `_EDIT` are designed to lay on top of an otherwise fully-functional layout. `_CMD` runs the entire vim state machine while `_EDIT` should lay across your base layer and mask off just the escape key.
7
8Works via OSX text editing shortcuts, mainly MOD+arrow combinations. This has some limitations and only works on OSX.
9
10The `_CMD` layer will temporarily disable itself while *CMD* or *ALT* are held down so that typical OSX shortcuts can be used without switching out of vim mode.
diff --git a/users/xtonhasvim/rules.mk b/users/xtonhasvim/rules.mk
new file mode 100644
index 000000000..3777917f8
--- /dev/null
+++ b/users/xtonhasvim/rules.mk
@@ -0,0 +1 @@
SRC += xtonhasvim.c
diff --git a/users/xtonhasvim/xtonhasvim.c b/users/xtonhasvim/xtonhasvim.c
new file mode 100644
index 000000000..85048401d
--- /dev/null
+++ b/users/xtonhasvim/xtonhasvim.c
@@ -0,0 +1,599 @@
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
19/************************************
20 * helper foo
21 ************************************/
22
23#define PRESS(kc) register_code(kc)
24#define RELEASE(kc) unregister_code(kc)
25
26static void TAP(uint16_t keycode) {
27 PRESS(keycode);
28 RELEASE(keycode);
29}
30
31static void CMD(uint16_t keycode) {
32 PRESS(KC_LGUI);
33 TAP(keycode);
34 RELEASE(KC_LGUI);
35}
36
37static void CTRL(uint16_t keycode) {
38 PRESS(KC_LCTRL);
39 TAP(keycode);
40 RELEASE(KC_LCTRL);
41}
42
43static void SHIFT(uint16_t keycode) {
44 PRESS(KC_LSHIFT);
45 TAP(keycode);
46 RELEASE(KC_LSHIFT);
47}
48
49static void ALT(uint16_t keycode) {
50 PRESS(KC_LALT);
51 TAP(keycode);
52 RELEASE(KC_LALT);
53}
54
55
56uint16_t vstate = VIM_START;
57bool yank_was_lines = false;
58bool SHIFTED = false;
59uint32_t mod_override_layer_state = 0;
60uint16_t mod_override_triggering_key = 0;
61bool do_check_kb_clear = false;
62
63void vim_reset(void) {
64 vstate = VIM_START;
65 SHIFTED = false;
66 yank_was_lines = false;
67}
68
69void edit(void) { vstate = VIM_START; layer_on(_EDIT); layer_off(_CMD); }
70#define EDIT edit()
71
72
73void simple_movement(uint16_t keycode) {
74 switch(keycode) {
75 case VIM_B:
76 PRESS(KC_LALT);
77 SHIFT(KC_LEFT); // select to start of this word
78 RELEASE(KC_LALT);
79 break;
80 case VIM_E:
81 PRESS(KC_LALT);
82 SHIFT(KC_RIGHT); // select to end of this word
83 RELEASE(KC_LALT);
84 break;
85 case VIM_H:
86 SHIFT(KC_LEFT);
87 break;
88 case VIM_J:
89 CMD(KC_LEFT);
90 SHIFT(KC_DOWN);
91 SHIFT(KC_DOWN);
92 break;
93 case VIM_K:
94 CMD(KC_LEFT);
95 TAP(KC_DOWN);
96 SHIFT(KC_UP);
97 SHIFT(KC_UP);
98 break;
99 case VIM_L:
100 SHIFT(KC_RIGHT);
101 break;
102 case VIM_W:
103 PRESS(KC_LALT);
104 SHIFT(KC_RIGHT); // select to end of this word
105 SHIFT(KC_RIGHT); // select to end of next word
106 SHIFT(KC_LEFT); // select to start of next word
107 RELEASE(KC_LALT);
108 break;
109 }
110}
111
112bool process_record_xtonhasvim(uint16_t keycode, keyrecord_t *record) {
113 if(record->event.pressed && layer_state_is(_CMD) && IS_MOD(keycode)) {
114 mod_override_layer_state = layer_state;
115 mod_override_triggering_key = keycode;
116 layer_clear();
117 return true; // let the event fall through...
118 }
119 if(mod_override_layer_state && !record->event.pressed && keycode == mod_override_triggering_key) {
120 layer_state_set(mod_override_layer_state);
121 mod_override_layer_state = 0;
122 mod_override_triggering_key = 0;
123 return true;
124 }
125
126 if (VIM_START <= keycode && keycode <= VIM_ESC) {
127 if(keycode == VIM_SHIFT) {
128 SHIFTED = record->event.pressed;
129 return false;
130 }
131
132 if (record->event.pressed) {
133 if(keycode == VIM_START) {
134 // entry from anywhere
135 layer_on(_CMD);
136 vstate = VIM_START;
137 return false;
138 }
139 switch(vstate) {
140 case VIM_START:
141 switch(keycode){
142 /*****************************
143 * ground state
144 *****************************/
145 case VIM_A:
146 if(SHIFTED) {
147 // CMD(KC_RIGHT);
148 CTRL(KC_E);
149 } else {
150 TAP(KC_RIGHT);
151 }
152 EDIT;
153 break;
154 case VIM_B:
155 PRESS(KC_LALT);
156 PRESS(KC_LEFT);
157 break;
158 case VIM_C:
159 if(SHIFTED) {
160 PRESS(KC_LSHIFT);
161 CMD(KC_RIGHT);
162 RELEASE(KC_LSHIFT);
163 CMD(KC_X);
164 yank_was_lines = false;
165 EDIT;
166 } else {
167 vstate = VIM_C;
168 }
169 break;
170 case VIM_D:
171 if(SHIFTED) {
172 TAP(KC_K);
173 } else {
174 vstate = VIM_D;
175 }
176 break;
177 case VIM_E:
178 PRESS(KC_LALT);
179 PRESS(KC_RIGHT);
180 break;
181 case VIM_G:
182 if(SHIFTED) {
183 TAP(KC_END);
184 } else {
185 vstate = VIM_G;
186 }
187 break;
188 case VIM_H:
189 PRESS(KC_LEFT);
190 break;
191 case VIM_I:
192 if(SHIFTED){
193 CTRL(KC_A);
194 }
195 EDIT;
196 break;
197 case VIM_J:
198 if(SHIFTED) {
199 CMD(KC_RIGHT);
200 TAP(KC_DEL);
201 } else {
202 PRESS(KC_DOWN);
203 }
204 break;
205 case VIM_K:
206 PRESS(KC_UP);
207 break;
208 case VIM_L:
209 PRESS(KC_RIGHT);
210 break;
211 case VIM_O:
212 if(SHIFTED) {
213 CMD(KC_LEFT);
214 TAP(KC_ENTER);
215 TAP(KC_UP);
216 EDIT;
217 } else {
218 CMD(KC_RIGHT);
219 TAP(KC_ENTER);
220 EDIT;
221 }
222 break;
223 case VIM_P:
224 if(SHIFTED) {
225 CMD(KC_LEFT);
226 CMD(KC_V);
227 } else {
228 if(yank_was_lines) {
229 CMD(KC_RIGHT);
230 TAP(KC_RIGHT);
231 CMD(KC_V);
232 } else {
233 CMD(KC_V);
234 }
235 }
236 break;
237 case VIM_S:
238 // s for substitute?
239 if(SHIFTED) {
240 CMD(KC_LEFT);
241 PRESS(KC_LSHIFT);
242 CMD(KC_RIGHT);
243 RELEASE(KC_LSHIFT);
244 CMD(KC_X);
245 yank_was_lines = false;
246 EDIT;
247 } else {
248 SHIFT(KC_RIGHT);
249 CMD(KC_X);
250 yank_was_lines = false;
251 EDIT;
252 }
253 break;
254 case VIM_U:
255 if(SHIFTED) {
256 PRESS(KC_LSFT);
257 CMD(KC_Z);
258 RELEASE(KC_LSHIFT);
259 } else {
260 CMD(KC_Z);
261 }
262 break;
263 case VIM_V:
264 if(SHIFTED) {
265 CMD(KC_LEFT);
266 SHIFT(KC_DOWN);
267 vstate = VIM_VS;
268 } else {
269 vstate = VIM_V;
270 }
271 break;
272 case VIM_W:
273 PRESS(KC_LALT);
274 TAP(KC_RIGHT);
275 TAP(KC_RIGHT);
276 TAP(KC_LEFT);
277 RELEASE(KC_LALT);
278 break;
279 case VIM_X:
280 // SHIFT(KC_RIGHT);
281 // CMD(KC_X);
282 PRESS(KC_DEL);
283 break;
284 case VIM_Y:
285 if(SHIFTED) {
286 CMD(KC_LEFT);
287 SHIFT(KC_DOWN);
288 CMD(KC_C);
289 TAP(KC_RIGHT);
290 yank_was_lines = true;
291 } else {
292 vstate = VIM_Y;
293 }
294 break;
295 case VIM_COMMA:
296 if(SHIFTED) {
297 // indent
298 CMD(KC_LBRACKET);
299 } else {
300 // toggle comment
301 CMD(KC_SLASH);
302 }
303 break;
304 case VIM_PERIOD:
305 if(SHIFTED) {
306 // outdent
307 CMD(KC_RBRACKET);
308 }
309 break;
310 }
311 break;
312 case VIM_C:
313 /*****************************
314 * c- ...for change. I never use this...
315 *****************************/
316 switch(keycode) {
317 case VIM_B:
318 case VIM_E:
319 case VIM_H:
320 case VIM_J:
321 case VIM_K:
322 case VIM_L:
323 case VIM_W:
324 simple_movement(keycode);
325 CMD(KC_X);
326 yank_was_lines = false;
327 EDIT;
328 break;
329
330 case VIM_C:
331 CMD(KC_LEFT);
332 PRESS(KC_LSHIFT);
333 CMD(KC_RIGHT);
334 RELEASE(KC_LSHIFT);
335 CMD(KC_X);
336 yank_was_lines = false;
337 EDIT;
338 break;
339 case VIM_I:
340 vstate = VIM_CI;
341 break;
342 default:
343 vstate = VIM_START;
344 break;
345 }
346 break;
347 case VIM_CI:
348 /*****************************
349 * ci- ...change inner word
350 *****************************/
351 switch(keycode) {
352 case VIM_W:
353 ALT(KC_LEFT);
354 PRESS(KC_LSHIFT);
355 ALT(KC_RIGHT);
356 RELEASE(KC_LSHIFT);
357 CMD(KC_X);
358 yank_was_lines = false;
359 EDIT;
360 default:
361 vstate = VIM_START;
362 break;
363 }
364 break;
365 case VIM_D:
366 /*****************************
367 * d- ...delete stuff
368 *****************************/
369 switch(keycode) {
370 case VIM_B:
371 case VIM_E:
372 case VIM_H:
373 case VIM_J:
374 case VIM_K:
375 case VIM_L:
376 case VIM_W:
377 simple_movement(keycode);
378 CMD(KC_X);
379 yank_was_lines = false;
380 break;
381 case VIM_D:
382 CMD(KC_LEFT);
383 SHIFT(KC_DOWN);
384 CMD(KC_X);
385 yank_was_lines = true;
386 vstate = VIM_START;
387 break;
388 case VIM_I:
389 vstate = VIM_DI;
390 break;
391 default:
392 vstate = VIM_START;
393 break;
394 }
395 break;
396 case VIM_DI:
397 /*****************************
398 * ci- ...delete a word... FROM THE INSIDE!
399 *****************************/
400 switch(keycode) {
401 case VIM_W:
402 ALT(KC_LEFT);
403 PRESS(KC_LSHIFT);
404 ALT(KC_RIGHT);
405 RELEASE(KC_LSHIFT);
406 CMD(KC_X);
407 yank_was_lines = false;
408 vstate = VIM_START;
409 default:
410 vstate = VIM_START;
411 break;
412 }
413 break;
414 case VIM_V:
415 /*****************************
416 * visual!
417 *****************************/
418 switch(keycode) {
419 case VIM_D:
420 case VIM_X:
421 CMD(KC_X);
422 yank_was_lines = false;
423 vstate = VIM_START;
424 break;
425 case VIM_B:
426 PRESS(KC_LALT);
427 PRESS(KC_LSHIFT);
428 PRESS(KC_LEFT);
429 // leave open for key repeat
430 break;
431 case VIM_E:
432 PRESS(KC_LALT);
433 PRESS(KC_LSHIFT);
434 PRESS(KC_RIGHT);
435 // leave open for key repeat
436 break;
437 case VIM_H:
438 PRESS(KC_LSHIFT);
439 PRESS(KC_LEFT);
440 break;
441 case VIM_I:
442 vstate = VIM_VI;
443 break;
444 case VIM_J:
445 PRESS(KC_LSHIFT);
446 PRESS(KC_DOWN);
447 break;
448 case VIM_K:
449 PRESS(KC_LSHIFT);
450 PRESS(KC_UP);
451 break;
452 case VIM_L:
453 PRESS(KC_LSHIFT);
454 PRESS(KC_RIGHT);
455 break;
456 case VIM_W:
457 PRESS(KC_LALT);
458 SHIFT(KC_RIGHT); // select to end of this word
459 SHIFT(KC_RIGHT); // select to end of next word
460 SHIFT(KC_LEFT); // select to start of next word
461 RELEASE(KC_LALT);
462 break;
463 case VIM_Y:
464 CMD(KC_C);
465 TAP(KC_RIGHT);
466 yank_was_lines = false;
467 vstate = VIM_START;
468 break;
469 case VIM_V:
470 case VIM_ESC:
471 TAP(KC_RIGHT);
472 vstate = VIM_START;
473 break;
474 default:
475 // do nothing
476 break;
477 }
478 break;
479 case VIM_VI:
480 /*****************************
481 * vi- ...select a word... FROM THE INSIDE!
482 *****************************/
483 switch(keycode) {
484 case VIM_W:
485 ALT(KC_LEFT);
486 PRESS(KC_LSHIFT);
487 ALT(KC_RIGHT);
488 RELEASE(KC_LSHIFT);
489 vstate = VIM_V;
490 default:
491 // ignore
492 vstate = VIM_V;
493 break;
494 }
495 break;
496 case VIM_VS:
497 /*****************************
498 * visual line
499 *****************************/
500 switch(keycode) {
501 case VIM_D:
502 case VIM_X:
503 CMD(KC_X);
504 yank_was_lines = true;
505 vstate = VIM_START;
506 break;
507 case VIM_J:
508 PRESS(KC_LSHIFT);
509 PRESS(KC_DOWN);
510 break;
511 case VIM_K:
512 PRESS(KC_LSHIFT);
513 PRESS(KC_UP);
514 break;
515 case VIM_Y:
516 CMD(KC_C);
517 yank_was_lines = true;
518 TAP(KC_RIGHT);
519 vstate = VIM_START;
520 break;
521 case VIM_V:
522 case VIM_ESC:
523 TAP(KC_RIGHT);
524 vstate = VIM_START;
525 break;
526 default:
527 // do nothing
528 break;
529 }
530 break;
531 case VIM_G:
532 /*****************************
533 * gg, and a grab-bag of other macros i find useful
534 *****************************/
535 switch(keycode) {
536 case VIM_G:
537 TAP(KC_HOME);
538 break;
539 // codes b
540 case VIM_H:
541 CTRL(KC_A);
542 break;
543 case VIM_J:
544 PRESS(KC_PGDN);
545 break;
546 case VIM_K:
547 PRESS(KC_PGUP);
548 break;
549 case VIM_L:
550 CTRL(KC_E);
551 break;
552 default:
553 // do nothing
554 break;
555 }
556 vstate = VIM_START;
557 break;
558 case VIM_Y:
559 /*****************************
560 * yoink!
561 *****************************/
562 switch(keycode) {
563 case VIM_B:
564 case VIM_E:
565 case VIM_H:
566 case VIM_J:
567 case VIM_K:
568 case VIM_L:
569 case VIM_W:
570 simple_movement(keycode);
571 CMD(KC_C);
572 TAP(KC_RIGHT);
573 yank_was_lines = false;
574 break;
575 case VIM_Y:
576 CMD(KC_LEFT);
577 SHIFT(KC_DOWN);
578 CMD(KC_C);
579 TAP(KC_RIGHT);
580 yank_was_lines = true;
581 break;
582 default:
583 // NOTHING
584 break;
585 }
586 vstate = VIM_START;
587 break;
588 }
589 } else {
590 /************************
591 * key release events
592 ************************/
593 clear_keyboard();
594 }
595 return false;
596 } else {
597 return true;
598 }
599}
diff --git a/users/xtonhasvim/xtonhasvim.h b/users/xtonhasvim/xtonhasvim.h
new file mode 100644
index 000000000..21b794c03
--- /dev/null
+++ b/users/xtonhasvim/xtonhasvim.h
@@ -0,0 +1,66 @@
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#ifndef USERSPACE
18#define USERSPACE
19
20#include QMK_KEYBOARD_H
21#include "action_layer.h"
22
23#define X_____X KC_NO
24
25bool process_record_xtonhasvim(uint16_t keycode, keyrecord_t *record);
26
27enum xtonhasvim_keycodes {
28 DUMMY = SAFE_RANGE,
29 VIM_START, // bookend for vim states
30 VIM_A,
31 VIM_B,
32 VIM_C,
33 VIM_CI,
34 VIM_D,
35 VIM_DI,
36 VIM_E,
37 VIM_H,
38 VIM_G,
39 VIM_I,
40 VIM_J,
41 VIM_K,
42 VIM_L,
43 VIM_O,
44 VIM_P,
45 VIM_S,
46 VIM_U,
47 VIM_V,
48 VIM_VS, // visual-line
49 VIM_VI,
50 VIM_W,
51 VIM_X,
52 VIM_Y,
53 VIM_PERIOD, // to support indent/outdent
54 VIM_COMMA, // and toggle comments
55 VIM_SHIFT, // avoid side-effect of supporting real shift.
56 VIM_ESC, // bookend
57 VIM_SAFE_RANGE // start other keycodes here.
58};
59
60enum xtonhasvim_layers {
61 _EDIT = 12,
62 _CMD
63};
64
65
66#endif