|
|
|
@ -0,0 +1,488 @@
@@ -0,0 +1,488 @@
|
|
|
|
|
;;; yaml-mode.el --- Major mode for editing YAML files |
|
|
|
|
|
|
|
|
|
;; Copyright (C) 2010-2014 Yoshiki Kurihara |
|
|
|
|
|
|
|
|
|
;; Author: Yoshiki Kurihara <clouder@gmail.com> |
|
|
|
|
;; Marshall T. Vandegrift <llasram@gmail.com> |
|
|
|
|
;; Maintainer: Vasilij Schneidermann <mail@vasilij.de> |
|
|
|
|
;; Package-Requires: ((emacs "24.1")) |
|
|
|
|
;; Package-Version: 20200725.1836 |
|
|
|
|
;; Package-Commit: 68fecb5f0dec712a10c8655df6881392a4613617 |
|
|
|
|
;; Keywords: data yaml |
|
|
|
|
;; Version: 0.0.14 |
|
|
|
|
|
|
|
|
|
;; This file is not part of Emacs |
|
|
|
|
|
|
|
|
|
;; This file is free software; you can redistribute it and/or modify |
|
|
|
|
;; it under the terms of the GNU General Public License as published by |
|
|
|
|
;; the Free Software Foundation; either version 2, or (at your option) |
|
|
|
|
;; any later version. |
|
|
|
|
|
|
|
|
|
;; This file is distributed in the hope that it will be useful, |
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
|
|
;; GNU General Public License for more details. |
|
|
|
|
|
|
|
|
|
;; You should have received a copy of the GNU General Public License along |
|
|
|
|
;; with this program; if not, write to the Free Software Foundation, Inc., |
|
|
|
|
;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|
|
|
|
|
|
|
|
|
;;; Commentary: |
|
|
|
|
|
|
|
|
|
;; This is a major mode for editing files in the YAML data |
|
|
|
|
;; serialization format. It was initially developed by Yoshiki |
|
|
|
|
;; Kurihara and many features were added by Marshall Vandegrift. As |
|
|
|
|
;; YAML and Python share the fact that indentation determines |
|
|
|
|
;; structure, this mode provides indentation and indentation command |
|
|
|
|
;; behavior very similar to that of python-mode. |
|
|
|
|
|
|
|
|
|
;;; Installation: |
|
|
|
|
|
|
|
|
|
;; To install, just drop this file into a directory in your |
|
|
|
|
;; `load-path' and (optionally) byte-compile it. To automatically |
|
|
|
|
;; handle files ending in '.yml', add something like: |
|
|
|
|
;; |
|
|
|
|
;; (require 'yaml-mode) |
|
|
|
|
;; (add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode)) |
|
|
|
|
;; |
|
|
|
|
;; to your .emacs file. |
|
|
|
|
;; |
|
|
|
|
;; Unlike python-mode, this mode follows the Emacs convention of not |
|
|
|
|
;; binding the ENTER key to `newline-and-indent'. To get this |
|
|
|
|
;; behavior, add the key definition to `yaml-mode-hook': |
|
|
|
|
;; |
|
|
|
|
;; (add-hook 'yaml-mode-hook |
|
|
|
|
;; '(lambda () |
|
|
|
|
;; (define-key yaml-mode-map "\C-m" 'newline-and-indent))) |
|
|
|
|
|
|
|
|
|
;;; Known Bugs: |
|
|
|
|
|
|
|
|
|
;; YAML is easy to write but complex to parse, and this mode doesn't |
|
|
|
|
;; even really try. Indentation and highlighting will break on |
|
|
|
|
;; abnormally complicated structures. |
|
|
|
|
|
|
|
|
|
;;; Code: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;; User definable variables |
|
|
|
|
|
|
|
|
|
;;;###autoload |
|
|
|
|
(defgroup yaml nil |
|
|
|
|
"Support for the YAML serialization format" |
|
|
|
|
:group 'languages |
|
|
|
|
:prefix "yaml-") |
|
|
|
|
|
|
|
|
|
(defcustom yaml-mode-hook nil |
|
|
|
|
"*Hook run by `yaml-mode'." |
|
|
|
|
:type 'hook |
|
|
|
|
:group 'yaml) |
|
|
|
|
|
|
|
|
|
(defcustom yaml-indent-offset 2 |
|
|
|
|
"*Amount of offset per level of indentation." |
|
|
|
|
:type 'integer |
|
|
|
|
:safe 'natnump |
|
|
|
|
:group 'yaml) |
|
|
|
|
|
|
|
|
|
(defcustom yaml-backspace-function 'backward-delete-char-untabify |
|
|
|
|
"*Function called by `yaml-electric-backspace' when deleting backwards. |
|
|
|
|
It will receive one argument, the numeric prefix value." |
|
|
|
|
:type 'function |
|
|
|
|
:group 'yaml) |
|
|
|
|
|
|
|
|
|
(defcustom yaml-block-literal-search-lines 100 |
|
|
|
|
"*Maximum number of lines to search for start of block literals." |
|
|
|
|
:type 'integer |
|
|
|
|
:group 'yaml) |
|
|
|
|
|
|
|
|
|
(defcustom yaml-block-literal-electric-alist |
|
|
|
|
'((?| . "") (?> . "-")) |
|
|
|
|
"*Characters for which to provide electric behavior. |
|
|
|
|
The association list key should be a key code and the associated value |
|
|
|
|
should be a string containing additional characters to insert when |
|
|
|
|
that key is pressed to begin a block literal." |
|
|
|
|
:type 'alist |
|
|
|
|
:group 'yaml) |
|
|
|
|
|
|
|
|
|
(defface yaml-tab-face |
|
|
|
|
'((((class color)) (:background "red" :foreground "red" :bold t)) |
|
|
|
|
(t (:reverse-video t))) |
|
|
|
|
"Face to use for highlighting tabs in YAML files." |
|
|
|
|
:group 'faces |
|
|
|
|
:group 'yaml) |
|
|
|
|
|
|
|
|
|
(defcustom yaml-imenu-generic-expression |
|
|
|
|
'((nil "^\\(:?[a-zA-Z_-]+\\):" 1)) |
|
|
|
|
"The imenu regex to parse an outline of the yaml file." |
|
|
|
|
:type 'string |
|
|
|
|
:group 'yaml) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;; Constants |
|
|
|
|
|
|
|
|
|
(defconst yaml-mode-version "0.0.14" "Version of `yaml-mode'.") |
|
|
|
|
|
|
|
|
|
(defconst yaml-blank-line-re "^ *$" |
|
|
|
|
"Regexp matching a line containing only (valid) whitespace.") |
|
|
|
|
|
|
|
|
|
(defconst yaml-directive-re "^\\(?:--- \\)? *%\\(\\w+\\)" |
|
|
|
|
"Regexp matching a line contatining a YAML directive.") |
|
|
|
|
|
|
|
|
|
(defconst yaml-document-delimiter-re "^\\(?:---\\|[.][.][.]\\)" |
|
|
|
|
"Rexexp matching a YAML document delimiter line.") |
|
|
|
|
|
|
|
|
|
(defconst yaml-node-anchor-alias-re "[&*][a-zA-Z0-9_-]+" |
|
|
|
|
"Regexp matching a YAML node anchor or alias.") |
|
|
|
|
|
|
|
|
|
(defconst yaml-tag-re "!!?[^ \n]+" |
|
|
|
|
"Rexexp matching a YAML tag.") |
|
|
|
|
|
|
|
|
|
(defconst yaml-bare-scalar-re |
|
|
|
|
"\\(?:[^-:,#!\n{\\[ ]\\|[^#!\n{\\[ ]\\S-\\)[^#\n]*?" |
|
|
|
|
"Rexexp matching a YAML bare scalar.") |
|
|
|
|
|
|
|
|
|
(defconst yaml-hash-key-re |
|
|
|
|
(concat "\\(?:^\\(?:--- \\)?\\|{\\|\\(?:[-,] +\\)+\\) *" |
|
|
|
|
"\\(?:" yaml-tag-re " +\\)?" |
|
|
|
|
"\\(" yaml-bare-scalar-re "\\) *:" |
|
|
|
|
"\\(?: +\\|$\\)") |
|
|
|
|
"Regexp matching a single YAML hash key.") |
|
|
|
|
|
|
|
|
|
(defconst yaml-scalar-context-re |
|
|
|
|
(concat "\\(?:^\\(?:--- \\)?\\|{\\|\\(?: *[-,] +\\)+\\) *" |
|
|
|
|
"\\(?:" yaml-bare-scalar-re " *: \\)?") |
|
|
|
|
"Regexp indicating the beginning of a scalar context.") |
|
|
|
|
|
|
|
|
|
(defconst yaml-nested-map-re |
|
|
|
|
(concat "[^#\n]*: *\\(?:&.*\\|{ *\\|" yaml-tag-re " *\\)?$") |
|
|
|
|
"Regexp matching a line beginning a YAML nested structure.") |
|
|
|
|
|
|
|
|
|
(defconst yaml-block-literal-base-re " *[>|][-+0-9]* *\\(?:\n\\|\\'\\)" |
|
|
|
|
"Regexp matching the substring start of a block literal.") |
|
|
|
|
|
|
|
|
|
(defconst yaml-block-literal-re |
|
|
|
|
(concat yaml-scalar-context-re |
|
|
|
|
"\\(?:" yaml-tag-re "\\)?" |
|
|
|
|
yaml-block-literal-base-re) |
|
|
|
|
"Regexp matching a line beginning a YAML block literal.") |
|
|
|
|
|
|
|
|
|
(defconst yaml-nested-sequence-re |
|
|
|
|
(concat "^\\(?:\\(?: *- +\\)+\\|\\(:? *-$\\)\\)" |
|
|
|
|
"\\(?:" yaml-bare-scalar-re " *:\\(?: +.*\\)?\\)?$") |
|
|
|
|
"Regexp matching a line containing one or more nested YAML sequences.") |
|
|
|
|
|
|
|
|
|
(defconst yaml-constant-scalars-re |
|
|
|
|
(concat "\\(?:^\\|\\(?::\\|-\\|,\\|{\\|\\[\\) +\\) *" |
|
|
|
|
(regexp-opt |
|
|
|
|
'("~" "null" "Null" "NULL" |
|
|
|
|
".nan" ".NaN" ".NAN" |
|
|
|
|
".inf" ".Inf" ".INF" |
|
|
|
|
"-.inf" "-.Inf" "-.INF" |
|
|
|
|
"y" "Y" "yes" "Yes" "YES" "n" "N" "no" "No" "NO" |
|
|
|
|
"true" "True" "TRUE" "false" "False" "FALSE" |
|
|
|
|
"on" "On" "ON" "off" "Off" "OFF") t) |
|
|
|
|
" *$") |
|
|
|
|
"Regexp matching certain scalar constants in scalar context.") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;; Mode setup |
|
|
|
|
|
|
|
|
|
(defvar yaml-mode-map |
|
|
|
|
(let ((map (make-sparse-keymap))) |
|
|
|
|
(define-key map "|" 'yaml-electric-bar-and-angle) |
|
|
|
|
(define-key map ">" 'yaml-electric-bar-and-angle) |
|
|
|
|
(define-key map "-" 'yaml-electric-dash-and-dot) |
|
|
|
|
(define-key map "." 'yaml-electric-dash-and-dot) |
|
|
|
|
(define-key map (kbd "DEL") 'yaml-electric-backspace) |
|
|
|
|
map) |
|
|
|
|
"Keymap used in `yaml-mode' buffers.") |
|
|
|
|
|
|
|
|
|
(defvar yaml-mode-syntax-table |
|
|
|
|
(let ((syntax-table (make-syntax-table))) |
|
|
|
|
(modify-syntax-entry ?\' "\"" syntax-table) |
|
|
|
|
(modify-syntax-entry ?\" "\"" syntax-table) |
|
|
|
|
(modify-syntax-entry ?# "<" syntax-table) |
|
|
|
|
(modify-syntax-entry ?\n ">" syntax-table) |
|
|
|
|
(modify-syntax-entry ?\\ "\\" syntax-table) |
|
|
|
|
(modify-syntax-entry ?- "_" syntax-table) |
|
|
|
|
(modify-syntax-entry ?_ "_" syntax-table) |
|
|
|
|
(modify-syntax-entry ?& "." syntax-table) |
|
|
|
|
(modify-syntax-entry ?* "." syntax-table) |
|
|
|
|
(modify-syntax-entry ?\( "." syntax-table) |
|
|
|
|
(modify-syntax-entry ?\) "." syntax-table) |
|
|
|
|
(modify-syntax-entry ?\{ "(}" syntax-table) |
|
|
|
|
(modify-syntax-entry ?\} "){" syntax-table) |
|
|
|
|
(modify-syntax-entry ?\[ "(]" syntax-table) |
|
|
|
|
(modify-syntax-entry ?\] ")[" syntax-table) |
|
|
|
|
syntax-table) |
|
|
|
|
"Syntax table in use in `yaml-mode' buffers.") |
|
|
|
|
|
|
|
|
|
;;;###autoload |
|
|
|
|
(define-derived-mode yaml-mode text-mode "YAML" |
|
|
|
|
"Simple mode to edit YAML. |
|
|
|
|
|
|
|
|
|
\\{yaml-mode-map}" |
|
|
|
|
:syntax-table yaml-mode-syntax-table |
|
|
|
|
(set (make-local-variable 'comment-start) "# ") |
|
|
|
|
(set (make-local-variable 'comment-start-skip) "#+ *") |
|
|
|
|
(set (make-local-variable 'indent-line-function) 'yaml-indent-line) |
|
|
|
|
(set (make-local-variable 'indent-tabs-mode) nil) |
|
|
|
|
(set (make-local-variable 'fill-paragraph-function) 'yaml-fill-paragraph) |
|
|
|
|
|
|
|
|
|
(set (make-local-variable 'syntax-propertize-function) |
|
|
|
|
'yaml-mode-syntax-propertize-function) |
|
|
|
|
(setq font-lock-defaults '(yaml-font-lock-keywords))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;; Font-lock support |
|
|
|
|
|
|
|
|
|
(defvar yaml-font-lock-keywords |
|
|
|
|
`((yaml-font-lock-block-literals 0 font-lock-string-face) |
|
|
|
|
(,yaml-constant-scalars-re . (1 font-lock-constant-face)) |
|
|
|
|
(,yaml-tag-re . (0 font-lock-type-face)) |
|
|
|
|
(,yaml-node-anchor-alias-re . (0 font-lock-function-name-face)) |
|
|
|
|
(,yaml-hash-key-re . (1 font-lock-variable-name-face)) |
|
|
|
|
(,yaml-document-delimiter-re . (0 font-lock-comment-face)) |
|
|
|
|
(,yaml-directive-re . (1 font-lock-builtin-face)) |
|
|
|
|
("^[\t]+" 0 'yaml-tab-face t)) |
|
|
|
|
"Additional expressions to highlight in YAML mode.") |
|
|
|
|
|
|
|
|
|
(defun yaml-mode-syntax-propertize-function (beg end) |
|
|
|
|
"Override buffer's syntax table for special syntactic constructs." |
|
|
|
|
;; Unhighlight foo#bar tokens between BEG and END. |
|
|
|
|
(save-excursion |
|
|
|
|
(goto-char beg) |
|
|
|
|
(while (search-forward "#" end t) |
|
|
|
|
(save-excursion |
|
|
|
|
(forward-char -1) |
|
|
|
|
;; both ^# and [ \t]# are comments |
|
|
|
|
(when (and (not (bolp)) |
|
|
|
|
(not (memq (preceding-char) '(?\s ?\t)))) |
|
|
|
|
(put-text-property (point) (1+ (point)) |
|
|
|
|
'syntax-table (string-to-syntax "_")))))) |
|
|
|
|
|
|
|
|
|
(save-excursion |
|
|
|
|
(goto-char beg) |
|
|
|
|
(while (and |
|
|
|
|
(> end (point)) |
|
|
|
|
(re-search-forward "['\"]" end t)) |
|
|
|
|
(when (get-text-property (point) 'yaml-block-literal) |
|
|
|
|
(put-text-property (1- (point)) (point) |
|
|
|
|
'syntax-table (string-to-syntax "w"))) |
|
|
|
|
(let* ((pt (point)) |
|
|
|
|
(sps (save-excursion (syntax-ppss (1- pt))))) |
|
|
|
|
(when (not (nth 8 sps)) |
|
|
|
|
(cond |
|
|
|
|
((and (char-equal ?' (char-before (1- pt))) |
|
|
|
|
(char-equal ?' (char-before pt))) |
|
|
|
|
(put-text-property (- pt 2) pt |
|
|
|
|
'syntax-table (string-to-syntax "w")) |
|
|
|
|
;; Workaround for https://debbugs.gnu.org/41195. |
|
|
|
|
(let ((syntax-propertize--done syntax-propertize--done)) |
|
|
|
|
;; Carefully invalidate the last cached ppss. |
|
|
|
|
(syntax-ppss-flush-cache (- pt 2)))) |
|
|
|
|
;; If quote is detected as a syntactic string start but appeared |
|
|
|
|
;; after a non-whitespace character, then mark it as syntactic word. |
|
|
|
|
((and (char-before (1- pt)) |
|
|
|
|
(char-equal ?w (char-syntax (char-before (1- pt))))) |
|
|
|
|
(put-text-property (1- pt) pt |
|
|
|
|
'syntax-table (string-to-syntax "w"))) |
|
|
|
|
(t |
|
|
|
|
;; We're right after a quote that opens a string literal. |
|
|
|
|
;; Skip over it (big speedup for long JSON strings). |
|
|
|
|
(goto-char (1- pt)) |
|
|
|
|
(condition-case nil |
|
|
|
|
(forward-sexp) |
|
|
|
|
(scan-error |
|
|
|
|
(goto-char end)))))))))) |
|
|
|
|
|
|
|
|
|
(defun yaml-font-lock-block-literals (bound) |
|
|
|
|
"Find lines within block literals. |
|
|
|
|
Find the next line of the first (if any) block literal after point and |
|
|
|
|
prior to BOUND. Returns the beginning and end of the block literal |
|
|
|
|
line in the match data, as consumed by `font-lock-keywords' matcher |
|
|
|
|
functions. The function begins by searching backwards to determine |
|
|
|
|
whether or not the current line is within a block literal. This could |
|
|
|
|
be time-consuming in large buffers, so the number of lines searched is |
|
|
|
|
artificially limited to the value of |
|
|
|
|
`yaml-block-literal-search-lines'." |
|
|
|
|
(if (eolp) (goto-char (1+ (point)))) |
|
|
|
|
(unless (or (eobp) (>= (point) bound)) |
|
|
|
|
(let ((begin (point)) |
|
|
|
|
(end (min (1+ (point-at-eol)) bound))) |
|
|
|
|
(goto-char (point-at-bol)) |
|
|
|
|
(while (and (looking-at yaml-blank-line-re) |
|
|
|
|
(not (bobp))) |
|
|
|
|
(forward-line -1)) |
|
|
|
|
(let ((nlines yaml-block-literal-search-lines) |
|
|
|
|
(min-level (current-indentation))) |
|
|
|
|
(forward-line -1) |
|
|
|
|
(while (and (/= nlines 0) |
|
|
|
|
(/= min-level 0) |
|
|
|
|
(not (looking-at yaml-block-literal-re)) |
|
|
|
|
(not (bobp))) |
|
|
|
|
(setq nlines (1- nlines)) |
|
|
|
|
(unless (looking-at yaml-blank-line-re) |
|
|
|
|
(setq min-level (min min-level (current-indentation)))) |
|
|
|
|
(forward-line -1)) |
|
|
|
|
(cond |
|
|
|
|
((and (< (current-indentation) min-level) |
|
|
|
|
(looking-at yaml-block-literal-re)) |
|
|
|
|
(goto-char end) |
|
|
|
|
(put-text-property begin end 'yaml-block-literal t) |
|
|
|
|
(set-match-data (list begin end)) |
|
|
|
|
t) |
|
|
|
|
((progn |
|
|
|
|
(goto-char begin) |
|
|
|
|
(re-search-forward (concat yaml-block-literal-re |
|
|
|
|
" *\\(.*\\)\n") |
|
|
|
|
bound t)) |
|
|
|
|
(let ((range (nthcdr 2 (match-data)))) |
|
|
|
|
(put-text-property (car range) (cadr range) 'yaml-block-literal t) |
|
|
|
|
(set-match-data range)) |
|
|
|
|
t)))))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;; Indentation and electric keys |
|
|
|
|
|
|
|
|
|
(defun yaml-compute-indentation () |
|
|
|
|
"Calculate the maximum sensible indentation for the current line." |
|
|
|
|
(save-excursion |
|
|
|
|
(beginning-of-line) |
|
|
|
|
(if (looking-at yaml-document-delimiter-re) 0 |
|
|
|
|
(forward-line -1) |
|
|
|
|
(while (and (looking-at yaml-blank-line-re) |
|
|
|
|
(> (point) (point-min))) |
|
|
|
|
(forward-line -1)) |
|
|
|
|
(+ (current-indentation) |
|
|
|
|
(if (looking-at yaml-nested-map-re) yaml-indent-offset 0) |
|
|
|
|
(if (looking-at yaml-nested-sequence-re) yaml-indent-offset 0) |
|
|
|
|
(if (looking-at yaml-block-literal-re) yaml-indent-offset 0))))) |
|
|
|
|
|
|
|
|
|
(defun yaml-indent-line () |
|
|
|
|
"Indent the current line. |
|
|
|
|
The first time this command is used, the line will be indented to the |
|
|
|
|
maximum sensible indentation. Each immediately subsequent usage will |
|
|
|
|
back-dent the line by `yaml-indent-offset' spaces. On reaching column |
|
|
|
|
0, it will cycle back to the maximum sensible indentation." |
|
|
|
|
(interactive "*") |
|
|
|
|
(let ((ci (current-indentation)) |
|
|
|
|
(cc (current-column)) |
|
|
|
|
(need (yaml-compute-indentation))) |
|
|
|
|
(save-excursion |
|
|
|
|
(beginning-of-line) |
|
|
|
|
(delete-horizontal-space) |
|
|
|
|
(if (and (equal last-command this-command) (/= ci 0)) |
|
|
|
|
(indent-to (* (/ (- ci 1) yaml-indent-offset) yaml-indent-offset)) |
|
|
|
|
(indent-to need))) |
|
|
|
|
(if (< (current-column) (current-indentation)) |
|
|
|
|
(forward-to-indentation 0)))) |
|
|
|
|
|
|
|
|
|
(defun yaml-electric-backspace (arg) |
|
|
|
|
"Delete characters or back-dent the current line. |
|
|
|
|
If invoked following only whitespace on a line, will back-dent to the |
|
|
|
|
immediately previous multiple of `yaml-indent-offset' spaces." |
|
|
|
|
(interactive "*p") |
|
|
|
|
(if (or (/= (current-indentation) (current-column)) (bolp)) |
|
|
|
|
(funcall yaml-backspace-function arg) |
|
|
|
|
(let ((ci (current-column))) |
|
|
|
|
(beginning-of-line) |
|
|
|
|
(delete-horizontal-space) |
|
|
|
|
(indent-to (* (/ (- ci (* arg yaml-indent-offset)) |
|
|
|
|
yaml-indent-offset) |
|
|
|
|
yaml-indent-offset))))) |
|
|
|
|
|
|
|
|
|
(defun yaml-electric-bar-and-angle (arg) |
|
|
|
|
"Insert the bound key and possibly begin a block literal. |
|
|
|
|
Inserts the bound key. If inserting the bound key causes the current |
|
|
|
|
line to match the initial line of a block literal, then inserts the |
|
|
|
|
matching string from `yaml-block-literal-electric-alist', a newline, |
|
|
|
|
and indents appropriately." |
|
|
|
|
(interactive "*P") |
|
|
|
|
(self-insert-command (prefix-numeric-value arg)) |
|
|
|
|
(let ((extra-chars |
|
|
|
|
(assoc last-command-event |
|
|
|
|
yaml-block-literal-electric-alist))) |
|
|
|
|
(cond |
|
|
|
|
((and extra-chars (not arg) (eolp) |
|
|
|
|
(save-excursion |
|
|
|
|
(beginning-of-line) |
|
|
|
|
(looking-at yaml-block-literal-re))) |
|
|
|
|
(insert (cdr extra-chars)) |
|
|
|
|
(newline-and-indent))))) |
|
|
|
|
|
|
|
|
|
(defun yaml-electric-dash-and-dot (arg) |
|
|
|
|
"Insert the bound key and possibly de-dent line. |
|
|
|
|
Inserts the bound key. If inserting the bound key causes the current |
|
|
|
|
line to match a document delimiter, de-dent the line to the left |
|
|
|
|
margin." |
|
|
|
|
(interactive "*P") |
|
|
|
|
(self-insert-command (prefix-numeric-value arg)) |
|
|
|
|
(save-excursion |
|
|
|
|
(beginning-of-line) |
|
|
|
|
(when (and (not arg) (looking-at yaml-document-delimiter-re)) |
|
|
|
|
(delete-horizontal-space)))) |
|
|
|
|
|
|
|
|
|
(defun yaml-narrow-to-block-literal () |
|
|
|
|
"Narrow the buffer to block literal if the point is in it, |
|
|
|
|
otherwise do nothing." |
|
|
|
|
(interactive) |
|
|
|
|
(save-excursion |
|
|
|
|
(goto-char (point-at-bol)) |
|
|
|
|
(while (and (looking-at-p yaml-blank-line-re) (not (bobp))) |
|
|
|
|
(forward-line -1)) |
|
|
|
|
(let ((nlines yaml-block-literal-search-lines) |
|
|
|
|
(min-level (current-indentation)) |
|
|
|
|
beg) |
|
|
|
|
(forward-line -1) |
|
|
|
|
(while (and (/= nlines 0) |
|
|
|
|
(/= min-level 0) |
|
|
|
|
(not (looking-at-p yaml-block-literal-re)) |
|
|
|
|
(not (bobp))) |
|
|
|
|
(setq nlines (1- nlines)) |
|
|
|
|
(unless (looking-at-p yaml-blank-line-re) |
|
|
|
|
(setq min-level (min min-level (current-indentation)))) |
|
|
|
|
(forward-line -1)) |
|
|
|
|
(when (and (< (current-indentation) min-level) |
|
|
|
|
(looking-at-p yaml-block-literal-re)) |
|
|
|
|
(setq min-level (current-indentation)) |
|
|
|
|
(forward-line) |
|
|
|
|
(setq beg (point)) |
|
|
|
|
(while (and (not (eobp)) |
|
|
|
|
(or (looking-at-p yaml-blank-line-re) |
|
|
|
|
(> (current-indentation) min-level))) |
|
|
|
|
(forward-line)) |
|
|
|
|
(narrow-to-region beg (point)))))) |
|
|
|
|
|
|
|
|
|
(defun yaml-fill-paragraph (&optional justify region) |
|
|
|
|
"Fill paragraph. |
|
|
|
|
Outside of comments, this behaves as `fill-paragraph' except that |
|
|
|
|
filling does not cross boundaries of block literals. Inside comments, |
|
|
|
|
this will do usual adaptive fill behaviors." |
|
|
|
|
(interactive "*P") |
|
|
|
|
(save-restriction |
|
|
|
|
(yaml-narrow-to-block-literal) |
|
|
|
|
(let ((fill-paragraph-function nil)) |
|
|
|
|
(or (fill-comment-paragraph justify) |
|
|
|
|
(fill-paragraph justify region))))) |
|
|
|
|
|
|
|
|
|
(defun yaml-set-imenu-generic-expression () |
|
|
|
|
(make-local-variable 'imenu-generic-expression) |
|
|
|
|
(make-local-variable 'imenu-create-index-function) |
|
|
|
|
(setq imenu-create-index-function 'imenu-default-create-index-function) |
|
|
|
|
(setq imenu-generic-expression yaml-imenu-generic-expression)) |
|
|
|
|
|
|
|
|
|
(add-hook 'yaml-mode-hook 'yaml-set-imenu-generic-expression) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(defun yaml-mode-version () |
|
|
|
|
"Display version of `yaml-mode'." |
|
|
|
|
(interactive) |
|
|
|
|
(message "yaml-mode %s" yaml-mode-version) |
|
|
|
|
yaml-mode-version) |
|
|
|
|
|
|
|
|
|
;;;###autoload |
|
|
|
|
(add-to-list 'auto-mode-alist '("\\.\\(e?ya?\\|ra\\)ml\\'" . yaml-mode)) |
|
|
|
|
|
|
|
|
|
(provide 'yaml-mode) |
|
|
|
|
|
|
|
|
|
;;; yaml-mode.el ends here |