1 ;;; yang-mode.el --- major mode for editing YANG files
3 ;; This program is free software; you can redistribute it and/or modify
4 ;; it under the terms of the GNU General Public License as published by
5 ;; the Free Software Foundation; either version 2 of the License, or
6 ;; (at your option) any later version.
8 ;; This program is distributed in the hope that it will be useful,
9 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 ;; GNU General Public License for more details.
13 ;; You should have received a copy of the GNU General Public License
14 ;; along with this program; see the file COPYING. If not, write to
15 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 ;; Boston, MA 02111-1307, USA.
18 ;; Author: Martin Bjorklund <mbj4668@gmail.com>
23 ;; Note: The interface used in this file requires CC Mode 5.30 or
28 ;; one more autoload fix
30 ;; autoload fix, tested with use-package
34 ;; derive from prog-mode if available, otherwise nil
35 ;; use proper syntax-table
39 ;; derive mode from prog-mode in order to get correct hook behavior
41 ;; use define-derived-mode
42 ;; yang-fill-paragraph now works in Emacs 23
44 ;; workaround Emacs bug #18845 (for 24.4+)
47 ;; added yang-fill-paragraph for better string fill
49 ;; draft-ietf-netmod-rfc6020bis-11 compliant
50 ;; added support for new 1.1 keywords
52 ;; removed unused defcustom yang-font-lock-extra-types
53 ;; made emacs24 to give a warning
56 ;; classify all keywords as decl-start gives better indentation
58 ;; draft-ietf-netmod-yang-12 compliant,
59 ;; added instructions for Emacs 23
61 ;; draft-ietf-netmod-yang-09 compliant,
63 ;; draft-ietf-netmod-yang-02 compliant.
65 ;; Initial version, draft-bjorklund-netconf-yang-00 compliant.
69 ;; If you're using use-package, put this in your .emacs:
70 ;; (use-package yang-mode
73 ;; Otherwise, put this in your .emacs:
74 ;; (require 'yang-mode)
76 ;; For use with Emacs 23, put this in your .emacs:
77 ;; (autoload 'yang-mode "yang-mode" "Major mode for editing YANG modules."
79 ;; (add-to-list 'auto-mode-alist '("\\.yang$" . yang-mode))
81 ;; Some users have reported other errors with Emacs 23, and have found
82 ;; that removing the byte-compiled cc-mode.elc file fixes these problems.
83 ;; (e.g. /usr/share/emacs/23.1/lisp/progmodes/cc-mode.elc)
86 ;; For editing somewhat larger YANG modules, add this to your .emacs
87 ;; (setq blink-matching-paren-distance nil)
89 ;; Common YANG layout:
90 ;; (defun my-yang-mode-hook ()
91 ;; "Configuration for YANG Mode. Add this to `yang-mode-hook'."
94 ;; (c-set-style "BSD")
95 ;; (setq indent-tabs-mode nil)
96 ;; (setq c-basic-offset 2)
97 ;; (setq font-lock-maximum-decoration t)
98 ;; (font-lock-mode t))))
100 ;; (add-hook 'yang-mode-hook 'my-yang-mode-hook)
102 ;; Using the oultine minor mode for YANG is very useful to get a
103 ;; good overview of the structure of a module.
105 ;; Put this in your .emacs:
107 ;; (defun show-onelevel ()
108 ;; "show entry and children in outline mode"
113 ;; (defun my-outline-bindings ()
114 ;; "sets shortcut bindings for outline minor mode"
116 ;; (local-set-key [?\C-,] 'hide-body)
117 ;; (local-set-key [?\C-.] 'show-all)
118 ;; (local-set-key [C-up] 'outline-previous-visible-heading)
119 ;; (local-set-key [C-down] 'outline-next-visible-heading)
120 ;; (local-set-key [C-left] 'hide-subtree)
121 ;; (local-set-key [C-right] 'show-onelevel)
122 ;; (local-set-key [M-up] 'outline-backward-same-level)
123 ;; (local-set-key [M-down] 'outline-forward-same-level)
124 ;; (local-set-key [M-left] 'hide-subtree)
125 ;; (local-set-key [M-right] 'show-subtree))
128 ;; 'outline-minor-mode-hook
129 ;; 'my-outline-bindings)
131 ;; (defconst sort-of-yang-identifier-regexp "[-a-zA-Z0-9_\\.:]*")
136 ;; (outline-minor-mode)
137 ;; (setq outline-regexp
138 ;; (concat "^ *" sort-of-yang-identifier-regexp " *"
139 ;; sort-of-yang-identifier-regexp
146 ;; These are only required at compile time to get the sources for the
147 ;; language constants. (The cc-fonts require and the font-lock
148 ;; related constants could additionally be put inside an
149 ;; (eval-after-load "font-lock" ...) but then some trickery is
150 ;; necessary to get them compiled.)
156 ;; Make our mode known to the language constant system. Use Java
157 ;; mode as the fallback for the constants we don't change here.
158 ;; This needs to be done also at compile time since the language
159 ;; constants are evaluated then.
160 (c-add-language 'yang-mode 'java-mode))
162 ;; Work around Emacs bug #18845, cc-mode expects cl to be loaded
164 (if (and (= emacs-major-version 24) (>= emacs-minor-version 4))
167 ;; YANG has no primitive types in the C/Java sense.
168 (c-lang-defconst c-primitive-type-kwds
171 (c-lang-defconst c-modifier-kwds
174 (c-lang-defconst c-label-kwds
177 (c-lang-defconst c-before-label-kwds
180 (c-lang-defconst c-class-decl-kwds
183 (c-lang-defconst c-decl-start-kwds
255 ;; No cpp in this language. (The definitions for the extra keywords
256 ;; above are enough to incorporate them into the fontification regexps
257 ;; for types and keywords, so no additional font-lock patterns are
259 (c-lang-defconst c-cpp-matchers
261 ;; There are some other things in `c-cpp-matchers' besides the
262 ;; preprocessor support, so include it.
263 (c-lang-const c-cpp-matchers))
265 ;; '-' is part of an identifier in YANG
266 ;; FIXME: how do I make '.' part of the identifier?
267 (c-lang-defconst c-identifier-syntax-modifications
268 yang (append '((?- . "w") (?: . "w"))
269 (c-lang-const c-identifier-syntax-modifications)))
271 (c-lang-defconst c-symbol-chars
272 yang (concat c-alnum ":_-"))
274 ;; YANG does not have labels
275 (c-lang-defconst c-recognize-colon-labels
278 (defconst yang-font-lock-keywords-1 (c-lang-const c-matchers-1 yang)
279 "Minimal highlighting for YANG mode.")
281 (defconst yang-font-lock-keywords-2 (c-lang-const c-matchers-2 yang)
282 "Fast normal highlighting for YANG mode.")
284 (defconst yang-font-lock-keywords-3 (c-lang-const c-matchers-3 yang)
285 "Accurate normal highlighting for YANG mode.")
287 (defvar yang-font-lock-keywords yang-font-lock-keywords-3
288 "Default expressions to highlight in YANG mode.")
290 (defvar yang-mode-syntax-table nil
291 "Syntax table used in `yang-mode' buffers.")
292 (or yang-mode-syntax-table
293 (setq yang-mode-syntax-table
294 (funcall (c-lang-const c-make-mode-syntax-table yang))))
296 (defvar yang-mode-map (let ((map (c-make-inherited-keymap)))
297 ;; Add bindings which are only useful for YANG
299 "Keymap used in `yang-mode' buffers.")
301 (easy-menu-define yang-menu yang-mode-map "YANG Mode Commands"
302 ;; Can use `yang' as the language for `c-mode-menu'
303 ;; since its definition covers any language. In
304 ;; this case the language is used to adapt to the
305 ;; nonexistence of a cpp pass and thus removing some
306 ;; irrelevant menu alternatives.
307 (cons "YANG" (c-lang-const c-mode-menu yang)))
309 (defun yang-fill-paragraph (&optional arg)
310 "Like \\[c-fill-paragraph] but handles first line in strings properly.
312 Optional prefix ARG means justify paragraph as well."
313 ;; c-fill-paragraph narrows the region to the contents of a string
314 ;; before filling, and this means that the start quote character
315 ;; will be in column 1 in the narrowed region. Thus the first line
316 ;; line will not be filled properly.
317 ;; This function handles this by temporarily inserting a newline
318 ;; followed by whitespaces to line up the first line before filling.
321 (let ((limits (c-literal-limits))
324 (if (eq (c-literal-type limits) 'string)
325 (let ((curpoint (point)))
327 (if (< (point) (car limits))
328 ;; do this in the first paragraph of a string
329 (let ((first-char (+ 1 (car limits))))
330 (goto-char first-char)
332 (setq col (- first-char (point)))
333 (goto-char first-char)
334 (setq tmppoint (point))
336 (insert-char ?\s col))
337 (goto-char curpoint))))
338 (c-fill-paragraph arg)
342 (delete-char (+ 1 col))))))
343 ;; Always return t. This has the effect that if filling isn't done
344 ;; above, it isn't done at all, and it's therefore effectively
345 ;; disabled in normal code.
348 ;; It doesn't suffice to put `yang-fill-paragraph' on
349 ;; `fill-paragraph-function' since `yang-fill-paragraph' must be called
350 ;; before any fill prefix adaption is done.
351 (substitute-key-definition 'c-fill-paragraph 'yang-fill-paragraph
352 yang-mode-map c-mode-map)
354 ;; derive from prog-mode if it is defined
355 (if (fboundp 'prog-mode)
356 (defmacro yang-define-derived-mode (mode &rest args)
357 `(define-derived-mode ,mode prog-mode ,@args))
358 (defmacro yang-define-derived-mode (mode &rest args)
359 `(define-derived-mode ,mode nil ,@args)))
361 ;;;###autoload(autoload 'yang-mode "yang-mode" "" t nil)
362 (yang-define-derived-mode yang-mode "YANG"
363 "Major mode for editing YANG modules.
365 The hook `c-mode-common-hook' is run with no args at mode
366 initialization, then `yang-mode-hook'.
370 :syntax-table yang-mode-syntax-table
371 (c-initialize-cc-mode t)
372 (c-init-language-vars yang-mode)
373 (c-common-init 'yang-mode)
375 ;; Allow auto-fill in strings
376 (setq c-ignore-auto-fill '(cpp code))
378 ;; Install `yang-fill-paragraph' on `fill-paragraph-function' so
379 ;; that a direct call to `fill-paragraph' behaves better.
380 (make-local-variable fill-paragraph-function)
381 (setq fill-paragraph-function 'yang-fill-paragraph)
382 ;; we derive from prog-mode/nil rather than c-mode in order to not run
383 ;; c-mode-hooks; this means that we need to run c-mode-common-hook
385 (c-run-mode-hooks 'c-mode-common-hook))
388 (add-to-list 'auto-mode-alist '("\\.yang\\'" . yang-mode))
392 ;;; yang-mode.el ends here