Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 line
5.6 KiB

4 年之前
  1. ;;; company-nxml.el --- company-mode completion backend for nxml-mode
  2. ;; Copyright (C) 2009-2011, 2013, 2018 Free Software Foundation, Inc.
  3. ;; Author: Nikolaj Schumacher
  4. ;; This file is part of GNU Emacs.
  5. ;; GNU Emacs is free software: you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation, either version 3 of the License, or
  8. ;; (at your option) any later version.
  9. ;; GNU Emacs is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;;
  17. ;; In Emacs >= 26, company-capf is used instead.
  18. ;;; Code:
  19. (require 'company)
  20. (require 'cl-lib)
  21. (defvar rng-open-elements)
  22. (defvar rng-validate-mode)
  23. (defvar rng-in-attribute-regex)
  24. (defvar rng-in-attribute-value-regex)
  25. (declare-function rng-set-state-after "rng-nxml")
  26. (declare-function rng-match-possible-start-tag-names "rng-match")
  27. (declare-function rng-adjust-state-for-attribute "rng-nxml")
  28. (declare-function rng-match-possible-attribute-names "rng-match")
  29. (declare-function rng-adjust-state-for-attribute-value "rng-nxml")
  30. (declare-function rng-match-possible-value-strings "rng-match")
  31. (defconst company-nxml-token-regexp
  32. "\\(?:[_[:alpha:]][-._[:alnum:]]*\\_>\\)")
  33. (defvar company-nxml-in-attribute-value-regexp
  34. (replace-regexp-in-string "w" company-nxml-token-regexp
  35. "<w\\(?::w\\)?\
  36. \\(?:[ \t\r\n]+w\\(?::w\\)?[ \t\r\n]*=\
  37. \[ \t\r\n]*\\(?:\"[^\"]*\"\\|'[^']*'\\)\\)*\
  38. \[ \t\r\n]+\\(w\\(:w\\)?\\)[ \t\r\n]*=[ \t\r\n]*\
  39. \\(\"\\([^\"]*\\>\\)\\|'\\([^']*\\>\\)\\)\\="
  40. t t))
  41. (defvar company-nxml-in-tag-name-regexp
  42. (replace-regexp-in-string "w" company-nxml-token-regexp
  43. "<\\(/?w\\(?::w?\\)?\\)?\\=" t t))
  44. (defun company-nxml-all-completions (prefix alist)
  45. (let ((candidates (mapcar 'cdr alist))
  46. (case-fold-search nil)
  47. filtered)
  48. (when (cdar rng-open-elements)
  49. (push (concat "/" (cdar rng-open-elements)) candidates))
  50. (setq candidates (sort (all-completions prefix candidates) 'string<))
  51. (while candidates
  52. (unless (equal (car candidates) (car filtered))
  53. (push (car candidates) filtered))
  54. (pop candidates))
  55. (nreverse filtered)))
  56. (defmacro company-nxml-prepared (&rest body)
  57. (declare (indent 0) (debug t))
  58. `(let ((lt-pos (save-excursion (search-backward "<" nil t)))
  59. xmltok-dtd)
  60. (when (and lt-pos (= (rng-set-state-after lt-pos) lt-pos))
  61. ,@body)))
  62. (defun company-nxml-tag (command &optional arg &rest ignored)
  63. (cl-case command
  64. (prefix (and (derived-mode-p 'nxml-mode)
  65. rng-validate-mode
  66. (company-grab company-nxml-in-tag-name-regexp 1)))
  67. (candidates (company-nxml-prepared
  68. (company-nxml-all-completions
  69. arg (rng-match-possible-start-tag-names))))
  70. (sorted t)))
  71. (defun company-nxml-attribute (command &optional arg &rest ignored)
  72. (cl-case command
  73. (prefix (and (derived-mode-p 'nxml-mode)
  74. rng-validate-mode
  75. (memq (char-after) '(?\ ?\t ?\n)) ;; outside word
  76. (company-grab rng-in-attribute-regex 1)))
  77. (candidates (company-nxml-prepared
  78. (and (rng-adjust-state-for-attribute
  79. lt-pos (- (point) (length arg)))
  80. (company-nxml-all-completions
  81. arg (rng-match-possible-attribute-names)))))
  82. (sorted t)))
  83. (defun company-nxml-attribute-value (command &optional arg &rest ignored)
  84. (cl-case command
  85. (prefix (and (derived-mode-p 'nxml-mode)
  86. rng-validate-mode
  87. (and (memq (char-after) '(?' ?\" ?\ ?\t ?\n)) ;; outside word
  88. (looking-back company-nxml-in-attribute-value-regexp nil)
  89. (or (match-string-no-properties 4)
  90. (match-string-no-properties 5)
  91. ""))))
  92. (candidates (company-nxml-prepared
  93. (let (attr-start attr-end colon)
  94. (and (looking-back rng-in-attribute-value-regex lt-pos)
  95. (setq colon (match-beginning 2)
  96. attr-start (match-beginning 1)
  97. attr-end (match-end 1))
  98. (rng-adjust-state-for-attribute lt-pos attr-start)
  99. (rng-adjust-state-for-attribute-value
  100. attr-start colon attr-end)
  101. (all-completions
  102. arg (rng-match-possible-value-strings))))))))
  103. ;;;###autoload
  104. (defun company-nxml (command &optional arg &rest ignored)
  105. "`company-mode' completion backend for `nxml-mode'."
  106. (interactive (list 'interactive))
  107. (cl-case command
  108. (interactive (company-begin-backend 'company-nxml))
  109. (prefix (or (company-nxml-tag 'prefix)
  110. (company-nxml-attribute 'prefix)
  111. (company-nxml-attribute-value 'prefix)))
  112. (candidates (cond
  113. ((company-nxml-tag 'prefix)
  114. (company-nxml-tag 'candidates arg))
  115. ((company-nxml-attribute 'prefix)
  116. (company-nxml-attribute 'candidates arg))
  117. ((company-nxml-attribute-value 'prefix)
  118. (sort (company-nxml-attribute-value 'candidates arg)
  119. 'string<))))
  120. (sorted t)))
  121. (provide 'company-nxml)
  122. ;;; company-nxml.el ends here