]> code.delx.au - gnu-emacs-elpa/commitdiff
Added nxml-mode support.
authorNikolaj Schumacher <git@nschum.de>
Thu, 12 Mar 2009 10:02:14 +0000 (11:02 +0100)
committerNikolaj Schumacher <git@nschum.de>
Fri, 20 Mar 2009 08:46:05 +0000 (09:46 +0100)
company-nxml.el [new file with mode: 0644]
company.el

diff --git a/company-nxml.el b/company-nxml.el
new file mode 100644 (file)
index 0000000..18badc8
--- /dev/null
@@ -0,0 +1,102 @@
+(require 'company)
+(require 'nxml-mode)
+(require 'rng-nxml)
+(eval-when-compile (require 'cl))
+
+(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)
+  (case command
+    ('prefix (and (eq major-mode '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)
+  (case command
+    ('prefix (and (eq major-mode '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)
+  (case command
+    ('prefix (and (eq major-mode 'nxml-mode)
+                  rng-validate-mode
+                  (and (memq (char-after) '(?' ?\" ?\  ?\t ?\n)) ;; outside word
+                       (looking-back company-nxml-in-attribute-value-regexp)
+                       (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))))))))
+
+(defun company-nxml (command &optional arg &rest ignored)
+  (case command
+    ('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
index af0f63a878d0ce6a86d71b93929968a1551e02ec..d4fd307ed2b58634f8ebfbaf9fdf482d7c84bc5f 100644 (file)
@@ -93,7 +93,7 @@
                                 company-preview-if-just-one-frontend)
                          (function :tag "custom function" nil))))
 
-(defcustom company-backends '(company-elisp)
+(defcustom company-backends '(company-elisp company-nxml)
   "*"
   :group 'company
   :type '(repeat (function :tag "function" nil)))