/.emacs.d/el-get/nxhtml/nxhtml/rngalt.el
https://bitbucket.org/shuangxinyu/emacspack · Lisp · 828 lines · 629 code · 65 blank · 134 comment · 15 complexity · d52541cd41f19acbd09da2354f6c3f02 MD5 · raw file
- ;;; rngalt.el --- Tools for making completion addition to nxml mode
- ;;
- ;; Author: Lennart Borgman
- ;; Created: Wed Jan 10 17:17:18 2007
- (defconst rngalt:version "0.51") ;;Version:
- ;; Last-Updated: 2008-03-08T03:33:56+0100 Sat
- ;; Keywords:
- ;; Compatibility:
- ;;
- ;; Features that might be required by this library:
- ;;
- ;; `nxml-enc', `nxml-ns', `nxml-parse', `nxml-util',
- ;; `ourcomments-util', `rng-dt', `rng-loc', `rng-match',
- ;; `rng-parse', `rng-pttrn', `rng-uri', `rng-util', `rng-valid',
- ;; `xmltok'.
- ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- ;;; Commentary:
- ;;
- ;;
- ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- ;;; Change log:
- ;;
- ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- ;; 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 2, 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; see the file COPYING. If not, write to the
- ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- ;; Boston, MA 02111-1307, USA.
- ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- ;;; Code:
- (eval-and-compile (require 'rng-valid))
- (eval-when-compile (require 'rng-nxml))
- (eval-when-compile (unless load-file-name (require 'nxhtml-mode nil t)))
- (eval-when-compile
- (let* ((this-file (or load-file-name
- (when (boundp 'bytecomp-filename) bytecomp-filename)
- buffer-file-name))
- (this-dir (file-name-directory this-file))
- (util-dir (expand-file-name "../util/" this-dir))
- (load-path (cons util-dir load-path)))
- (require 'ourcomments-util)))
- ;;(require 'ourcomments-util)
- ;; (setq x (macroexpand '(defcustom my-temp-opt t "doc" :type 'boolean)))
- ;; (setq x (macroexpand '(define-minor-mode my-temp-mode "doc")))
- ;; (setq x (macroexpand '(define-toggle my-temp-toggle t "doc")))
- ;;(define-toggle rngalt-display-validation-header t
- (define-minor-mode rngalt-display-validation-header
- "Display XML validation headers at the top of buffer when t.
- The validation header is only displayed in buffers where the main
- major mode is derived from `nxml-mode'."
- :global t
- :init-value t
- :group 'relax-ng
- :group 'nxhtml
- (when (fboundp 'rngalt-update-validation-header-overlay-everywhere)
- (rngalt-update-validation-header-overlay-everywhere)))
- (defun rngalt-display-validation-header-toggle ()
- "Toggle `rngalt-display-validation-header'."
- (interactive)
- (rngalt-display-validation-header (if rngalt-display-validation-header -1 1)))
- ;;(define-toggle rngalt-minimal-validation-header t
- (define-minor-mode rngalt-minimal-validation-header
- "If non-nil display only a short informaion about the XML validation header.
- See also `rngalt-display-validation-header'."
- :global t
- :init-value t
- :group 'relax-ng
- :group 'nxhtml
- (when (fboundp 'rngalt-update-validation-header-overlay-everywhere)
- (rngalt-update-validation-header-overlay-everywhere)))
- (defun rngalt-minimal-validation-header-toggle ()
- "Toggle `rngalt-minimal-validation-header'."
- (interactive)
- (rngalt-minimal-validation-header (if rngalt-minimal-validation-header -1 1)))
- (defface rngalt-validation-header-top
- '((t (:foreground "RGB:87/CE/FA" :background "white")))
- "Face first line of validation header."
- :group 'nxhtml)
- (defface rngalt-validation-header-bottom
- '((t (:foreground "white" :background "RGB:87/CE/FA")))
- "Face first line of validation header."
- :group 'nxhtml)
- ;; FIX-ME: remember to clear these variable, but where?
- (defvar rngalt-validation-header nil)
- (make-variable-buffer-local 'rngalt-validation-header)
- (put 'rngalt-validation-header 'permanent-local t)
- (defvar rngalt-current-schema-file-name nil)
- (make-variable-buffer-local 'rngalt-current-schema-file-name)
- (put 'rngalt-current-schema-file-name 'permanent-local t)
- (defvar rngalt-validation-header-overlay nil)
- (make-variable-buffer-local 'rngalt-validation-header-overlay)
- (put 'rngalt-validation-header-overlay 'permanent-local t)
- (defvar rngalt-major-mode nil)
- (make-variable-buffer-local 'rngalt-major-mode)
- (put 'rngalt-major-mode 'permanent-local t)
- (defvar rngalt-complete-first-try nil
- "First function to try for completion.
- If non-nil should be a function with no parameters. Used by
- `rngalt-complete'.")
- (defvar rngalt-complete-last-try nil
- "Last function to try for completion.
- If non-nil should be a function with no parameters. Used by
- `rngalt-complete'.")
- (defvar rngalt-completing-read-tag nil
- "Alternate function for completing tag name.
- If non-nil should be a function with the same parameters as
- `completing-read'. Used by `rngalt-complete'.")
- (defvar rngalt-completing-read-attribute-name nil
- "Alternate function for completing attribute name.
- If non-nil should be a function with the same parameters as
- `completing-read'. Used by `rngalt-complete'.")
- (defvar rngalt-completing-read-attribute-value nil
- "Alternate function for completing attribute value.
- If non-nil should be a function with the same parameters as
- `completing-read'. Used by `rngalt-complete'.")
- (defun rngalt-finish-element ()
- "Finish the current element by inserting an end-tag.
- Like `nxml-finish-element' but takes `rngalt-validation-header'
- into account."
- (interactive "*")
- (rngalt-finish-element-1 nil))
- ;; Fix-me: Check the other uses of `nxml-finish-element-1'. But this
- ;; is maybe not necessary since the only other use is in
- ;; `nxml-split-element' and that will anyway work - I believe ...
- (defun rngalt-finish-element-1 (startp)
- "Insert an end-tag for the current element and optionally a start-tag.
- The start-tag is inserted if STARTP is non-nil. Return the position
- of the inserted start-tag or nil if none was inserted.
- This is like `nxml-finish-element-1' but takes
- `rngalt-validation-header' into account."
- (interactive "*")
- (let (token-end
- start-tag-end
- starts-line
- ends-line
- start-tag-indent
- qname
- inserted-start-tag-pos)
- ;; Temporary insert the fictive validation header if any.
- (let ((buffer-undo-list nil)
- (here (point-marker)))
- (when rngalt-validation-header
- (let ((vh (nth 2 rngalt-validation-header)))
- (set-marker-insertion-type here t)
- (save-restriction
- (widen)
- (goto-char (point-min))
- (insert vh)))
- (goto-char here))
- (setq token-end (nxml-token-before))
- (setq start-tag-end
- (save-excursion
- (when (and (< (point) token-end)
- (memq xmltok-type
- '(cdata-section
- processing-instruction
- comment
- start-tag
- end-tag
- empty-element)))
- (error "Point is inside a %s"
- (nxml-token-type-friendly-name xmltok-type)))
- (nxml-scan-element-backward token-end t)))
- (when start-tag-end
- (setq starts-line
- (save-excursion
- (unless (eq xmltok-type 'start-tag)
- (error "No matching start-tag"))
- (goto-char xmltok-start)
- (back-to-indentation)
- (eq (point) xmltok-start)))
- (setq ends-line
- (save-excursion
- (goto-char start-tag-end)
- (looking-at "[ \t\r\n]*$")))
- (setq start-tag-indent (save-excursion
- (goto-char xmltok-start)
- (current-column)))
- (setq qname (xmltok-start-tag-qname)))
- ;; Undo the insertion of the fictive header:
- (undo-start)
- (while (and (not (eq t pending-undo-list))
- pending-undo-list)
- (undo-more 1))
- (goto-char here))
- (unless start-tag-end (error "No more start tags"))
- (when (and starts-line ends-line)
- ;; start-tag is on a line by itself
- ;; => put the end-tag on a line by itself
- (unless (<= (point)
- (save-excursion
- (back-to-indentation)
- (point)))
- (insert "\n"))
- (indent-line-to start-tag-indent))
- (insert "</" qname ">")
- (when startp
- (when starts-line
- (insert "\n")
- (indent-line-to start-tag-indent))
- (setq inserted-start-tag-pos (point))
- (insert "<" qname ">")
- (when (and starts-line ends-line)
- (insert "\n")
- (indent-line-to (save-excursion
- (goto-char xmltok-start)
- (forward-line 1)
- (back-to-indentation)
- (if (= (current-column)
- (+ start-tag-indent nxml-child-indent))
- (+ start-tag-indent nxml-child-indent)
- start-tag-indent)))))
- inserted-start-tag-pos))
- (defun rngalt-complete ()
- "Complete the string before point using the current schema.
- Return non-nil if in a context it understands.
- This function should be added to `nxml-completion-hook' before
- `rng-complete'. By default it works just like this function, but
- you can add your own completion by setting the variables
- `rngalt-complete-first-try', `rngalt-completing-read-tag',
- `rngalt-completing-read-attribute-name',
- `rngalt-completing-read-attribute-value' and
- `rngalt-complete-last-try'."
- (interactive)
- (unless rng-validate-mode
- (when (y-or-n-p
- "XML Validation is not on. Do you want to turn it on? ")
- (rng-validate-mode 1)))
- (when rng-validate-mode
- ;; schema file may mismatch if user sets it explicitly:
- (rngalt-reapply-validation-header)
- (when rng-current-schema-file-name
- (rngalt-validate))
- (or (when rngalt-complete-first-try
- (funcall rngalt-complete-first-try))
- (progn
- (unless rng-current-schema-file-name
- (when (eq major-mode 'nxhtml-mode)
- (when (y-or-n-p
- "There is currently no DTD specified for the buffer.
- This makes XHTML completion impossible. You can add a fictive
- XHTML validation header that sets the DTD to XHTML. This will
- not be inserted in the buffer but completion and XHTML validation
- will assume it is there so both error checking and completion
- will work.
- Do you want to add a fictive XHTML validation header? ")
- (message "") ;; Get rid of the large minibuffer message window
- (nxhtml-validation-header-mode)
- )))
- (let ((lt-pos (save-excursion (search-backward "<" nil t)))
- xmltok-dtd)
- (or (and lt-pos
- (= (rng-set-state-after lt-pos) lt-pos)
- (or (rngalt-complete-tag lt-pos)
- (rng-complete-end-tag lt-pos)
- (rngalt-complete-attribute-name lt-pos)
- (rngalt-complete-attribute-value lt-pos)))
- (when rngalt-complete-last-try
- (funcall rngalt-complete-last-try))))))))
- (defun rngalt-validate ()
- (unless (= (buffer-size) 0)
- (let ((while-n1 0)
- (maxn1 20))
- (condition-case err
- (while (and (> maxn1 (setq while-n1 (1+ while-n1)))
- (rng-do-some-validation))
- nil)
- (error
- ;; FIX-ME: for debugging:
- ;;(lwarn 'rngalt-validate :error "%s" (error-message-string err))
- (message "rngalt-validate: %s" (error-message-string err))
- nil))
- (when (>= while-n1 maxn1)
- (error "rngalt-validate: Could not validate")))
- (rng-validate-done)))
- (defvar rngalt-region-ovl nil)
- (defvar rngalt-region-prepared nil)
- (defun rngalt-complete-tag-region-prepare ()
- (unless rngalt-region-prepared
- (when rngalt-region-ovl
- (when (overlayp rngalt-region-ovl)
- (delete-overlay rngalt-region-ovl))
- (setq rngalt-region-ovl nil))
- (when (and mark-active
- transient-mark-mode)
- (let ((beginning (region-beginning))
- (end (region-end)))
- (unless (= (point) (region-beginning))
- (goto-char beginning))
- (when (save-excursion
- (when (re-search-forward "\\=[^<]*\\(?:<[^<]*>\\)*[^>]*" end t)
- (= end (point))))
- (setq rngalt-region-ovl (make-overlay beginning end))
- (overlay-put rngalt-region-ovl 'face 'region)
- )))
- (setq rngalt-region-prepared t)))
- (defun rngalt-complete-tag-region-cleanup ()
- (when rngalt-region-prepared
- (when (overlayp rngalt-region-ovl)
- (delete-overlay rngalt-region-ovl))
- (deactivate-mark)
- (setq rngalt-region-prepared nil)))
- (defun rngalt-complete-tag-region-finish ()
- (when (and rngalt-region-prepared
- (overlayp rngalt-region-ovl))
- (let ((here (point)))
- (insert ">")
- (goto-char (overlay-end rngalt-region-ovl))
- (nxml-finish-element)
- (rngalt-validate)
- (goto-char here)))
- (rngalt-complete-tag-region-cleanup))
- (defun rngalt-complete-tag (lt-pos)
- "Like `rng-complete-tag' but with some additions.
- The additions are:
- - Alternate completion.
- - Complete around highlighted region.
- See also the variable `rngalt-completing-read-tag'."
- (let (rng-complete-extra-strings)
- (when (and (= lt-pos (1- (point)))
- rng-complete-end-tags-after-<
- rng-open-elements
- (not (eq (car rng-open-elements) t))
- (or rng-collecting-text
- (rng-match-save
- (rng-match-end-tag))))
- (setq rng-complete-extra-strings
- (cons (concat "/"
- (if (caar rng-open-elements)
- (concat (caar rng-open-elements)
- ":"
- (cdar rng-open-elements))
- (cdar rng-open-elements)))
- rng-complete-extra-strings)))
- (when (save-excursion
- (re-search-backward rng-in-start-tag-name-regex
- lt-pos
- t))
- (and rng-collecting-text (rng-flush-text))
- (rngalt-complete-tag-region-prepare)
- (let ((completion
- (let ((rng-complete-target-names
- (rng-match-possible-start-tag-names))
- (rng-complete-name-attribute-flag nil))
- (rngalt-complete-before-point (1+ lt-pos)
- 'rng-complete-qname-function
- "Insert tag: "
- nil
- 'rng-tag-history
- rngalt-completing-read-tag)))
- name)
- (when completion
- (cond ((rng-qname-p completion)
- (setq name (rng-expand-qname completion
- t
- 'rng-start-tag-expand-recover))
- (when (and name
- (rng-match-start-tag-open name)
- (or (not (rng-match-start-tag-close))
- ;; need a namespace decl on the root element
- (and (car name)
- (not rng-open-elements))))
- ;; attributes are required
- (insert " "))
- (rngalt-complete-tag-region-finish)
- (run-hook-with-args 'rngalt-complete-tag-hooks completion)
- )
- ((member completion rng-complete-extra-strings)
- (insert ">")))))
- (rngalt-complete-tag-region-finish)
- t)))
- (defvar rngalt-complete-tag-hooks nil
- "Hook run after completing a tag.
- Each function is called with the last name of the last tag
- completed.")
- (defun rngalt-complete-attribute-name (lt-pos)
- "Like `rng-complete-attribute-name' but with alternate completion.
- See the variable `rngalt-completing-read-attribute-name'."
- (when (save-excursion
- (re-search-backward rng-in-attribute-regex lt-pos t))
- (let ((attribute-start (match-beginning 1))
- rng-undeclared-prefixes)
- (and (rng-adjust-state-for-attribute lt-pos
- attribute-start)
- (let ((rng-complete-target-names
- (rng-match-possible-attribute-names))
- (rng-complete-extra-strings
- (mapcar (lambda (prefix)
- (if prefix
- (concat "xmlns:" prefix)
- "xmlns"))
- rng-undeclared-prefixes))
- (rng-complete-name-attribute-flag t)
- completion)
- (setq completion
- (rngalt-complete-before-point attribute-start
- 'rng-complete-qname-function
- "Attribute: "
- nil
- 'rng-attribute-name-history
- rngalt-completing-read-attribute-name))
- (when (and completion
- (< 0 (length completion)))
- (insert "=\"")))))
- t))
- (defun rngalt-complete-attribute-value (lt-pos)
- "Like `rng-complete-attribute-value' but with alternate completion.
- See the variable `rngalt-completing-read-attribute-value'."
- (when (save-excursion
- (re-search-backward rng-in-attribute-value-regex lt-pos t))
- (let ((name-start (match-beginning 1))
- (name-end (match-end 1))
- (colon (match-beginning 2))
- (value-start (1+ (match-beginning 3))))
- (and (rng-adjust-state-for-attribute lt-pos
- name-start)
- (if (string= (buffer-substring-no-properties name-start
- (or colon name-end))
- "xmlns")
- (rngalt-complete-before-point
- value-start
- (rng-strings-to-completion-alist
- (rng-possible-namespace-uris
- (and colon
- (buffer-substring-no-properties (1+ colon) name-end))))
- "Namespace URI: "
- nil
- 'rng-namespace-uri-history
- rngalt-completing-read-attribute-value) ;; fix-me
- (rng-adjust-state-for-attribute-value name-start
- colon
- name-end)
- (rngalt-complete-before-point
- value-start
- (rng-strings-to-completion-alist
- (rng-match-possible-value-strings))
- "Value: "
- nil
- 'rng-attribute-value-history
- rngalt-completing-read-attribute-value))
- (unless (eq (char-after) (char-before value-start))
- (insert (char-before value-start)))))
- t))
- (defun rngalt-complete-before-point (start table prompt &optional predicate hist altcompl)
- "Complete text between START and point.
- Works like `rng-complete-before-point' if ALTCOMPL is nil. When
- ALTCOMPL is a function symbol and no completion alternative is
- available from table then this is called instead of
- `compleating-read' with the same parameters."
- (let* ((orig (buffer-substring-no-properties start (point)))
- (completion (try-completion orig table predicate))
- (completing-fun (if altcompl altcompl 'completing-read))
- (completion-ignore-case t))
- (cond ((not (or completion completing-fun))
- (if (string= orig "")
- (message "No completions available")
- (message "No completion for %s" (rng-quote-string orig)))
- (ding)
- nil)
- ((eq completion t) orig)
- ((and completion
- (not (string= completion orig)))
- (delete-region start (point))
- (insert completion)
- (cond ((not (rng-completion-exact-p completion table predicate))
- (message "Incomplete")
- nil)
- ((eq (try-completion completion table predicate) t)
- completion)
- (t
- (message "Complete but not unique")
- nil)))
- (t
- (setq completion
- (let ((saved-minibuffer-setup-hook
- (default-value 'minibuffer-setup-hook)))
- (add-hook 'minibuffer-setup-hook
- 'minibuffer-completion-help
- t)
- (unwind-protect
- (funcall completing-fun
- prompt
- table
- predicate
- nil
- orig
- hist)
- (setq-default minibuffer-setup-hook
- saved-minibuffer-setup-hook))))
- (when completion
- (delete-region start (point))
- (insert completion))
- completion))))
- (defun rngalt-get-missing-required-attr (single-tag)
- "Get a list of missing required attributes.
- This is to be used when completing attribute names.
- SINGLE-TAG should be non-nil if the tag has no end tag.
- For a typical use see `nxhtml-completing-read-attribute-name' in
- nxhtml.el.
- "
- ;; FIX-ME: This is a terrible cludge. One day I hope I will
- ;; understand how to write this ;-)
- ;;
- ;; I currently fetch the missing tags from the error message in the
- ;; error overlay set by rng validate.
- (let ((here (point)))
- (unless (save-match-data (looking-at "[^<]\\{,200\\}>"))
- ;; We can probably add a >, so let us do it:
- (when single-tag
- (insert "/"))
- (insert ">")
- (rngalt-validate))
- (goto-char here))
- (let ((ovl (rng-error-overlay-message (or (rng-error-overlay-after (point))
- (rng-error-overlay-after (1- (point)))))))
- ;;(message "ovl=%s" ovl)(sit-for 1)
- ;;(message "prop ovl=%s" (overlay-properties ovl))(sit-for 1)
- (when (and ovl
- (eq (overlay-get ovl 'category) 'rng-error))
- ;;(message "rng-error")(sit-for 1)
- (let ((msg (overlay-get ovl 'help-echo)))
- ;;(message "msg=%s" msg);(sit-for 1)
- (when (string-match "Missing attributes? \\(.*\\)" msg)
- ;;(message "0=%s" (match-string 0 msg));(sit-for 1)
- ;;(message "1=%s" (match-string 1 msg));(sit-for 1)
- (let* ((matches (match-string 1 msg))
- (lst (split-string (substring matches 1 (- (length matches) 1)) "\", \"")))
- ;;(message "matches=%s" matches);(sit-for 2)
- ;;(message "lst=%s" lst);(sit-for 1)
- lst))))))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;; Validation start state
- (defun rngalt-after-change-major ()
- (unless (and (boundp 'mumamo-set-major-running)
- mumamo-set-major-running)
- (setq rngalt-major-mode major-mode)
- (when (and (derived-mode-p 'nxml-mode)
- rngalt-validation-header)
- (rngalt-reapply-validation-header))
- (rngalt-update-validation-header-overlay)))
- (defvar rngalt-validation-header-keymap
- (let ((map (make-sparse-keymap)))
- (define-key map [mouse-1] 'rngalt-minimal-validation-header-toggle)
- map))
- (defun rngalt-update-validation-header-overlay ()
- (if (and (boundp 'rngalt-display-validation-header)
- rngalt-display-validation-header
- rngalt-validation-header
- (or (derived-mode-p 'nxml-mode)
- (let ((major-mode rngalt-major-mode))
- (and major-mode
- (derived-mode-p 'nxml-mode))))
- )
- (progn
- (if rngalt-validation-header-overlay
- (move-overlay rngalt-validation-header-overlay 1 1)
- (setq rngalt-validation-header-overlay (make-overlay 1 1)))
- (overlay-put rngalt-validation-header-overlay
- 'priority 1000)
- ;; Other properties should go to the 'before-string
- (let* ((validation-header (nth 2 rngalt-validation-header))
- (header
- (if rngalt-minimal-validation-header
- (propertize
- (concat
- "*** Fictive XHTML/XML Validation Header: ... "
- (save-match-data
- (if (string-match "\\(<[^[:space:]>]+\\)[^>]*>[^<>]*\\'"
- validation-header)
- (concat (match-string 1 validation-header) ">")
- "Error"))
- "\n")
- 'face 'rngalt-validation-header-bottom)
- (concat
- (propertize "*** Fictive XHTML/XML Validation Header:\n"
- 'face 'rngalt-validation-header-top)
- (propertize (concat validation-header "\n")
- 'face 'rngalt-validation-header-bottom)))))
- (setq header
- (propertize
- header
- 'help-echo
- "Click to toggle full/minimal display of header"
- 'keymap rngalt-validation-header-keymap))
- (overlay-put rngalt-validation-header-overlay
- 'before-string header)))
- (when rngalt-validation-header-overlay
- (delete-overlay rngalt-validation-header-overlay))))
- (defun rngalt-update-validation-header-overlay-everywhere ()
- (dolist (b (buffer-list))
- (when (buffer-live-p b)
- (with-current-buffer b
- (when rngalt-validation-header
- (rngalt-update-validation-header-overlay))))))
- ;; This is exactly the same as the original `rng-set-initial-state'
- ;; except when `rngalt-validation-header' is non-nil."
- (defadvice rng-set-initial-state (around
- rngalt-set-initial-state
- activate
- compile
- )
- (nxml-ns-init)
- (rng-match-start-document)
- (setq rng-open-elements nil)
- (setq rng-pending-contents nil)
- (when rngalt-validation-header
- (let ((state (car rngalt-validation-header)))
- (rng-restore-state state)))
- (setq ad-return-value (goto-char (point-min))))
- ;; (defun rng-new-validate-prepare ()
- ;; "Prepare to do some validation, initializing point and the state.
- ;; Return t if there is work to do, nil otherwise.
- ;; This is exactly the same as the original-insert-directory
- ;; `rng-validate-prepare' with the difference that the state at
- ;; point 1 is set differently if `rngalt-validation-header' is
- ;; non-nil.
- ;; See also `rng-set-initial-state'."
- ;; (cond ((= rng-validate-up-to-date-end 1)
- ;; (rng-set-initial-state)
- ;; t)
- ;; ((= rng-validate-up-to-date-end (point-max))
- ;; nil)
- ;; (t (let ((state
- ;; (if (and rngalt-validation-header
- ;; (= rng-validate-up-to-date-end 1))
- ;; (car rngalt-validation-header)
- ;; (get-text-property (1- rng-validate-up-to-date-end)
- ;; 'rng-state))))
- ;; (cond (state
- ;; (rng-restore-state state)
- ;; (goto-char rng-validate-up-to-date-end))
- ;; (t
- ;; (let ((pos (previous-single-property-change
- ;; rng-validate-up-to-date-end
- ;; 'rng-state)))
- ;; (cond (pos
- ;; (rng-restore-state
- ;; (or (get-text-property (1- pos) 'rng-state)
- ;; (error "Internal error: state null")))
- ;; (goto-char pos))
- ;; (t (rng-set-initial-state))))))))))
- ;; For as-external.el
- ;;;###autoload
- (defun rngalt-set-validation-header (start-of-doc)
- (let ((old-rvm rng-validate-mode))
- (when old-rvm (rng-validate-mode -1))
- (if start-of-doc
- (progn
- (add-hook 'after-change-major-mode-hook 'rngalt-after-change-major nil t)
- (setq rngalt-validation-header (rngalt-get-state-after start-of-doc))
- (rng-set-schema-file-1 (cadr rngalt-validation-header))
- (setq rngalt-current-schema-file-name rng-current-schema-file-name)
- (setq rng-compile-table nil)
- (setq rng-ipattern-table nil)
- (setq rng-last-ipattern-index nil))
- (remove-hook 'after-change-major-mode-hook 'rngalt-after-change-major t)
- (setq rngalt-validation-header nil)
- (when old-rvm
- (rng-set-vacuous-schema)
- (rng-auto-set-schema)))
- (when old-rvm
- (rng-validate-mode 1)
- (rngalt-update-validation-header-overlay)
- (rngalt-update-validation-header-buffer))))
- (defun rngalt-reapply-validation-header ()
- (when rngalt-validation-header
- (when (or (not rng-current-schema-file-name)
- (unless (string= rngalt-current-schema-file-name rng-current-schema-file-name)
- (lwarn 'schema-mismatch :warning
- "XHTML validation header schema %s reapplied (replaces %s)"
- (file-name-nondirectory rngalt-current-schema-file-name)
- (file-name-nondirectory rng-current-schema-file-name))
- t))
- (rngalt-set-validation-header (nth 2 rngalt-validation-header)))))
- ;; (defun rngalt-clear-validation-header ()
- ;; "Remove XML validation header from current buffer.
- ;; For more information see `rngalt-show-validation-header'."
- ;; (interactive)
- ;; (rngalt-set-validation-header nil)
- ;; (rng-auto-set-schema t))
- ;; FIX-ME: Add edit header?
- (defun rngalt-get-validation-header-buffer ()
- (let ((b (get-buffer " *XML Validation Header*")))
- (unless b
- (setq b (get-buffer-create " *XML Validation Header*"))
- (with-current-buffer b
- ;;(fundamental-mode)
- (nxml-mode)))
- b))
- (defun rngalt-get-state-after (start-of-doc)
- ;; FIX-ME: better buffer name?
- (let ((statebuf (rngalt-get-validation-header-buffer)))
- (with-current-buffer statebuf
- (when rng-validate-mode (rng-validate-mode -1))
- (erase-buffer)
- (insert start-of-doc)
- ;; From rng-get-state
- (setq rng-match-state nil)
- (setq nxml-ns-state nil)
- (setq rng-open-elements nil)
- ;; From rng-match-init-buffer
- (setq rng-compile-table nil)
- (setq rng-ipattern-table nil)
- (setq rng-last-ipattern-index nil)
- (nxml-mode)
- (rng-validate-mode 1)
- (rngalt-validate)
- (let* ((state (rng-get-state))
- (cp-state (copy-tree state)))
- ;;(if (equal state cp-state) (message "(equal state cp-state)=t") (message "(equal state cp-state)=nil"))
- ;; Fix-me: is the copy-tree necessary here?
- (list
- cp-state
- (rng-locate-schema-file)
- start-of-doc)))))
- (defun rngalt-show-validation-header ()
- "Show XML validation header used in current buffer.
- The XML validation header is used in `nxhtml-mode' to set a state
- for XML validation at the start of the buffer.
- The purpose is to make it possible to use `nxml-mode' completion
- in buffers where you do not actually have a full XML file. This
- could for example be a buffer with PHP code or a buffer with a
- blog entry.
- More techhnical info: This can be used by any mode derived from
- `nxml-mode'. To use it in other modes than `nxhtml-mode' replace
- `rng-complete' by `rngalt-complete' in `nxml-completion-hook'."
- (interactive)
- (unless (derived-mode-p 'nxml-mode)
- (error "Buffer mode is not an nXml type major mode: %s" major-mode))
- (rngalt-update-validation-header-buffer)
- (display-buffer (rngalt-get-validation-header-buffer) t))
- (defun rngalt-update-validation-header-buffer ()
- (let ((vh (nth 2 rngalt-validation-header))
- (cb (current-buffer)))
- (with-current-buffer (rngalt-get-validation-header-buffer)
- (erase-buffer)
- (if (not vh)
- (setq header-line-format (concat " No XML validation header in buffer "
- (buffer-name cb)))
- (insert vh)
- (setq header-line-format (concat " XML validation header in buffer "
- (buffer-name cb)))))))
- ;; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- (provide 'rngalt)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;; rngalt.el ends here