slim 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ !!! html
2
+
3
+ %body
4
+ %head
5
+ %title Simple Benchmark
6
+ %body
7
+ %h1= header
8
+ - unless item.empty?
9
+ %ul
10
+ - for i in item
11
+ - if i[:current]
12
+ %li
13
+ %strong= i[:name]
14
+ - else
15
+ %li
16
+ %a{:href => i[:url]}= i[:name]
17
+ - else
18
+ %p The list is empty.
@@ -0,0 +1,17 @@
1
+ doctype html
2
+ html
3
+ head
4
+ title Simple Benchmark
5
+ body
6
+ h1 == header
7
+ - unless item.empty?
8
+ ul
9
+ - for i in item
10
+ - if i[:current]
11
+ li
12
+ strong == i[:name]
13
+ - else
14
+ li
15
+ a href=i[:url] == i[:name]
16
+ - else
17
+ p The list is empty.
@@ -0,0 +1,15 @@
1
+ require 'tilt'
2
+
3
+ class ComplexView
4
+ def header
5
+ "Colors"
6
+ end
7
+
8
+ def item
9
+ items = []
10
+ items << { :name => 'red', :current => true, :url => '#red' }
11
+ items << { :name => 'green', :current => false, :url => '#green' }
12
+ items << { :name => 'blue', :current => false, :url => '#blue' }
13
+ items
14
+ end
15
+ end
@@ -0,0 +1,409 @@
1
+ ;;; slim-mode.el --- Major mode for editing Slim files
2
+
3
+ ;; Copyright (c) 2007, 2008 Nathan Weizenbaum
4
+ ;; Modified slightly for Slim by Daniel Mendler
5
+
6
+ ;; Author: Nathan Weizenbaum
7
+ ;; URL: http://github.com/stonean/slim
8
+ ;; Version: 1.0
9
+ ;; Keywords: markup, language
10
+
11
+ ;;; Commentary:
12
+
13
+ ;; Because Slim's indentation schema is similar
14
+ ;; to that of YAML and Python, many indentation-related
15
+ ;; functions are similar to those in yaml-mode and python-mode.
16
+
17
+ ;; TODO: This whole file has to be reworked to provide optimal support
18
+ ;; for Slim. This is only a slightly adapted haml version.
19
+
20
+ ;; To install, save this on your load path and add the following to
21
+ ;; your .emacs file:
22
+
23
+ ;;
24
+ ;; (require 'slim-mode)
25
+
26
+ ;;; Code:
27
+
28
+ (eval-when-compile (require 'cl))
29
+
30
+ ;; User definable variables
31
+
32
+ (defgroup slim nil
33
+ "Support for the Slim template language."
34
+ :group 'languages
35
+ :prefix "slim-")
36
+
37
+ (defcustom slim-mode-hook nil
38
+ "Hook run when entering Slim mode."
39
+ :type 'hook
40
+ :group 'slim)
41
+
42
+ (defcustom slim-indent-offset 2
43
+ "Amount of offset per level of indentation."
44
+ :type 'integer
45
+ :group 'slim)
46
+
47
+ (defcustom slim-backspace-backdents-nesting t
48
+ "Non-nil to have `slim-electric-backspace' re-indent all code
49
+ nested beneath the backspaced line be re-indented along with the
50
+ line itself."
51
+ :type 'boolean
52
+ :group 'slim)
53
+
54
+ (defface slim-tab-face
55
+ '((((class color)) (:background "hotpink"))
56
+ (t (:reverse-video t)))
57
+ "Face to use for highlighting tabs in Slim files."
58
+ :group 'faces
59
+ :group 'slim)
60
+
61
+ (defvar slim-indent-function 'slim-indent-p
62
+ "This function should look at the current line and return true
63
+ if the next line could be nested within this line.")
64
+
65
+ (defvar slim-block-openers
66
+ `("^ *\\([\\.#a-z][^ \t]*\\)\\(\\[.*\\]\\)?[ \t]*$"
67
+ "^ *[-=].*do[ \t]*\\(|.*|[ \t]*\\)?$"
68
+ ,(concat "^ *-[ \t]*\\("
69
+ (regexp-opt '("if" "unless" "while" "until" "else"
70
+ "begin" "elsif" "rescue" "ensure" "when"))
71
+ "\\)")
72
+ "^ *|"
73
+ "^ */"
74
+ "^ *[a-z0-9_]:")
75
+ "A list of regexps that match lines of Slim that could have
76
+ text nested beneath them.")
77
+
78
+ ;; Font lock
79
+
80
+ ;; Helper for nested block (comment, embedded, text)
81
+ (defun slim-nested-re (re)
82
+ (concat "^\\( *\\)" re "\n\\(?:\\(?:\\1 .*\\)\n\\)*"))
83
+
84
+ (defconst slim-font-lock-keywords
85
+ `((,(slim-nested-re "/.*") 0 font-lock-comment-face) ;; Comment block
86
+ (,(slim-nested-re "[a-z0-9_]+:") 0 font-lock-string-face) ;; Embedded block
87
+ (,(slim-nested-re "[\|'`].*") 0 font-lock-string-face) ;; Text block
88
+ ("^!.*" 0 font-lock-constant-face) ;; Directive
89
+ ("^ *\\(\t\\)" 1 'slim-tab-face)
90
+ ("\\('[^']*'\\)" 1 font-lock-string-face append) ;; Single quote string TODO
91
+ ("\\(\"[^\"]*\"\\)" 1 font-lock-string-face append) ;; Double quoted string TODO
92
+ ("@[a-z0-9_]+" 0 font-lock-variable-name-face append) ;; Class variable TODO
93
+ ("^ *\\(#[a-z0-9_]+\/?\\)" 1 font-lock-keyword-face) ;; #id
94
+ ("^ *\\(\\.[a-z0-9_]+\/?\\)" 1 font-lock-type-face) ;; .class
95
+ ("^ *\\([a-z0-9_]+\/?\\)" 1 font-lock-function-name-face) ;; div
96
+ ("^ *\\(#[a-z0-9_]+\/?\\)" (1 font-lock-keyword-face) ;; #id.class
97
+ ("\\.[a-z0-9_]+" nil nil (0 font-lock-type-face)))
98
+ ("^ *\\(\\.[a-z0-9_]+\/?\\)" (1 font-lock-type-face) ;; .class.class
99
+ ("\\.[a-z0-9_]+" nil nil (0 font-lock-type-face)))
100
+ ("^ *\\(\\.[a-z0-9_]+\/?\\)" (1 font-lock-type-face) ;; .class#id
101
+ ("\\#[a-z0-9_]+" nil nil (0 font-lock-keyword-face)))
102
+ ("^ *\\([a-z0-9_]+\/?\\)" (1 font-lock-function-name-face) ;; div.class
103
+ ("\\.[a-z0-9_]+" nil nil (0 font-lock-type-face)))
104
+ ("^ *\\([a-z0-9_]+\/?\\)" (1 font-lock-function-name-face) ;; div#id
105
+ ("\\#[a-z0-9_]+" nil nil (0 font-lock-keyword-face)))
106
+ ("^ *\\(\\(==?|-\\) .*\\)" 1 font-lock-preprocessor-face prepend) ;; ==, =, -
107
+ ("^ *[\\.#a-z0-9_]+\\(==? .*\\)" 1 font-lock-preprocessor-face prepend))) ;; tag ==, tag =
108
+
109
+ (defconst slim-embedded-re "^ *[a-z0-9_]+:")
110
+ (defconst slim-comment-re "^ */")
111
+
112
+ (defun* slim-extend-region ()
113
+ "Extend the font-lock region to encompass embedded engines and comments."
114
+ (let ((old-beg font-lock-beg)
115
+ (old-end font-lock-end))
116
+ (save-excursion
117
+ (goto-char font-lock-beg)
118
+ (beginning-of-line)
119
+ (unless (or (looking-at slim-embedded-re)
120
+ (looking-at slim-comment-re))
121
+ (return-from slim-extend-region))
122
+ (setq font-lock-beg (point))
123
+ (slim-forward-sexp)
124
+ (beginning-of-line)
125
+ (setq font-lock-end (max font-lock-end (point))))
126
+ (or (/= old-beg font-lock-beg)
127
+ (/= old-end font-lock-end))))
128
+
129
+
130
+ ;; Mode setup
131
+
132
+ (defvar slim-mode-syntax-table
133
+ (let ((table (make-syntax-table)))
134
+ (modify-syntax-entry ?: "." table)
135
+ (modify-syntax-entry ?_ "w" table)
136
+ table)
137
+ "Syntax table in use in slim-mode buffers.")
138
+
139
+ (defvar slim-mode-map
140
+ (let ((map (make-sparse-keymap)))
141
+ (define-key map [backspace] 'slim-electric-backspace)
142
+ (define-key map "\C-?" 'slim-electric-backspace)
143
+ (define-key map "\C-c\C-f" 'slim-forward-sexp)
144
+ (define-key map "\C-c\C-b" 'slim-backward-sexp)
145
+ (define-key map "\C-c\C-u" 'slim-up-list)
146
+ (define-key map "\C-c\C-d" 'slim-down-list)
147
+ (define-key map "\C-c\C-k" 'slim-kill-line-and-indent)
148
+ map))
149
+
150
+ ;;;###autoload
151
+ (define-derived-mode slim-mode fundamental-mode "Slim"
152
+ "Major mode for editing Slim files.
153
+
154
+ \\{slim-mode-map}"
155
+ (set-syntax-table slim-mode-syntax-table)
156
+ (add-to-list 'font-lock-extend-region-functions 'slim-extend-region)
157
+ (set (make-local-variable 'font-lock-multiline) t)
158
+ (set (make-local-variable 'indent-line-function) 'slim-indent-line)
159
+ (set (make-local-variable 'indent-region-function) 'slim-indent-region)
160
+ (set (make-local-variable 'parse-sexp-lookup-properties) t)
161
+ (setq comment-start "/")
162
+ (setq indent-tabs-mode nil)
163
+ (setq font-lock-defaults '((slim-font-lock-keywords) nil t)))
164
+
165
+ ;; Useful functions
166
+
167
+ (defun slim-comment-block ()
168
+ "Comment the current block of Slim code."
169
+ (interactive)
170
+ (save-excursion
171
+ (let ((indent (current-indentation)))
172
+ (back-to-indentation)
173
+ (insert "/")
174
+ (newline)
175
+ (indent-to indent)
176
+ (beginning-of-line)
177
+ (slim-mark-sexp)
178
+ (slim-reindent-region-by slim-indent-offset))))
179
+
180
+ (defun slim-uncomment-block ()
181
+ "Uncomment the current block of Slim code."
182
+ (interactive)
183
+ (save-excursion
184
+ (beginning-of-line)
185
+ (while (not (looking-at slim-comment-re))
186
+ (slim-up-list)
187
+ (beginning-of-line))
188
+ (slim-mark-sexp)
189
+ (kill-line 1)
190
+ (slim-reindent-region-by (- slim-indent-offset))))
191
+
192
+ ;; Navigation
193
+
194
+ (defun slim-forward-through-whitespace (&optional backward)
195
+ "Move the point forward at least one line, until it reaches
196
+ either the end of the buffer or a line with no whitespace.
197
+
198
+ If `backward' is non-nil, move the point backward instead."
199
+ (let ((arg (if backward -1 1))
200
+ (endp (if backward 'bobp 'eobp)))
201
+ (loop do (forward-line arg)
202
+ while (and (not (funcall endp))
203
+ (looking-at "^[ \t]*$")))))
204
+
205
+ (defun slim-at-indent-p ()
206
+ "Returns whether or not the point is at the first
207
+ non-whitespace character in a line or whitespace preceding that
208
+ character."
209
+ (let ((opoint (point)))
210
+ (save-excursion
211
+ (back-to-indentation)
212
+ (>= (point) opoint))))
213
+
214
+ (defun slim-forward-sexp (&optional arg)
215
+ "Move forward across one nested expression.
216
+ With `arg', do it that many times. Negative arg -N means move
217
+ backward across N balanced expressions.
218
+
219
+ A sexp in Slim is defined as a line of Slim code as well as any
220
+ lines nested beneath it."
221
+ (interactive "p")
222
+ (or arg (setq arg 1))
223
+ (if (and (< arg 0) (not (slim-at-indent-p)))
224
+ (back-to-indentation)
225
+ (while (/= arg 0)
226
+ (let ((indent (current-indentation)))
227
+ (loop do (slim-forward-through-whitespace (< arg 0))
228
+ while (and (not (eobp))
229
+ (not (bobp))
230
+ (> (current-indentation) indent)))
231
+ (back-to-indentation)
232
+ (setq arg (+ arg (if (> arg 0) -1 1)))))))
233
+
234
+ (defun slim-backward-sexp (&optional arg)
235
+ "Move backward across one nested expression.
236
+ With ARG, do it that many times. Negative arg -N means move
237
+ forward across N balanced expressions.
238
+
239
+ A sexp in Slim is defined as a line of Slim code as well as any
240
+ lines nested beneath it."
241
+ (interactive "p")
242
+ (slim-forward-sexp (if arg (- arg) -1)))
243
+
244
+ (defun slim-up-list (&optional arg)
245
+ "Move out of one level of nesting.
246
+ With ARG, do this that many times."
247
+ (interactive "p")
248
+ (or arg (setq arg 1))
249
+ (while (> arg 0)
250
+ (let ((indent (current-indentation)))
251
+ (loop do (slim-forward-through-whitespace t)
252
+ while (and (not (bobp))
253
+ (>= (current-indentation) indent)))
254
+ (setq arg (- arg 1))))
255
+ (back-to-indentation))
256
+
257
+ (defun slim-down-list (&optional arg)
258
+ "Move down one level of nesting.
259
+ With ARG, do this that many times."
260
+ (interactive "p")
261
+ (or arg (setq arg 1))
262
+ (while (> arg 0)
263
+ (let ((indent (current-indentation)))
264
+ (slim-forward-through-whitespace)
265
+ (when (<= (current-indentation) indent)
266
+ (slim-forward-through-whitespace t)
267
+ (back-to-indentation)
268
+ (error "Nothing is nested beneath this line"))
269
+ (setq arg (- arg 1))))
270
+ (back-to-indentation))
271
+
272
+ (defun slim-mark-sexp ()
273
+ "Marks the next Slim block."
274
+ (let ((forward-sexp-function 'slim-forward-sexp))
275
+ (mark-sexp)))
276
+
277
+ (defun slim-mark-sexp-but-not-next-line ()
278
+ "Marks the next Slim block, but puts the mark at the end of the
279
+ last line of the sexp rather than the first non-whitespace
280
+ character of the next line."
281
+ (slim-mark-sexp)
282
+ (set-mark
283
+ (save-excursion
284
+ (goto-char (mark))
285
+ (forward-line -1)
286
+ (end-of-line)
287
+ (point))))
288
+
289
+ ;; Indentation and electric keys
290
+
291
+ (defun slim-indent-p ()
292
+ "Returns true if the current line can have lines nested beneath it."
293
+ (loop for opener in slim-block-openers
294
+ if (looking-at opener) return t
295
+ finally return nil))
296
+
297
+ (defun slim-compute-indentation ()
298
+ "Calculate the maximum sensible indentation for the current line."
299
+ (save-excursion
300
+ (beginning-of-line)
301
+ (if (bobp) 0
302
+ (slim-forward-through-whitespace t)
303
+ (+ (current-indentation)
304
+ (if (funcall slim-indent-function) slim-indent-offset
305
+ 0)))))
306
+
307
+ (defun slim-indent-region (start end)
308
+ "Indent each nonblank line in the region.
309
+ This is done by indenting the first line based on
310
+ `slim-compute-indentation' and preserving the relative
311
+ indentation of the rest of the region.
312
+
313
+ If this command is used multiple times in a row, it will cycle
314
+ between possible indentations."
315
+ (save-excursion
316
+ (goto-char end)
317
+ (setq end (point-marker))
318
+ (goto-char start)
319
+ (let (this-line-column current-column
320
+ (next-line-column
321
+ (if (and (equal last-command this-command) (/= (current-indentation) 0))
322
+ (* (/ (- (current-indentation) 1) slim-indent-offset) slim-indent-offset)
323
+ (slim-compute-indentation))))
324
+ (while (< (point) end)
325
+ (setq this-line-column next-line-column
326
+ current-column (current-indentation))
327
+ ;; Delete whitespace chars at beginning of line
328
+ (delete-horizontal-space)
329
+ (unless (eolp)
330
+ (setq next-line-column (save-excursion
331
+ (loop do (forward-line 1)
332
+ while (and (not (eobp)) (looking-at "^[ \t]*$")))
333
+ (+ this-line-column
334
+ (- (current-indentation) current-column))))
335
+ ;; Don't indent an empty line
336
+ (unless (eolp) (indent-to this-line-column)))
337
+ (forward-line 1)))
338
+ (move-marker end nil)))
339
+
340
+ (defun slim-indent-line ()
341
+ "Indent the current line.
342
+ The first time this command is used, the line will be indented to the
343
+ maximum sensible indentation. Each immediately subsequent usage will
344
+ back-dent the line by `slim-indent-offset' spaces. On reaching column
345
+ 0, it will cycle back to the maximum sensible indentation."
346
+ (interactive "*")
347
+ (let ((ci (current-indentation))
348
+ (cc (current-column))
349
+ (need (slim-compute-indentation)))
350
+ (save-excursion
351
+ (beginning-of-line)
352
+ (delete-horizontal-space)
353
+ (if (and (equal last-command this-command) (/= ci 0))
354
+ (indent-to (* (/ (- ci 1) slim-indent-offset) slim-indent-offset))
355
+ (indent-to need)))
356
+ (if (< (current-column) (current-indentation))
357
+ (forward-to-indentation 0))))
358
+
359
+ (defun slim-reindent-region-by (n)
360
+ "Add N spaces to the beginning of each line in the region.
361
+ If N is negative, will remove the spaces instead. Assumes all
362
+ lines in the region have indentation >= that of the first line."
363
+ (let ((ci (current-indentation)))
364
+ (save-excursion
365
+ (replace-regexp (concat "^" (make-string ci ? ))
366
+ (make-string (max 0 (+ ci n)) ? )
367
+ nil (point) (mark)))))
368
+
369
+ (defun slim-electric-backspace (arg)
370
+ "Delete characters or back-dent the current line.
371
+ If invoked following only whitespace on a line, will back-dent
372
+ the line and all nested lines to the immediately previous
373
+ multiple of `slim-indent-offset' spaces.
374
+
375
+ Set `slim-backspace-backdents-nesting' to nil to just back-dent
376
+ the current line."
377
+ (interactive "*p")
378
+ (if (or (/= (current-indentation) (current-column))
379
+ (bolp)
380
+ (looking-at "^[ \t]+$"))
381
+ (backward-delete-char arg)
382
+ (save-excursion
383
+ (let ((ci (current-column)))
384
+ (beginning-of-line)
385
+ (if slim-backspace-backdents-nesting
386
+ (slim-mark-sexp-but-not-next-line)
387
+ (set-mark (save-excursion (end-of-line) (point))))
388
+ (slim-reindent-region-by (* (- arg) slim-indent-offset))
389
+ (back-to-indentation)
390
+ (pop-mark)))))
391
+
392
+ (defun slim-kill-line-and-indent ()
393
+ "Kill the current line, and re-indent all lines nested beneath it."
394
+ (interactive)
395
+ (beginning-of-line)
396
+ (slim-mark-sexp-but-not-next-line)
397
+ (kill-line 1)
398
+ (slim-reindent-region-by (* -1 slim-indent-offset)))
399
+
400
+ (defun slim-indent-string ()
401
+ "Return the indentation string for `slim-indent-offset'."
402
+ (mapconcat 'identity (make-list slim-indent-offset " ") ""))
403
+
404
+ ;;;###autoload
405
+ (add-to-list 'auto-mode-alist '("\\.slim$" . slim-mode))
406
+
407
+ ;; Setup/Activation
408
+ (provide 'slim-mode)
409
+ ;;; slim-mode.el ends here