|
|
- ;;; company-nxml.el --- company-mode completion backend for nxml-mode
-
- ;; Copyright (C) 2009-2011, 2013, 2018 Free Software Foundation, Inc.
-
- ;; Author: Nikolaj Schumacher
-
- ;; This file is part of GNU Emacs.
-
- ;; GNU Emacs 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 3 of the License, or
- ;; (at your option) any later version.
-
- ;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
-
-
- ;;; Commentary:
- ;;
- ;; In Emacs >= 26, company-capf is used instead.
-
- ;;; Code:
-
- (require 'company)
- (require 'cl-lib)
-
- (defvar rng-open-elements)
- (defvar rng-validate-mode)
- (defvar rng-in-attribute-regex)
- (defvar rng-in-attribute-value-regex)
- (declare-function rng-set-state-after "rng-nxml")
- (declare-function rng-match-possible-start-tag-names "rng-match")
- (declare-function rng-adjust-state-for-attribute "rng-nxml")
- (declare-function rng-match-possible-attribute-names "rng-match")
- (declare-function rng-adjust-state-for-attribute-value "rng-nxml")
- (declare-function rng-match-possible-value-strings "rng-match")
-
- (defconst company-nxml-token-regexp
- "\\(?:[_[:alpha:]][-._[:alnum:]]*\\_>\\)")
-
- (defvar company-nxml-in-attribute-value-regexp
- (replace-regexp-in-string "w" company-nxml-token-regexp
- "<w\\(?::w\\)?\
- \\(?:[ \t\r\n]+w\\(?::w\\)?[ \t\r\n]*=\
- \[ \t\r\n]*\\(?:\"[^\"]*\"\\|'[^']*'\\)\\)*\
- \[ \t\r\n]+\\(w\\(:w\\)?\\)[ \t\r\n]*=[ \t\r\n]*\
- \\(\"\\([^\"]*\\>\\)\\|'\\([^']*\\>\\)\\)\\="
- t t))
-
- (defvar company-nxml-in-tag-name-regexp
- (replace-regexp-in-string "w" company-nxml-token-regexp
- "<\\(/?w\\(?::w?\\)?\\)?\\=" t t))
-
- (defun company-nxml-all-completions (prefix alist)
- (let ((candidates (mapcar 'cdr alist))
- (case-fold-search nil)
- filtered)
- (when (cdar rng-open-elements)
- (push (concat "/" (cdar rng-open-elements)) candidates))
- (setq candidates (sort (all-completions prefix candidates) 'string<))
- (while candidates
- (unless (equal (car candidates) (car filtered))
- (push (car candidates) filtered))
- (pop candidates))
- (nreverse filtered)))
-
- (defmacro company-nxml-prepared (&rest body)
- (declare (indent 0) (debug t))
- `(let ((lt-pos (save-excursion (search-backward "<" nil t)))
- xmltok-dtd)
- (when (and lt-pos (= (rng-set-state-after lt-pos) lt-pos))
- ,@body)))
-
- (defun company-nxml-tag (command &optional arg &rest ignored)
- (cl-case command
- (prefix (and (derived-mode-p 'nxml-mode)
- rng-validate-mode
- (company-grab company-nxml-in-tag-name-regexp 1)))
- (candidates (company-nxml-prepared
- (company-nxml-all-completions
- arg (rng-match-possible-start-tag-names))))
- (sorted t)))
-
- (defun company-nxml-attribute (command &optional arg &rest ignored)
- (cl-case command
- (prefix (and (derived-mode-p 'nxml-mode)
- rng-validate-mode
- (memq (char-after) '(?\ ?\t ?\n)) ;; outside word
- (company-grab rng-in-attribute-regex 1)))
- (candidates (company-nxml-prepared
- (and (rng-adjust-state-for-attribute
- lt-pos (- (point) (length arg)))
- (company-nxml-all-completions
- arg (rng-match-possible-attribute-names)))))
- (sorted t)))
-
- (defun company-nxml-attribute-value (command &optional arg &rest ignored)
- (cl-case command
- (prefix (and (derived-mode-p 'nxml-mode)
- rng-validate-mode
- (and (memq (char-after) '(?' ?\" ?\ ?\t ?\n)) ;; outside word
- (looking-back company-nxml-in-attribute-value-regexp nil)
- (or (match-string-no-properties 4)
- (match-string-no-properties 5)
- ""))))
- (candidates (company-nxml-prepared
- (let (attr-start attr-end colon)
- (and (looking-back rng-in-attribute-value-regex lt-pos)
- (setq colon (match-beginning 2)
- attr-start (match-beginning 1)
- attr-end (match-end 1))
- (rng-adjust-state-for-attribute lt-pos attr-start)
- (rng-adjust-state-for-attribute-value
- attr-start colon attr-end)
- (all-completions
- arg (rng-match-possible-value-strings))))))))
-
- ;;;###autoload
- (defun company-nxml (command &optional arg &rest ignored)
- "`company-mode' completion backend for `nxml-mode'."
- (interactive (list 'interactive))
- (cl-case command
- (interactive (company-begin-backend 'company-nxml))
- (prefix (or (company-nxml-tag 'prefix)
- (company-nxml-attribute 'prefix)
- (company-nxml-attribute-value 'prefix)))
- (candidates (cond
- ((company-nxml-tag 'prefix)
- (company-nxml-tag 'candidates arg))
- ((company-nxml-attribute 'prefix)
- (company-nxml-attribute 'candidates arg))
- ((company-nxml-attribute-value 'prefix)
- (sort (company-nxml-attribute-value 'candidates arg)
- 'string<))))
- (sorted t)))
-
- (provide 'company-nxml)
- ;;; company-nxml.el ends here
|