-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathom-mode.el
179 lines (155 loc) · 5.2 KB
/
om-mode.el
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
;;; om-mode.el --- Insert Om component template with life cycle.
;; Copyright (C) 2014 Daniel Szmulewicz
;; <http://about.me/daniel.szmulewicz>
;; Author: Daniel Szmulewicz <[email protected]>
;; Keywords: clojurescript
;; Created: 14th September 2014
;; Version: 0.5.20140916
;;; Commentary:
;; Insert Om component template with life cycle and jump easily
;; between the relevant positions. Also, using abbrev to expand the
;; template by typing a user-configurable abbrev, "om" being the
;; default.
;; Just call "om-insert-template" to start.
;;; Legal:
;;
;; This file is NOT part of GNU Emacs.
;;
;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published
;; by the Free Software Foundation; either version 3 of the License,
;; or (at your option) any later version.
;; This file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;; See <http://www.gnu.org/licenses/> for a copy of the GNU General
;; Public License.
;;; Code:
(require 'skeleton)
;;;###autoload
(define-skeleton om-insert-template
"Om component skeleton"
"Name of component: "
"(defn " str \n
> "\"Om component for new " str "\""
\n > "[data owner]"
\n > "(reify" \n
'(setq v1 (skeleton-read "Render with state (y/n)? "))
(when (string= v1 "y")
(progn (init-state) nil))
'(indent-according-to-mode)
"om/IWillMount" \n
> "(will-mount [_]" \n
@ - ")" \n >
"om/IDidMount" \n
> "(did-mount [_]" \n
@ - ")" \n >
"om/IWillUnmount" \n
> "(will-unmount [_]" \n
@ - ")" \n >
"om/IShouldUpdate" \n
> "(should-update [_ next-props next-state]" \n
@ - ")" \n >
"om/IWillReceiveProps" \n
> "(will-receive-props [_ next-props]" \n
@ - ")" \n >
"om/IWillUpdate" \n
> "(will-update [_ next-props next-state]" \n
@ - ")" \n >
"om/IDidUpdate" \n
> "(did-update [_ prev-props prev-state]" \n
@ - ")" \n >
"om/IDisplayName" \n
> "(display-name [this]" \n
"\"" str "\")" \n >
(if (string= v1 "y")
"om/IRenderState\n(render-state [_ state]"
"om/IRender\n(render [_]")
'(indent-according-to-mode)
\n > @ - ")"
'(indent-according-to-mode)
resume: "))"
'(om-insert-mode 1))
(define-skeleton init-state
"init state"
nil \n "om/IInitState" \n
> "(init-state [_] {" @ " }"
\n ")" \n >)
(defgroup om-mode nil
"Customization group for `om-mode'."
:group 'convenience)
(defconst om-insert-mode-map
(let ((map (make-sparse-keymap)))
(define-key map [remap next-line] 'om-next-position)
(define-key map [remap previous-line] (lambda () (interactive) (om-next-position 1)))
(define-key map (kbd "C-c C-c") 'om-exit-edit)
map)
"Keymap used in om mode.")
(defcustom om-expand-abbrev "om"
"This is the abbrev to expand an Om component."
:group 'om-mode
:type '(string))
(make-variable-buffer-local
(defvar om-markers nil
"Markers for locations saved in skeleton-positions."))
(defun om-make-markers ()
"Make markers in skeleton."
(while om-markers
(set-marker (pop om-markers) nil))
(setq om-markers
(mapcar 'copy-marker (reverse skeleton-positions))))
(defun om-exit-edit ()
"Reset the variable with Om markers, so that `next line' can be bound to default."
(interactive)
(om-insert-mode -1))
(defun om-next-position (&optional reverse)
"Jump to next position in skeleton.
REVERSE - Jump to previous position in skeleton"
(interactive "P")
(let* ((positions (mapcar 'marker-position om-markers))
(positions (if reverse (reverse positions) positions))
(comp (if reverse '> '<))
pos)
(when positions
(if (catch 'break
(while (setq pos (pop positions))
(when (funcall comp (point) pos)
(throw 'break t))))
(goto-char pos)
(goto-char (marker-position
(car om-markers)))))))
;; abbrev table for this mode
;;
(defun om-install-abbrevs ()
"Install default abbrev table for clojure if none is available."
(if (and (boundp 'clojure-mode-abbrev-table)
(not (equal clojure-mode-abbrev-table (make-abbrev-table))))
(let ((save-abbrevs 'silently))
(define-abbrev clojure-mode-abbrev-table om-expand-abbrev "" 'om-insert-template)
(message "Clojure abbrevs already exists, om abbrev added to it"))
(let ((save-abbrevs nil))
(define-abbrev-table 'clojure-mode-abbrev-table om-expand-abbrev "" 'om-insert-template)
(message "Clojure abbrevs loaded."))))
(unless noninteractive
(om-install-abbrevs))
(define-minor-mode om-insert-mode
"Toggle om mode."
:init-value nil
;; The indicator for the mode line.
:keymap om-insert-mode-map
:lighter " OmInsert"
;; The minor mode bindings.
:global nil
:group 'om-mode
(if om-insert-mode
(progn
(om-make-markers)
(message "Use C-n and C-p to move between Om fields, C-c C-c to finish."))
(message "Om insertion stopped.")))
(provide 'om-mode)
;;; om-mode.el ends here