1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
|
;;; hm--html-indentation.el
;;; v1.00; 9-Feb-1997
;;; Copyright (C) 1997 Heiko Muenkel
;;; email: muenkel@tnt.uni-hannover.de
;;;
;;; 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 1, 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, write to the Free Software
;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;;;
;;;
;;; Description:
;;;
;;; Defines functions for the indentation.
;;;
;;; Installation:
;;;
;;; Put this file in one of your load path directories.
;;;
(defun hm--html-point-between-strings-p (string-1
string-2
&optional boundary)
"Returns non nil, if the current point is between STRING-1 and STRING-2."
(when (and (re-search-backward (concat "\\("
(regexp-quote string-1)
"\\)\\|\\("
(regexp-quote string-2)
"\\)")
boundary
t)
(match-string 1))
(point)))
(defun hm--html-in-comment-p ()
"Checks if the current point is in a comment block.
If this is the case, then the start point of the comment is returned.
Otherwise nil is returned."
(save-excursion
(hm--html-point-between-strings-p comment-start comment-end)))
(defun hm--html-previous-line-start ()
"Returns the start of the previous non blank line."
(save-excursion
(beginning-of-line)
(skip-chars-backward " \t\n")
(beginning-of-line)
(point)))
(defun hm--html-look-at-comment-end-p ()
"T, if the current line starts with the comment end."
(looking-at (regexp-quote comment-end)))
(defun hm--html-column-of-previous-regexp (regexp)
"Returns the column of the start of the previous REGEXP.
It searches backward until the REGEXP is found. If no
REGEXP is found, then it returns 0."
(save-excursion
(if (re-search-backward regexp nil t)
(current-column)
0)))
(defun hm--html-look-at-end-tag-p ()
"Returns the end tag name if the point is at the start of an end tag.
nil is returned otherwise."
(when (looking-at "\\(<[ \t\n]*/[ \t\n]*\\)\\([^ \t\n>]+\\)")
(match-string 2)))
(defun hm--html-previous-line-indentation ()
"Returns the indentation of the previous non blank line."
(save-excursion
(beginning-of-line)
(skip-chars-backward " \t\n")
(back-to-indentation)
(current-column)))
(defun hm--html-in-tag-p ()
"Checks if the current point is in a tag.
If this is the case, then the start point of the tag is returned.
Otherwise nil is returned."
(save-excursion
(let ((start (re-search-backward "\\(<\\)\\|\\(>\\)" nil t)))
(when (match-string 1)
start))))
(defun hm--html-return-beginning-of-line ()
"Returns the beginning of the current line."
(save-excursion
(beginning-of-line)
(point)))
(defun hm--html-return-end-of-line ()
"Returns the end of the current line."
(save-excursion
(end-of-line)
(point)))
(defun hm--html-paramter-column-in-line-after-point (point)
"Returns the column where the second non blank text after POINT starts.
This point must be in the line with POINT otherwise it returns nil."
(save-excursion
(goto-char point)
(when (re-search-forward "<[ \t]*[^ \t]+[ \t]"
(hm--html-return-end-of-line)
t)
(when (looking-at "[^\n]")
(current-column)))))
(defun hm--html-column-of-point (point)
"Returns the column of the POINT."
(save-excursion
(goto-char point)
(current-column)))
(defun hm--html-search-previous-tag-in-current-line ()
"Searches tags from the `(point)' to the beginning of the line.
It returns nil, if there is no tag and the tag name, if there is
a tag. The tag name contains a leading /, if it is an end tag."
(when (re-search-backward ">" (hm--html-return-beginning-of-line) t)
(when (re-search-backward
"\\(<[ \t\n]*\\(/?\\)\\([ \t\n]*[^> \t\n]+\\)[^>]*\\)"
nil
t)
(concat (match-string 2) (match-string 3)))))
(defun hm--html-search-start-tag (tag-name until)
"Searches start tag backwards from the current point until the point UNTIL.
The name of the tag is TAG-NAME. After this function the point is at UNTIL
(then it returns nil) or at the start of the tag, then it returns t."
(if (re-search-backward (concat "\\(<[ \t\n]*\\)\\(/?\\)\\("
tag-name
"\\)\\([^>]*>\\)") until t)
(if (string= "/" (match-string 2))
(progn
(hm--html-search-start-tag tag-name until)
(hm--html-search-start-tag tag-name until))
t)
(goto-char until)
nil))
(defun hm--html-is-one-element-tag-p (tag-name)
"Returns t, if the tag with the tag-name is a one element tag."
(assoc ':hm--html-one-element-tag
(cdr (assoc* (downcase tag-name)
hm--html-tag-name-alist
:test 'string=))))
(defun hm--html-calculate-indent-according-to-previous-tags ()
"Calculate the indent according to the previous tags in this line.
If no tags are found, then nil is returned."
(save-excursion
(let ((tag (hm--html-search-previous-tag-in-current-line)))
(cond ((not tag) nil)
((eq ?/ (elt tag 0)) ; end tag found
(if (hm--html-search-start-tag
(substring tag 1)
(point-min))
(or (hm--html-calculate-indent-according-to-previous-tags)
(progn
(backward-to-indentation 0)
(current-column)))
0)) ; it may be that the current indentation is better here
((hm--html-is-one-element-tag-p tag) ; one element tag
(or (hm--html-calculate-indent-according-to-previous-tags)
(progn
(backward-to-indentation 0)
(current-column))))
(t ; start tag found
(+ (current-column) hm--html-inter-tag-indent))))))
(defun hm--html-calculate-indent ()
"Calculate the indentation of the current line."
(let ((match-point)
(tag))
(save-excursion
(beginning-of-line)
(back-to-indentation)
(cond ((eq (count-lines (point-min) (point)) 0) 0) ; Filestart
((setq match-point (hm--html-in-comment-p)) ; in a comment
(if (>= match-point (hm--html-previous-line-start)) ; 1. line
(if (hm--html-look-at-comment-end-p)
(hm--html-column-of-previous-regexp
(regexp-quote comment-start))
(+ (hm--html-column-of-previous-regexp
(regexp-quote comment-start))
hm--html-comment-indent))
(if (hm--html-look-at-comment-end-p)
(- (hm--html-previous-line-indentation)
hm--html-comment-indent)
(hm--html-previous-line-indentation))))
((setq tag (hm--html-look-at-end-tag-p)) ; look at end tag
(hm--html-search-start-tag tag (point-min))
(current-column))
((looking-at ">")
(hm--html-column-of-previous-regexp "<"))
((setq match-point (hm--html-in-tag-p))
(if (>= match-point (hm--html-previous-line-start)) ; 1. line
(or (hm--html-paramter-column-in-line-after-point match-point)
(+ (hm--html-column-of-point match-point)
hm--html-intra-tag-indent))
(hm--html-previous-line-indentation)))
(t (or (save-excursion ; check previous line
(skip-chars-backward " \t\n")
(hm--html-calculate-indent-according-to-previous-tags))
(hm--html-previous-line-indentation)))
))))
;;; Indentation commands
(defun hm--html-indent-line ()
"Indent the current line line."
(interactive)
(unless hm--html-disable-indentation
(let ((pos (- (point-max) (point))))
(indent-line-to (max 0 (hm--html-calculate-indent)))
(when (> (- (point-max) pos) (point))
(goto-char (- (point-max) pos))))))
;(defun hm--html-indent-region (begin end)
; "Indents the region between BEGIN and END according to the major mode."
; (interactive "d\nm")
; (when (< end begin)
; (let ((a end))
; (setq end begin)
; (setq begin a)))
; (save-excursion
; (goto-char begin)
; (let ((old-point))
; (while (and (<= (point) end)
; (not (eq (point) old-point)))
; (setq old-point (point))
; (indent-according-to-mode)
; (forward-line)
; ))))
(defun hm--html-indent-region (begin end)
"Indents the region between BEGIN and END according to the major mode."
(interactive "d\nm")
(when (< end begin)
(let ((a end))
(setq end begin)
(setq begin a)))
(let ((lines (count-lines begin end)))
(save-excursion
(goto-char begin)
(loop repeat lines
do (indent-according-to-mode)
(forward-line))))
)
(provide 'hm--html-indentation)
|