;;; sgml-mode.el --- SGML- and HTML-editing modes
-;; Copyright (C) 1992, 1995, 1996, 1998 Free Software Foundation, Inc.
+;; Copyright (C) 1992,95,96,98,2001 Free Software Foundation, Inc.
;; Author: James Clark <jjc@jclark.com>
;; Adapted-By: ESR, Daniel Pfeiffer <occitan@esperanto.org>,
(defvar sgml-mode-map
- (let ((map (list 'keymap (make-vector 256 nil)))
+ (let ((map (make-keymap)) ;`sparse' doesn't allow binding to charsets.
(menu-map (make-sparse-keymap "SGML")))
- (define-key map "\t" 'indent-relative-maybe)
(define-key map "\C-c\C-i" 'sgml-tags-invisible)
(define-key map "/" 'sgml-slash)
(define-key map "\C-c\C-n" 'sgml-name-char)
(define-key map "\"" 'sgml-name-self))
(if (memq ?' sgml-specials)
(define-key map "'" 'sgml-name-self))))
- (let ((c 127)
- (map (nth 1 map)))
- (while (< (setq c (1+ c)) 256)
- (aset map c 'sgml-maybe-name-self)))
+ (define-key map (vector (make-char 'latin-iso8859-1))
+ 'sgml-maybe-name-self)
(define-key map [menu-bar sgml] (cons "SGML" menu-map))
(define-key menu-map [sgml-validate] '("Validate" . sgml-validate))
(define-key menu-map [sgml-name-8bit-mode]
"nbsp" "iexcl" "cent" "pound" "curren" "yen" "brvbar" "sect"
"uml" "copy" "ordf" "laquo" "not" "shy" "reg" "macr"
"ring" "plusmn" "sup2" "sup3" "acute" "micro" "para" "middot"
- "cedil" "sup1" "ordm" "raquo" "frac14" "half" "frac34" "iquest"
+ "cedil" "sup1" "ordm" "raquo" "frac14" "frac12" "frac34" "iquest"
"Agrave" "Aacute" "Acirc" "Atilde" "Auml" "Aring" "AElig" "Ccedil"
"Egrave" "Eacute" "Ecirc" "Euml" "Igrave" "Iacute" "Icirc" "Iuml"
"ETH" "Ntilde" "Ograve" "Oacute" "Ocirc" "Otilde" "Ouml" nil
"The command last used to validate in this buffer.")
-;;; I doubt that null end tags are used much for large elements,
-;;; so use a small distance here.
+;; I doubt that null end tags are used much for large elements,
+;; so use a small distance here.
(defcustom sgml-slash-distance 1000
"*If non-nil, is the maximum distance to search for matching `/'."
:type '(choice (const nil) integer)
(make-local-variable 'comment-start)
(make-local-variable 'comment-end)
(make-local-variable 'comment-indent-function)
- (make-local-variable 'comment-start-skip)
(make-local-variable 'comment-indent-function)
(make-local-variable 'sgml-tags-invisible)
(make-local-variable 'skeleton-transformation)
paragraph-separate "[ \t]*$\\|\
\[ \t]*</?\\([A-Za-z]\\([-.A-Za-z0-9= \t\n]\\|\"[^\"]*\"\\|'[^']*'\\)*\\)?>$"
paragraph-start "[ \t]*$\\|\
-\[ \t]*</?\\([A-Za-z]\\([-.A-Za-z0-9= \t\n]\\|\"[^\"]*\"\\|'[^']*'\\)*\\)?>$"
+\[ \t]*</?\\([A-Za-z]\\([-.A-Za-z0-9= \t\n]\\|\"[^\"]*\"\\|'[^']*'\\)*\\)?>"
adaptive-fill-regexp "[ \t]*"
comment-start "<!-- "
comment-end " -->"
comment-indent-function 'sgml-comment-indent
- ;; This will allow existing comments within declarations to be
- ;; recognized.
- comment-start-skip "--[ \t]*"
skeleton-transformation sgml-transformation
skeleton-further-elements '((completion-ignore-case t))
skeleton-end-hook (lambda ()
nil
t)
facemenu-add-face-function 'sgml-mode-facemenu-add-face-function)
- (while sgml-display-text
- (put (car (car sgml-display-text)) 'before-string
- (cdr (car sgml-display-text)))
- (setq sgml-display-text (cdr sgml-display-text))))
+ ;; This will allow existing comments within declarations to be
+ ;; recognized.
+ (set (make-local-variable 'comment-start-skip) "\\(?:<!\\)?--[ \t]*")
+ (set (make-local-variable 'comment-end-skip) "[ \t]*--\\([ \t\n]*>\\)?")
+ (dolist (pair sgml-display-text)
+ (put (car pair) 'before-string (cdr pair))))
(defun sgml-mode-facemenu-add-face-function (face end)
(setq face (funcall skeleton-transformation face))
(setq facemenu-end-add-face (concat "</" face ">"))
(concat "<" face ">"))
- (error "Face not configured for %s mode." mode-name)))
+ (error "Face not configured for %s mode" mode-name)))
;;;###autoload
-(defun sgml-mode (&optional function)
+(defun sgml-mode ()
"Major mode for editing SGML documents.
Makes > match <. Makes / blink matching /.
Keys <, &, SPC within <>, \" and ' can be electric depending on
(defun sgml-comment-indent ()
- (if (and (looking-at "--")
- (not (and (eq (preceding-char) ?!)
- (eq (char-after (- (point) 2)) ?<))))
- (progn
- (skip-chars-backward " \t")
- (max comment-column (1+ (current-column))))
- 0))
+ (if (looking-at "--") comment-column 0))
"Insert a symbolic character name according to `sgml-char-names'."
(interactive "*")
(if sgml-name-8bit-mode
- (sgml-name-char last-command-char)
+ (sgml-name-char
+ (if (eq (char-charset last-command-char) 'latin-iso8859-1)
+ (+ 128 (- last-command-char (make-char 'latin-iso8859-1)))
+ last-command-char))
(self-insert-command 1)))
(setq sgml-transformation 'upcase)"
(funcall skeleton-transformation
(completing-read "Tag: " sgml-tag-alist))
- ?< (setq v1 (eval str)) |
+ ?< str |
(("") -1 '(undo-boundary) (identity "<")) | ; see comment above
- (("") '(setq v2 (sgml-attributes v1 t)) ?>
- (if (string= "![" v1)
- (prog1 '(("") " [ " _ " ]]")
- (backward-char))
- (if (or (eq v2 t)
- (string-match "^[/!?]" v1))
- ()
- (if (symbolp v2)
- '(("") v2 _ v2 "</" v1 ?>)
- (if (eq (car v2) t)
- (cons '("") (cdr v2))
- (append '(("") (car v2))
- (cdr v2)
- '(resume: (car v2) _ "</" v1 ?>))))))))
+ `(("") '(setq v2 (sgml-attributes ,str t)) ?>
+ (if (string= "![" ,str)
+ (prog1 '(("") " [ " _ " ]]")
+ (backward-char))
+ (if (or (eq v2 t)
+ (string-match "^[/!?]" ,str))
+ ()
+ (if (symbolp v2)
+ ;; We go use `identity' to prevent skeleton from passing
+ ;; `str' through skeleton-transformation a second time.
+ '(("") v2 _ v2 "</" (identity ',str) ?>)
+ (if (eq (car v2) t)
+ (cons '("") (cdr v2))
+ (append '(("") (car v2))
+ (cdr v2)
+ '(resume: (car v2) _ "</" (identity ',str) ?>))))))))
(autoload 'skeleton-read "skeleton")
(interactive "P")
(let ((modified (buffer-modified-p))
(inhibit-read-only t)
+ (inhibit-modification-hooks t)
+ ;; Avoid spurious the `file-locked' checks.
+ (buffer-file-name nil)
;; This is needed in case font lock gets called,
;; since it moves point and might call sgml-point-entered.
(inhibit-point-motion-hooks t)
symbol)
- (save-excursion
- (goto-char (point-min))
- (if (setq sgml-tags-invisible
- (if arg
- (>= (prefix-numeric-value arg) 0)
- (not sgml-tags-invisible)))
- (while (re-search-forward "<\\([!/?A-Za-z][-A-Za-z0-9]*\\)"
- nil t)
- (setq symbol (intern-soft (downcase (match-string 1))))
- (goto-char (match-beginning 0))
- (and (get symbol 'before-string)
- (not (overlays-at (point)))
- (overlay-put (make-overlay (point)
- (match-beginning 1))
- 'category symbol))
- (put-text-property (point)
- (progn (forward-list) (point))
- 'category 'sgml-tag))
- (let ((pos (point)))
- (while (< (setq pos (next-overlay-change pos)) (point-max))
- (delete-overlay (car (overlays-at pos)))))
- (remove-text-properties (point-min) (point-max)
- '(category sgml-tag intangible t))))
- (set-buffer-modified-p modified)
+ (unwind-protect
+ (save-excursion
+ (goto-char (point-min))
+ (if (setq sgml-tags-invisible
+ (if arg
+ (>= (prefix-numeric-value arg) 0)
+ (not sgml-tags-invisible)))
+ (while (re-search-forward "<\\([!/?A-Za-z][-A-Za-z0-9]*\\)"
+ nil t)
+ (setq symbol (intern-soft (downcase (match-string 1))))
+ (goto-char (match-beginning 0))
+ (and (get symbol 'before-string)
+ (not (overlays-at (point)))
+ (overlay-put (make-overlay (point)
+ (match-beginning 1))
+ 'category symbol))
+ (put-text-property (point)
+ (progn (forward-list) (point))
+ 'category 'sgml-tag))
+ (let ((pos (point)))
+ (while (< (setq pos (next-overlay-change pos)) (point-max))
+ (delete-overlay (car (overlays-at pos)))))
+ (remove-text-properties (point-min) (point-max)
+ '(category sgml-tag intangible t))))
+ (restore-buffer-modified-p modified))
(run-hooks 'sgml-tags-invisible-hook)
(message "")))
(let ((inhibit-point-motion-hooks t))
(save-excursion
(message "Invisible tag: %s"
- (buffer-substring
+ ;; Strip properties, otherwise, the text is invisible.
+ (buffer-substring-no-properties
(point)
(if (or (and (> x y)
(not (eq (following-char) ?<)))
(if alist
(insert (skeleton-read '(completing-read "Value: " alist))))
(insert ?\"))))
-
-(provide 'sgml-mode)
\f
+
+;;; HTML mode
+
(defcustom html-mode-hook nil
"Hook run by command `html-mode'.
`text-mode-hook' and `sgml-mode-hook' are run first."
This takes effect when first loading the library.")
(defvar html-mode-map
- (let ((map (nconc (make-sparse-keymap) sgml-mode-map))
+ (let ((map (make-sparse-keymap))
(menu-map (make-sparse-keymap "HTML")))
+ (set-keymap-parent map sgml-mode-map)
(define-key map "\C-c6" 'html-headline-6)
(define-key map "\C-c5" 'html-headline-5)
(define-key map "\C-c4" 'html-headline-4)
;; should code exactly HTML 3 here when that is finished
(defvar html-tag-alist
(let* ((1-7 '(("1") ("2") ("3") ("4") ("5") ("6") ("7")))
- (1-9 '(,@1-7 ("8") ("9")))
+ (1-9 `(,@1-7 ("8") ("9")))
(align '(("align" ("left") ("center") ("right"))))
(valign '(("top") ("middle") ("bottom") ("baseline")))
(rel '(("next") ("previous") ("parent") ("subdocument") ("made")))
("rel" ,@rel)
("rev" ,@rel)
("title")))
- (list '((nil \n ( "List item: "
- "<li>" str \n))))
+ (list '((nil \n ("List item: " "<li>" str \n))))
(cell `(t
- ,align
+ ,@align
("valign" ,@valign)
("colspan" ,@1-9)
("rowspan" ,@1-9)
("dd" t)
("del")
("dfn")
+ ("div")
("dl" (nil \n
( "Term: "
"<dt>" str "<dd>" _ \n)))
("s")
("samp")
("small")
+ ("span")
("strong")
("sub")
("sup")
outline-level (lambda ()
(char-after (1- (match-end 0)))))
(setq imenu-create-index-function 'html-imenu-index)
- (make-local-variable 'imenu-sort-function)
- (setq imenu-sort-function nil) ; sorting the menu defeats the purpose
+ ;; It's for the user to decide if it defeats it or not -stef
+ ;; (make-local-variable 'imenu-sort-function)
+ ;; (setq imenu-sort-function nil) ; sorting the menu defeats the purpose
(run-hooks 'text-mode-hook 'sgml-mode-hook 'html-mode-hook))
\f
(defvar html-imenu-regexp
(and (boundp 'after-save-hook)
(memq 'browse-url-of-buffer after-save-hook))))
(setq after-save-hook (delq 'browse-url-of-buffer after-save-hook))
- (make-local-hook 'after-save-hook)
(add-hook 'after-save-hook 'browse-url-of-buffer nil t))
(message "Autoviewing turned %s."
(if arg "off" "on")))
"")))
\n))
+(provide 'sgml-mode)
+
;;; sgml-mode.el ends here