107
|
1 ;; This django-html-mode is mainly derived from html mode |
|
2 (require 'sgml-mode) |
|
3 |
|
4 (defvar django-html-mode-hook nil) |
|
5 |
|
6 (defvar django-html-mode-map |
|
7 (let ((django-html-mode-map (make-keymap))) |
|
8 (define-key django-html-mode-map "\C-j" 'newline-and-indent) |
|
9 django-html-mode-map) |
|
10 "Keymap for Django major mode") |
|
11 |
|
12 ;; if : if, if not, if A or B, if not A or B, if not A and B |
|
13 ;; for : for a in alist reversed |
|
14 ;; forloop.counter The current iteration of the loop (1-indexed) |
|
15 ;; forloop.counter0 The current iteration of the loop (0-indexed) |
|
16 ;; forloop.revcounter The number of iterations from the end of the loop (1-indexed) |
|
17 ;; forloop.revcounter0 The number of iterations from the end of the loop (0-indexed) |
|
18 ;; forloop.first True if this is the first time through the loop |
|
19 ;; forloop.last True if this is the last time through the loop |
|
20 ;; forloop.parentloop For nested loops, this is the loop "above" the current one |
|
21 |
|
22 ;; ifequal : ifequal A B |
|
23 ;; comment : {% This is comment %} |
|
24 ;; filter : {{ name | lower }} |
|
25 |
|
26 ;; keyword-end : if, for, ifequal, block, ifnotequal, spaceless |
|
27 ;; keyword-3 : regroup |
|
28 ;; keyword-2 : for, ifequal |
|
29 ;; keyword-1 : if, block, extends, include, ifchanged, load, now, ssi, withratio |
|
30 ;; keyword-0 : else, spaceless |
|
31 |
|
32 ;; start and end keyword for block/comment/variable |
|
33 (defconst django-html-open-block "{%") |
|
34 (defconst django-html-close-block "%}") |
|
35 (defconst django-html-open-comment "{#") |
|
36 (defconst django-html-close-comment "#}") |
|
37 (defconst django-html-open-variable "{{") |
|
38 (defconst django-html-close-variable "}}") |
|
39 |
|
40 (defconst django-html-font-lock-keywords-1 |
|
41 (append |
|
42 ;; html-mode keyword |
|
43 sgml-font-lock-keywords-1) |
|
44 |
|
45 "First level keyword highlighting") |
|
46 |
|
47 (defconst django-html-font-lock-keywords-2 |
|
48 (append |
|
49 django-html-font-lock-keywords-1 |
|
50 sgml-font-lock-keywords-2)) |
|
51 |
|
52 (defconst django-html-font-lock-keywords-3 |
|
53 (append |
|
54 django-html-font-lock-keywords-1 |
|
55 django-html-font-lock-keywords-2 |
|
56 |
|
57 `(;; comment |
|
58 (,(rx (eval django-html-open-comment) |
|
59 (1+ space) |
|
60 (0+ (not (any "#"))) |
|
61 (1+ space) |
|
62 (eval django-html-close-comment)) |
|
63 . font-lock-comment-face) |
|
64 |
|
65 ;; variable font lock |
|
66 (,(rx (eval django-html-open-variable) |
|
67 (1+ space) |
|
68 (group (0+ (not (any "}")))) |
|
69 (1+ space) |
|
70 (eval django-html-close-variable)) |
|
71 (1 font-lock-variable-name-face)) |
|
72 |
|
73 ;; start, end keyword font lock |
|
74 (,(rx (group (or (eval django-html-open-block) |
|
75 (eval django-html-close-block) |
|
76 (eval django-html-open-comment) |
|
77 (eval django-html-close-comment) |
|
78 (eval django-html-open-variable) |
|
79 (eval django-html-close-variable)))) |
|
80 (1 font-lock-builtin-face)) |
|
81 |
|
82 ;; end prefix keyword font lock |
|
83 (,(rx (eval django-html-open-block) |
|
84 (1+ space) |
|
85 (group (and "end" |
|
86 ;; end prefix keywords |
|
87 (or "if" "for" "ifequal" "block" "ifnotequal" "spaceless" "filter"))) |
|
88 (1+ space) |
|
89 (eval django-html-close-block)) |
|
90 (1 font-lock-keyword-face)) |
|
91 |
|
92 ;; more words after keyword |
|
93 (,(rx (eval django-html-open-block) |
|
94 (1+ space) |
|
95 (group (or "extends" "for" "cycle" "filter" "if not" "else" |
|
96 "firstof" "debug" "if" "ifchanged" "ifequal" "ifnotequal" |
|
97 "include" "load" "now" "regroup" "spaceless" "ssi" |
|
98 "templatetag" "widthratio" "block")) |
|
99 |
|
100 ;; TODO: is there a more beautiful way? |
|
101 (0+ (not (any "}"))) |
|
102 |
|
103 (1+ space) |
|
104 (eval django-html-close-block)) |
|
105 (1 font-lock-keyword-face)) |
|
106 |
|
107 ;; TODO: if specific cases for supporting "or", "not", and "and" |
|
108 |
|
109 ;; for sepcific cases for supporting in |
|
110 (,(rx (eval django-html-open-block) |
|
111 (1+ space) |
|
112 "for" |
|
113 (1+ space) |
|
114 |
|
115 (group (1+ (or word ?_ ?.))) |
|
116 |
|
117 (1+ space) |
|
118 (group "in") |
|
119 (1+ space) |
|
120 |
|
121 (group (1+ (or word ?_ ?.))) |
|
122 |
|
123 (group (? (1+ space) "reverse")) |
|
124 |
|
125 (1+ space) |
|
126 (eval django-html-close-block)) |
|
127 (1 font-lock-variable-name-face) (2 font-lock-keyword-face) |
|
128 (3 font-lock-variable-name-face) (4 font-lock-keyword-face))))) |
|
129 |
|
130 (defvar django-html-font-lock-keywords |
|
131 django-html-font-lock-keywords-1) |
|
132 |
|
133 (defvar django-html-mode-syntax-table |
|
134 (let ((django-html-mode-syntax-table (make-syntax-table))) |
|
135 django-html-mode-syntax-table) |
|
136 "Syntax table for django-html-mode") |
|
137 |
|
138 ;;;###autoload |
|
139 (define-derived-mode django-html-mode html-mode "django-html" |
|
140 "Major mode for editing django html files(.djhtml)" |
|
141 :group 'django-html |
|
142 |
|
143 ;; it mainly from sgml-mode font lock setting |
|
144 (set (make-local-variable 'font-lock-defaults) |
|
145 '((django-html-font-lock-keywords |
|
146 django-html-font-lock-keywords-1 |
|
147 django-html-font-lock-keywords-2 |
|
148 django-html-font-lock-keywords-3) |
|
149 nil t nil nil |
|
150 (font-lock-syntactic-keywords |
|
151 . sgml-font-lock-syntactic-keywords)))) |
|
152 |
|
153 (add-to-list 'auto-mode-alist '("\\.djhtml$'" . django-html-mode)) |
|
154 |
|
155 (provide 'django-html-mode) |