OLD | NEW |
---|---|
1 ;;; gn.el - A major mode for editing gn files. | 1 ;;; gn-mode.el - A major mode for editing gn files. |
2 | 2 |
3 ;; Copyright 2015 The Chromium Authors. All rights reserved. | 3 ;; Copyright 2015 The Chromium Authors. All rights reserved. |
4 ;; Use of this source code is governed by a BSD-style license that can be | 4 ;; Use of this source code is governed by a BSD-style license that can be |
5 ;; found in the LICENSE file. | 5 ;; found in the LICENSE file. |
6 | 6 |
7 ;; Put this somewhere in your load-path and | 7 ;; Author: Elliot Glaysher <erg@chromium.org> |
8 ;; (require 'gn) | 8 ;; Created: April 03, 2015 |
9 ;; Keywords: tools, gn, ninja, chromium | |
9 | 10 |
10 ;; TODO(erg): There's a lot of general improvements that could be made here: | 11 ;; This file is not part of GNU Emacs. |
11 ;; | 12 |
13 ;;; Commentary: | |
14 | |
15 ;; A major mode for editing GN files. GN stands for Generate Ninja. GN is the | |
16 ;; meta build system used in Chromium. For more information on GN, see the GN | |
17 ;; manual: <https://code.google.com/p/chromium/wiki/gn> | |
18 | |
19 ;;; To Do: | |
20 | |
12 ;; - We syntax highlight builtin actions, but don't highlight instantiations of | 21 ;; - We syntax highlight builtin actions, but don't highlight instantiations of |
13 ;; templates. Should we? | 22 ;; templates. Should we? |
14 ;; - `fill-paragraph' works for comments, but when pointed at code, breaks | 23 ;; - `fill-paragraph' works for comments, but when pointed at code, breaks |
15 ;; spectacularly. | 24 ;; spectacularly. |
16 ;; - Might want to support `imenu' users. Even if it's just a list of toplevel | 25 |
17 ;; targets? | 26 |
18 | 27 |
19 (eval-when-compile (require 'cl)) ;For the `case' macro. | 28 (eval-when-compile (require 'cl)) ;For the `case' macro. |
20 (require 'smie) | 29 (require 'smie) |
21 | 30 |
31 (defgroup gn nil | |
32 "Major mode for editing Generate Ninja files." | |
33 :prefix "gn-" | |
34 :group 'languages) | |
35 | |
36 (defcustom gn-indent-basic 2 | |
37 "The number of spaces to indent a new scope." | |
38 :group 'gn | |
39 :type 'integer) | |
40 | |
41 (defgroup gn-faces nil | |
42 "Faces used in Generate Ninja mode." | |
43 :group 'gn | |
44 :group 'faces) | |
45 | |
46 (defface gn-embedded-variable | |
47 '((t :inherit font-lock-variable-name-face)) | |
48 "Font lock face used to highlight variable names in strings." | |
49 :group 'gn-faces) | |
50 | |
51 (defface gn-embedded-variable-boundary | |
52 '((t :bold t | |
53 :inherit gn-embedded-variable)) | |
54 "Font lock face used to highlight the '$' that starts a | |
55 variable name or the '{{' and '}}' which surround it." | |
56 :group 'gn-faces) | |
57 | |
22 (defvar gn-font-lock-target-declaration-keywords | 58 (defvar gn-font-lock-target-declaration-keywords |
23 '("action" "action_foreach" "copy" "executable" "group" | 59 '("action" "action_foreach" "copy" "executable" "group" |
24 "shared_library" "source_set" "static_library" "if" "else")) | 60 "shared_library" "source_set" "static_library" "if" "else")) |
25 | 61 |
26 (defvar gn-font-lock-buildfile-fun-keywords | 62 (defvar gn-font-lock-buildfile-fun-keywords |
27 '("assert" "config" "declare_args" "defined" "exec_script" "foreach" | 63 '("assert" "config" "declare_args" "defined" "exec_script" "foreach" |
28 "get_label_info" "get_path_info" "get_target_outputs" "getenv" "import" | 64 "get_label_info" "get_path_info" "get_target_outputs" "getenv" "import" |
29 "print" "process_file_template" "read_file" "rebase_path" | 65 "print" "process_file_template" "read_file" "rebase_path" |
30 "set_default_toolchain" "set_defaults" "set_sources_assignment_filter" | 66 "set_default_toolchain" "set_defaults" "set_sources_assignment_filter" |
31 "template" "tool" "toolchain" "toolchain_args" "write_file")) | 67 "template" "tool" "toolchain" "toolchain_args" "write_file")) |
(...skipping 13 matching lines...) Expand all Loading... | |
45 "visibility")) | 81 "visibility")) |
46 | 82 |
47 (defconst gn-font-lock-keywords | 83 (defconst gn-font-lock-keywords |
48 `((,(regexp-opt gn-font-lock-target-declaration-keywords 'words) . | 84 `((,(regexp-opt gn-font-lock-target-declaration-keywords 'words) . |
49 font-lock-keyword-face) | 85 font-lock-keyword-face) |
50 (,(regexp-opt gn-font-lock-buildfile-fun-keywords 'words) . | 86 (,(regexp-opt gn-font-lock-buildfile-fun-keywords 'words) . |
51 font-lock-function-name-face) | 87 font-lock-function-name-face) |
52 (,(regexp-opt gn-font-lock-predefined-var-keywords 'words) . | 88 (,(regexp-opt gn-font-lock-predefined-var-keywords 'words) . |
53 font-lock-constant-face) | 89 font-lock-constant-face) |
54 (,(regexp-opt gn-font-lock-var-keywords 'words) . | 90 (,(regexp-opt gn-font-lock-var-keywords 'words) . |
55 font-lock-variable-name-face))) | 91 font-lock-variable-name-face) |
56 | 92 ;; $variables_like_this |
Nico
2015/04/04 20:30:35
I like these comments.
| |
57 (defvar gn-indent-basic 2) | 93 ("\\(\\$\\)\\([a-zA-Z0-9_]+\\)" |
94 (1 'gn-embedded-variable-boundary t) | |
95 (2 'gn-embedded-variable t)) | |
96 ;; ${variables_like_this} | |
97 ("\\(\\${\\)\\([^\n }]+\\)\\(}\\)" | |
98 (1 'gn-embedded-variable-boundary t) | |
99 (2 'gn-embedded-variable t) | |
100 (3 'gn-embedded-variable-boundary t)) | |
101 ;; {{variables_like_this}} | |
102 ("\\({{\\)\\([^\n }]+\\)\\(}}\\)" | |
Nico
2015/04/04 20:30:34
Huh, I wasn't aware this is a thing. It's not on h
Elliot Glaysher
2015/04/07 18:01:20
Calling substitutions variables isn't strictly cor
| |
103 (1 'gn-embedded-variable-boundary t) | |
104 (2 'gn-embedded-variable t) | |
105 (3 'gn-embedded-variable-boundary t)))) | |
58 | 106 |
59 (defun gn-smie-rules (kind token) | 107 (defun gn-smie-rules (kind token) |
60 "These are slightly modified indentation rules from the SMIE | 108 "These are slightly modified indentation rules from the SMIE |
61 Indentation Example info page. This changes the :before rule | 109 Indentation Example info page. This changes the :before rule |
62 and adds a :list-intro to handle our x = [ ] syntax." | 110 and adds a :list-intro to handle our x = [ ] syntax." |
63 (pcase (cons kind token) | 111 (pcase (cons kind token) |
64 (`(:elem . basic) gn-indent-basic) | 112 (`(:elem . basic) gn-indent-basic) |
65 (`(,_ . ",") (smie-rule-separator kind)) | 113 (`(,_ . ",") (smie-rule-separator kind)) |
66 (`(:list-intro . "") gn-indent-basic) | 114 (`(:list-intro . "") gn-indent-basic) |
67 (`(:before . ,(or `"[" `"(" `"{")) | 115 (`(:before . ,(or `"[" `"(" `"{")) |
68 (if (smie-rule-hanging-p) (smie-rule-parent))) | 116 (if (smie-rule-hanging-p) (smie-rule-parent))) |
69 (`(:before . "if") | 117 (`(:before . "if") |
70 (and (not (smie-rule-bolp)) (smie-rule-prev-p "else") | 118 (and (not (smie-rule-bolp)) (smie-rule-prev-p "else") |
71 (smie-rule-parent))))) | 119 (smie-rule-parent))))) |
72 | 120 |
73 ;;;###autoload | 121 ;;;###autoload |
74 (define-derived-mode gn-mode prog-mode "GN" | 122 (define-derived-mode gn-mode prog-mode "GN" |
75 "Major mode for editing gn (Generate Ninja)." | 123 "Major mode for editing gn (Generate Ninja)." |
76 | 124 :group 'gn |
77 (setq-local font-lock-defaults '(gn-font-lock-keywords)) | |
78 | 125 |
79 (setq-local comment-use-syntax t) | 126 (setq-local comment-use-syntax t) |
80 (setq-local comment-start "#") | 127 (setq-local comment-start "#") |
81 (setq-local comment-end "") | 128 (setq-local comment-end "") |
82 | 129 |
130 (setq-local font-lock-defaults '(gn-font-lock-keywords)) | |
131 | |
132 (setq-local imenu-generic-expression | |
133 '((nil "^\s*[a-zA-Z0-9_]+(\"\\([a-zA-Z0-9_]+\\)\")\s*{" 1))) | |
Nico
2015/04/04 20:30:35
Maybe have a comment for this too?
| |
134 | |
83 (smie-setup nil #'gn-smie-rules) | 135 (smie-setup nil #'gn-smie-rules) |
84 (setq-local smie-indent-basic gn-indent-basic) | 136 (setq-local smie-indent-basic gn-indent-basic) |
85 | 137 |
86 ;; python style comment: “# …” | 138 ;; python style comment: “# …” |
87 (modify-syntax-entry ?# "< b" gn-mode-syntax-table) | 139 (modify-syntax-entry ?# "< b" gn-mode-syntax-table) |
88 (modify-syntax-entry ?\n "> b" gn-mode-syntax-table) | 140 (modify-syntax-entry ?\n "> b" gn-mode-syntax-table) |
89 (modify-syntax-entry ?_ "w" gn-mode-syntax-table)) | 141 (modify-syntax-entry ?_ "w" gn-mode-syntax-table)) |
90 | 142 |
91 ;;;###autoload | 143 ;;;###autoload |
92 (add-to-list 'auto-mode-alist '("\\.gni?\\'" . gn-mode)) | 144 (add-to-list 'auto-mode-alist '("\\.gni?\\'" . gn-mode)) |
93 | 145 |
94 (provide 'gn-mode) | 146 (provide 'gn-mode) |
OLD | NEW |