summaryrefslogtreecommitdiff
path: root/rekado-mode.el
blob: 72c794ab217bba7fc6e0e89bf4def49c31cdd3b0 (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
;; ---------------- rekado minor mode --------------------
(defvar rekado-permanent-mode-q nil "indicates whether permanent keys are active")
(defvar rekado-mode-map (make-sparse-keymap) "keymap for rekado-mode")
(defun rekado-mode-define-keys (define-permanent-keys)
  "Defines key bindings for rekado-mode.  If the argument is t,
the edit mode keys will be bound as well."
  (let* ((modal-keys
          '(
            ("a" . move-beginning-of-line)
            ("e" . move-end-of-line)

            ;; define JKLI (HTNC in Dvorak) as arrow keys
            ("c" . previous-line)
            ("t" . next-line)
            ("h" . backward-char)
            ("n" . forward-char)

            ;; add meta key to move more quickly
            ("M-c" . (lambda () (interactive)
                       (previous-line 5)))
            ("M-t" . (lambda () (interactive)
                       (next-line 5)))
            ("M-h" . (lambda () (interactive)
                       (backward-char 5)))
            ("M-n" . (lambda () (interactive)
                       (forward-char 5)))

            ;; define u/o (g/r in Dvorak) as backward/forward-word
            ("g" . backward-word)
            ("r" . forward-word)
            ;; define U/O (G/R in Dvorak) to kill word in direction
            ("G" . backward-kill-word)
            ("R" . kill-word)

            ;; TODO: add advice for C, T, H and N (upper case arrows in Dvorak) to mark and start selection
            ;; jump to character
            ("f" . ace-jump-char-mode)
            ("i" . rekado-permanent-mode-exit)
            ("k" . (lambda ()
                     (interactive)
                     (move-beginning-of-line nil)
                     (kill-whole-line)))
            ;; undo as in vim
            ("u" . undo)
            ;; repeat as in vim
            ("." . repeat)
            ;; paste as in vim
            ("p" . (lambda ()
                     (interactive)
                     (next-line)
                     (beginning-of-line)
                     (yank)))
            ("P" . (lambda ()
                     (interactive)
                     (beginning-of-line)
                     (yank)))
            ;; copy as in vim
            ("y" . kill-ring-save)
            ("s" . isearch-forward-regexp)
            ;; open line below/above as in vim
            ("o" . (lambda ()
                     (interactive)
                     (open-line-below)
                     (rekado-permanent-mode-exit)))
            ("O" . (lambda ()
                     (interactive)
                     (open-line-above)
                     (rekado-permanent-mode-exit)))
            ;; join lines (like J in vim)
            ("j" . (lambda ()
                     (interactive)
                     (join-line -1)))
            ;; change till the end of the line
            ("C" . (lambda ()
                     (interactive)
                     (kill-line)
                     (rekado-permanent-mode-exit)))
            )))
    (progn
      ;; toggle permanent mode
      (define-key rekado-mode-map
        (kbd "<C-return>")
        'rekado-permanent-mode-toggle)

      ;; toggle permanent mode
      (define-key rekado-mode-map
        (kbd "<M-SPC>")
        'rekado-permanent-mode-toggle)

      (if define-permanent-keys
          ;; define permanent keys
          (progn
            (setq rekado-permanent-mode-q t)
            (mapc (lambda (pair)
                    (define-key rekado-mode-map
                      (kbd (car pair))
                      (cdr pair)))
                  modal-keys))
        ;; undefine permanent keys
        (progn
          (setq rekado-permanent-mode-q nil)
          (mapc (lambda (pair)
                  (define-key rekado-mode-map
                    (kbd (car pair))
                    nil))
                modal-keys)))))
  rekado-mode-map)

(defun open-line-below ()
  (interactive)
  (end-of-line)
  (newline)
  (indent-for-tab-command))

(defun open-line-above ()
  (interactive)
  (beginning-of-line)
  (newline)
  (forward-line -1)
  (indent-for-tab-command))

(defun rekado-permanent-mode-exit ()
  (interactive)
  (set-cursor-color "White")
  (rekado-mode-define-keys nil))

(defun rekado-permanent-mode-toggle ()
  (interactive)
  (if rekado-permanent-mode-q
      (rekado-permanent-mode-exit)
    (progn
      (set-cursor-color "Red")
      (rekado-mode-define-keys 1))))

;; disable permanent keys when in the minibuffer (also when running
;; commands such as isearch)
(add-hook 'post-command-hook (lambda () (if (minibufferp) (rekado-permanent-mode-exit))))

(define-minor-mode rekado-mode
  "Cursor movement shortcuts while Alt is hold and editing
shortcuts when permanent mode is active."
  :lighter " rekado"
  :global t
  :keymap rekado-mode-map
  :after-hook (rekado-mode-define-keys nil))

(provide 'rekado-mode)