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.
263 lines
9.8 KiB
263 lines
9.8 KiB
;;; ac-html-core.el --- auto complete html core -*- lexical-binding: t; -*- |
|
|
|
;; Copyright (C) 2015 Zhang Kai Yu |
|
|
|
;; Author: Zhang Kai Yu <yeannylam@gmail.com> |
|
|
|
;; This program 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. |
|
|
|
;; This program 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, see <http://www.gnu.org/licenses/>. |
|
|
|
;;; Commentary: |
|
|
|
;; |
|
|
|
;;; Code: |
|
|
|
(require 'auto-complete) |
|
(require 'cl-lib) |
|
(require 'dash) |
|
|
|
;;; Customization |
|
|
|
(defgroup auto-complete-html nil |
|
"HTML Auto Complete." |
|
:group 'auto-complete |
|
:prefix "ac-html-") |
|
|
|
;;; Variables |
|
|
|
(defvar ac-html-data-providers nil "Completion data providers.") |
|
|
|
(defvar-local ac-html-enabled-data-providers nil |
|
"The enabled data providers of current buffer.") |
|
|
|
(defvar-local ac-html-current-tag-function nil |
|
"The function to find current tag.") |
|
|
|
(defvar-local ac-html-current-attr-function nil |
|
"The function to find current attr.") |
|
|
|
;;; Provider |
|
|
|
;;;###autoload |
|
(defmacro ac-html-define-data-provider (provider &rest pairs) |
|
"Define ac-html data provider with this macro. |
|
This macro is buggy and cannot be used now." |
|
(declare (indent 1) (debug t)) |
|
(let (tag-func attr-func attrv-func id-func class-func tag-doc-func |
|
attr-doc-func attrv-doc-func id-doc-func class-doc-func) |
|
(let (label value) |
|
(while (not (= 0 (length pairs))) |
|
(setq label (pop pairs)) |
|
(setq value (pop pairs)) |
|
(and (equal :tag-func label) (setq tag-func value)) |
|
(and (equal :attr-func label) (setq attr-func value)) |
|
(and (equal :attrv-func label) (setq attrv-func value)) |
|
(and (equal :id-func label) (setq id-func value)) |
|
(and (equal :class-func label) (setq class-func value)) |
|
(and (equal :tag-doc-func label) (setq tag-doc-func value)) |
|
(and (equal :attr-doc-func label) (setq attr-doc-func value)) |
|
(and (equal :attrv-doc-func label) (setq attrv-doc-func value)) |
|
(and (equal :id-doc-func label) (setq id-doc-func value)) |
|
(and (equal :class-doc-func label) (setq class-doc-func value)))) |
|
`(progn |
|
(add-to-list 'ac-html-data-providers ,provider) |
|
(put ,provider :tag-func ,tag-func) |
|
(put ,provider :attr-func ,attr-func) |
|
(put ,provider :attrv-func ,attrv-func) |
|
(put ,provider :id-func ,id-func) |
|
(put ,provider :class-func ,class-func) |
|
(put ,provider :tag-doc-func ,tag-doc-func) |
|
(put ,provider :attr-doc-func ,attr-doc-func) |
|
(put ,provider :attrv-doc-func ,attrv-doc-func) |
|
(put ,provider :id-doc-func ,id-doc-func) |
|
(put ,provider :class-doc-func ,class-doc-func)))) |
|
|
|
;;;###autoload |
|
(defun ac-html-enable-data-provider (provider) |
|
"Enable data provider PROVIDER." |
|
(add-to-list 'ac-html-enabled-data-providers provider)) |
|
|
|
(defun ac-html-query-data-provider (provider key) |
|
(get provider key)) |
|
|
|
;;; Language (Adaptor) |
|
|
|
;;;###autoload |
|
(defmacro ac-html-define-ac-source (lang &rest pairs) |
|
"Define ac-html lang with this macro." |
|
(declare (indent 1) (debug t)) |
|
(let (tag-prefix attr-prefix attrv-prefix id-prefix class-prefix |
|
current-tag-func current-attr-func) |
|
(let (label value) |
|
(while (not (= 0 (length pairs))) |
|
(setq label (pop pairs)) |
|
(setq value (pop pairs)) |
|
(and (equal :tag-prefix label) (setq tag-prefix value)) |
|
(and (equal :attr-prefix label) (setq attr-prefix value)) |
|
(and (equal :attrv-prefix label) (setq attrv-prefix value)) |
|
(and (equal :id-prefix label) (setq id-prefix value)) |
|
(and (equal :class-prefix label) (setq class-prefix value)) |
|
(and (equal :current-tag-func label) (setq current-tag-func value)) |
|
(and (equal :current-attr-func label) (setq current-attr-func value)))) |
|
|
|
`(progn |
|
(defun ,(intern (format "ac-%s-setup" lang)) () |
|
,(format "Setup for ac-html to provide completion for %s language." lang) |
|
(setq ac-html-current-tag-function (quote ,current-tag-func)) |
|
(setq ac-html-current-attr-function (quote ,current-attr-func))) |
|
,(if tag-prefix |
|
`(ac-define-source ,(format "%s-%s" lang "tag") |
|
'((candidates . ac-html-all-tag-candidates) |
|
(prefix . ,tag-prefix) |
|
(document . ac-html-tag-documentation) |
|
(symbol . "t")))) |
|
,(if attr-prefix |
|
`(ac-define-source ,(format "%s-%s" lang "attr") |
|
'((candidates . ac-html-all-attr-candidates) |
|
(prefix . ,attr-prefix) |
|
(document . ac-html-attr-documentation) |
|
(symbol . "a")))) |
|
,(if attrv-prefix |
|
`(ac-define-source ,(format "%s-%s" lang "attrv") |
|
'((candidates . ac-html-all-attrv-candidates) |
|
(prefix . ,attrv-prefix) |
|
(document . ac-html-attrv-documentation) |
|
(symbol . "v")))) |
|
,(if id-prefix |
|
`(ac-define-source ,(format "%s-%s" lang "id") |
|
'((candidates . ac-html-all-id-candidates) |
|
(prefix . ,id-prefix) |
|
(document . ac-html-id-documentation) |
|
(symbol . "i")))) |
|
,(if class-prefix |
|
`(ac-define-source ,(format "%s-%s" lang "class") |
|
'((candidates . ac-html-all-class-candidates) |
|
(prefix . ,class-prefix) |
|
(document . ac-html-class-documentation) |
|
(symbol . "c")))) |
|
))) |
|
|
|
;;; Data |
|
|
|
(defun ac-html-all-tag-candidates () |
|
"All tag candidates get from data providers." |
|
(let (list func) |
|
(dolist (provider ac-html-enabled-data-providers) |
|
(setq func (ac-html-query-data-provider provider :tag-func)) |
|
(if func (setq list (-concat list (funcall func))))) |
|
list)) |
|
|
|
(defun ac-html-all-attr-candidates () |
|
"All attr candidates get from data providers." |
|
(let (list func tag) |
|
(dolist (provider ac-html-enabled-data-providers) |
|
(setq func (ac-html-query-data-provider provider :attr-func)) |
|
(setq tag (funcall ac-html-current-tag-function)) |
|
(if func (setq list (-concat list (funcall func tag))))) |
|
list)) |
|
|
|
(defun ac-html-all-attrv-candidates () |
|
"All attrv candidates get from data providers." |
|
(let (list func tag attr) |
|
(dolist (provider ac-html-enabled-data-providers) |
|
(setq func (ac-html-query-data-provider provider :attrv-func)) |
|
(setq tag (funcall ac-html-current-tag-function)) |
|
(setq attr (funcall ac-html-current-attr-function)) |
|
(if func (setq list (-concat list (funcall func tag attr))))) |
|
(if (string= attr "class") |
|
(setq list (-concat list (ac-html-all-class-candidates)))) |
|
(if (string= attr "id") |
|
(setq list (-concat list (ac-html-all-id-candidates)))) |
|
list)) |
|
|
|
(defun ac-html-all-id-candidates () |
|
"" |
|
(let (list func) |
|
(dolist (provider ac-html-enabled-data-providers) |
|
(setq func (ac-html-query-data-provider provider :id-func)) |
|
(if func (setq list (-concat list (funcall func))))) |
|
list)) |
|
|
|
(defun ac-html-all-class-candidates () |
|
"" |
|
(let (list func) |
|
(dolist (provider ac-html-enabled-data-providers) |
|
(setq func (ac-html-query-data-provider provider :class-func)) |
|
(if func (setq list (-concat list (funcall func))))) |
|
list)) |
|
|
|
(defun ac-html-tag-documentation (tag) |
|
"Not documented yet." |
|
(catch 'return-val |
|
(let (doc func) |
|
(dolist (provider ac-html-enabled-data-providers) |
|
(setq func (ac-html-query-data-provider provider :tag-doc-func)) |
|
(if func |
|
(progn |
|
(setq doc (funcall func tag)) |
|
(if doc (throw 'return-val doc)))))))) |
|
|
|
(defun ac-html-attr-documentation (attr) |
|
"Not documented yet." |
|
(catch 'return-val |
|
(let (doc func tag) |
|
(dolist (provider ac-html-enabled-data-providers) |
|
(setq func (ac-html-query-data-provider provider :attr-doc-func)) |
|
(if func |
|
(progn |
|
(setq tag (funcall ac-html-current-tag-function)) |
|
(setq doc (funcall func tag attr)) |
|
(if doc (throw 'return-val doc)))))))) |
|
|
|
(defun ac-html-attrv-documentation (attrv) |
|
"Not documented yet." |
|
(catch 'return-val |
|
(let (doc func tag attr) |
|
(dolist (provider ac-html-enabled-data-providers) |
|
(setq func (ac-html-query-data-provider provider :attrv-doc-func)) |
|
(if func |
|
(progn |
|
(setq tag (funcall ac-html-current-tag-function)) |
|
(setq attr (funcall ac-html-current-attr-function)) |
|
(setq doc (funcall func tag attr attrv)) |
|
(if doc (throw 'return-val doc))))) |
|
(if (string= attr "class") |
|
(throw 'return-val (ac-html-class-documentation attrv))) |
|
(if (string= attr "id") |
|
(throw 'return-val (ac-html-id-documentation attrv)))))) |
|
|
|
(defun ac-html-id-documentation (id) |
|
"" |
|
(catch 'return-val |
|
(let (doc func) |
|
(dolist (provider ac-html-enabled-data-providers) |
|
(setq func (ac-html-query-data-provider provider :id-doc-func)) |
|
(if func |
|
(progn |
|
(setq doc (funcall func id)) |
|
(if doc (throw 'return-val doc)))))))) |
|
|
|
(defun ac-html-class-documentation (class) |
|
"" |
|
(catch 'return-val |
|
(let (doc func) |
|
(dolist (provider ac-html-enabled-data-providers) |
|
(setq func (ac-html-query-data-provider provider :class-doc-func)) |
|
(if func |
|
(progn |
|
(setq doc (funcall func class)) |
|
(if doc (throw 'return-val doc)))))))) |
|
|
|
(provide 'ac-html-core) |
|
;;; ac-html-core.el ends here
|
|
|