Evan Klitzke | 39d730d | 2020-05-17 11:10:23 -0700 | [diff] [blame] | 1 | ;;; protobuf-mode.el --- major mode for editing protocol buffers. -*- lexical-binding: t; -*- |
kenton@google.com | 2cdba5b | 2009-05-01 21:03:20 +0000 | [diff] [blame] | 2 | |
| 3 | ;; Author: Alexandre Vassalotti <alexandre@peadrop.com> |
| 4 | ;; Created: 23-Apr-2009 |
| 5 | ;; Version: 0.3 |
| 6 | ;; Keywords: google protobuf languages |
| 7 | |
| 8 | ;; Redistribution and use in source and binary forms, with or without |
| 9 | ;; modification, are permitted provided that the following conditions are |
| 10 | ;; met: |
| 11 | ;; |
| 12 | ;; * Redistributions of source code must retain the above copyright |
| 13 | ;; notice, this list of conditions and the following disclaimer. |
| 14 | ;; * Redistributions in binary form must reproduce the above |
| 15 | ;; copyright notice, this list of conditions and the following disclaimer |
| 16 | ;; in the documentation and/or other materials provided with the |
| 17 | ;; distribution. |
| 18 | ;; * Neither the name of Google Inc. nor the names of its |
| 19 | ;; contributors may be used to endorse or promote products derived from |
| 20 | ;; this software without specific prior written permission. |
| 21 | ;; |
| 22 | ;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 23 | ;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 24 | ;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 25 | ;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 26 | ;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 27 | ;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 28 | ;; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 29 | ;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 30 | ;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 31 | ;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 32 | ;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 33 | |
| 34 | ;;; Commentary: |
| 35 | |
| 36 | ;; Installation: |
| 37 | ;; - Put `protobuf-mode.el' in your Emacs load-path. |
| 38 | ;; - Add this line to your .emacs file: |
| 39 | ;; (require 'protobuf-mode) |
| 40 | ;; |
| 41 | ;; You can customize this mode just like any mode derived from CC Mode. If |
| 42 | ;; you want to add customizations specific to protobuf-mode, you can use the |
| 43 | ;; `protobuf-mode-hook'. For example, the following would make protocol-mode |
| 44 | ;; use 2-space indentation: |
| 45 | ;; |
| 46 | ;; (defconst my-protobuf-style |
| 47 | ;; '((c-basic-offset . 2) |
| 48 | ;; (indent-tabs-mode . nil))) |
| 49 | ;; |
| 50 | ;; (add-hook 'protobuf-mode-hook |
| 51 | ;; (lambda () (c-add-style "my-style" my-protobuf-style t))) |
| 52 | ;; |
| 53 | ;; Refer to the documentation of CC Mode for more information about |
| 54 | ;; customization details and how to use this mode. |
| 55 | ;; |
| 56 | ;; TODO: |
| 57 | ;; - Make highlighting for enum values work properly. |
| 58 | ;; - Fix the parser to recognize extensions as identifiers and not |
| 59 | ;; as casts. |
| 60 | ;; - Improve the parsing of option assignment lists. For example: |
| 61 | ;; optional int32 foo = 1 [(my_field_option) = 4.5]; |
| 62 | ;; - Add support for fully-qualified identifiers (e.g., with a leading "."). |
| 63 | |
| 64 | ;;; Code: |
| 65 | |
| 66 | (require 'cc-mode) |
| 67 | |
| 68 | (eval-when-compile |
Philipp Stephani | 979107e | 2017-05-18 20:24:04 +0200 | [diff] [blame] | 69 | (and (= emacs-major-version 24) |
| 70 | (>= emacs-minor-version 4) |
| 71 | (require 'cl)) |
kenton@google.com | 2cdba5b | 2009-05-01 21:03:20 +0000 | [diff] [blame] | 72 | (require 'cc-langs) |
| 73 | (require 'cc-fonts)) |
| 74 | |
Yutian Li | ddf6d1e | 2016-08-05 15:12:20 +0800 | [diff] [blame] | 75 | ;; This mode does not inherit properties from other modes. So, we do not use |
kenton@google.com | 2cdba5b | 2009-05-01 21:03:20 +0000 | [diff] [blame] | 76 | ;; the usual `c-add-language' function. |
kenton@google.com | d5cf7b5 | 2009-12-18 01:55:04 +0000 | [diff] [blame] | 77 | (eval-and-compile |
| 78 | (put 'protobuf-mode 'c-mode-prefix "protobuf-")) |
kenton@google.com | 2cdba5b | 2009-05-01 21:03:20 +0000 | [diff] [blame] | 79 | |
| 80 | ;; The following code uses of the `c-lang-defconst' macro define syntactic |
| 81 | ;; features of protocol buffer language. Refer to the documentation in the |
| 82 | ;; cc-langs.el file for information about the meaning of the -kwds variables. |
| 83 | |
| 84 | (c-lang-defconst c-primitive-type-kwds |
| 85 | protobuf '("double" "float" "int32" "int64" "uint32" "uint64" "sint32" |
| 86 | "sint64" "fixed32" "fixed64" "sfixed32" "sfixed64" "bool" |
| 87 | "string" "bytes" "group")) |
| 88 | |
| 89 | (c-lang-defconst c-modifier-kwds |
| 90 | protobuf '("required" "optional" "repeated")) |
| 91 | |
| 92 | (c-lang-defconst c-class-decl-kwds |
| 93 | protobuf '("message" "enum" "service")) |
| 94 | |
| 95 | (c-lang-defconst c-constant-kwds |
| 96 | protobuf '("true" "false")) |
| 97 | |
| 98 | (c-lang-defconst c-other-decl-kwds |
| 99 | protobuf '("package" "import")) |
| 100 | |
| 101 | (c-lang-defconst c-other-kwds |
| 102 | protobuf '("default" "max")) |
| 103 | |
| 104 | (c-lang-defconst c-identifier-ops |
| 105 | ;; Handle extended identifiers like google.protobuf.MessageOptions |
| 106 | protobuf '((left-assoc "."))) |
| 107 | |
| 108 | ;; The following keywords do not fit well in keyword classes defined by |
| 109 | ;; cc-mode. So, we approximate as best we can. |
| 110 | |
| 111 | (c-lang-defconst c-type-list-kwds |
Bo Yang | 5db2173 | 2015-05-21 14:28:59 -0700 | [diff] [blame] | 112 | protobuf '("extensions" "to" "reserved")) |
kenton@google.com | 2cdba5b | 2009-05-01 21:03:20 +0000 | [diff] [blame] | 113 | |
| 114 | (c-lang-defconst c-typeless-decl-kwds |
| 115 | protobuf '("extend" "rpc" "option" "returns")) |
| 116 | |
| 117 | |
| 118 | ;; Here we remove default syntax for loops, if-statements and other C |
| 119 | ;; syntactic features that are not supported by the protocol buffer language. |
| 120 | |
| 121 | (c-lang-defconst c-brace-list-decl-kwds |
| 122 | ;; Remove syntax for C-style enumerations. |
| 123 | protobuf nil) |
| 124 | |
| 125 | (c-lang-defconst c-block-stmt-1-kwds |
| 126 | ;; Remove syntax for "do" and "else" keywords. |
| 127 | protobuf nil) |
| 128 | |
| 129 | (c-lang-defconst c-block-stmt-2-kwds |
| 130 | ;; Remove syntax for "for", "if", "switch" and "while" keywords. |
| 131 | protobuf nil) |
| 132 | |
| 133 | (c-lang-defconst c-simple-stmt-kwds |
| 134 | ;; Remove syntax for "break", "continue", "goto" and "return" keywords. |
| 135 | protobuf nil) |
| 136 | |
| 137 | (c-lang-defconst c-paren-stmt-kwds |
| 138 | ;; Remove special case for the "(;;)" in for-loops. |
| 139 | protobuf nil) |
| 140 | |
| 141 | (c-lang-defconst c-label-kwds |
| 142 | ;; Remove case label syntax for the "case" and "default" keywords. |
| 143 | protobuf nil) |
| 144 | |
| 145 | (c-lang-defconst c-before-label-kwds |
| 146 | ;; Remove special case for the label in a goto statement. |
| 147 | protobuf nil) |
| 148 | |
| 149 | (c-lang-defconst c-cpp-matchers |
| 150 | ;; Disable all the C preprocessor syntax. |
| 151 | protobuf nil) |
| 152 | |
| 153 | (c-lang-defconst c-decl-prefix-re |
| 154 | ;; Same as for C, except it does not match "(". This is needed for disabling |
| 155 | ;; the syntax for casts. |
| 156 | protobuf "\\([\{\};,]+\\)") |
| 157 | |
| 158 | |
| 159 | ;; Add support for variable levels of syntax highlighting. |
| 160 | |
| 161 | (defconst protobuf-font-lock-keywords-1 (c-lang-const c-matchers-1 protobuf) |
| 162 | "Minimal highlighting for protobuf-mode.") |
| 163 | |
| 164 | (defconst protobuf-font-lock-keywords-2 (c-lang-const c-matchers-2 protobuf) |
| 165 | "Fast normal highlighting for protobuf-mode.") |
| 166 | |
| 167 | (defconst protobuf-font-lock-keywords-3 (c-lang-const c-matchers-3 protobuf) |
| 168 | "Accurate normal highlighting for protobuf-mode.") |
| 169 | |
| 170 | (defvar protobuf-font-lock-keywords protobuf-font-lock-keywords-3 |
| 171 | "Default expressions to highlight in protobuf-mode.") |
| 172 | |
| 173 | ;; Our syntax table is auto-generated from the keyword classes we defined |
| 174 | ;; previously with the `c-lang-const' macro. |
| 175 | (defvar protobuf-mode-syntax-table nil |
| 176 | "Syntax table used in protobuf-mode buffers.") |
| 177 | (or protobuf-mode-syntax-table |
| 178 | (setq protobuf-mode-syntax-table |
| 179 | (funcall (c-lang-const c-make-mode-syntax-table protobuf)))) |
| 180 | |
| 181 | (defvar protobuf-mode-abbrev-table nil |
| 182 | "Abbreviation table used in protobuf-mode buffers.") |
| 183 | |
| 184 | (defvar protobuf-mode-map nil |
| 185 | "Keymap used in protobuf-mode buffers.") |
| 186 | (or protobuf-mode-map |
| 187 | (setq protobuf-mode-map (c-make-inherited-keymap))) |
| 188 | |
| 189 | (easy-menu-define protobuf-menu protobuf-mode-map |
| 190 | "Protocol Buffers Mode Commands" |
| 191 | (cons "Protocol Buffers" (c-lang-const c-mode-menu protobuf))) |
| 192 | |
| 193 | ;;;###autoload (add-to-list 'auto-mode-alist '("\\.proto\\'" . protobuf-mode)) |
| 194 | |
| 195 | ;;;###autoload |
| 196 | (defun protobuf-mode () |
| 197 | "Major mode for editing Protocol Buffers description language. |
| 198 | |
| 199 | The hook `c-mode-common-hook' is run with no argument at mode |
| 200 | initialization, then `protobuf-mode-hook'. |
| 201 | |
| 202 | Key bindings: |
| 203 | \\{protobuf-mode-map}" |
| 204 | (interactive) |
| 205 | (kill-all-local-variables) |
| 206 | (set-syntax-table protobuf-mode-syntax-table) |
| 207 | (setq major-mode 'protobuf-mode |
| 208 | mode-name "Protocol-Buffers" |
| 209 | local-abbrev-table protobuf-mode-abbrev-table |
| 210 | abbrev-mode t) |
| 211 | (use-local-map protobuf-mode-map) |
| 212 | (c-initialize-cc-mode t) |
kenton@google.com | f4c6e4b | 2009-09-15 17:12:06 +0000 | [diff] [blame] | 213 | (if (fboundp 'c-make-emacs-variables-local) |
| 214 | (c-make-emacs-variables-local)) |
kenton@google.com | 2cdba5b | 2009-05-01 21:03:20 +0000 | [diff] [blame] | 215 | (c-init-language-vars protobuf-mode) |
| 216 | (c-common-init 'protobuf-mode) |
| 217 | (easy-menu-add protobuf-menu) |
| 218 | (c-run-mode-hooks 'c-mode-common-hook 'protobuf-mode-hook) |
Yue Zhu | 582558a | 2020-06-11 11:37:02 -0400 | [diff] [blame] | 219 | (c-update-modeline) |
| 220 | (setq imenu-generic-expression |
| 221 | '(("Message" "^[[:space:]]*message[[:space:]]+\\([[:alnum:]]+\\)" 1) |
| 222 | ("Enum" "^[[:space:]]*enum[[:space:]]+\\([[:alnum:]]+\\)" 1) |
| 223 | ("Service" "^[[:space:]]*service[[:space:]]+\\([[:alnum:]]+\\)" 1)))) |
kenton@google.com | 2cdba5b | 2009-05-01 21:03:20 +0000 | [diff] [blame] | 224 | |
| 225 | (provide 'protobuf-mode) |
| 226 | |
| 227 | ;;; protobuf-mode.el ends here |