buf2html-with-number
buf2html
ini2css-file
ini2css-buffer
(provide "buf2html")
(defconstant *buf2html-version* "0.0.0.5"
"buf2html: Version")
(defvar *buf2html-color-context* t
"buf2html: context の解析を行う")
(defvar *buf2html-color-keyword* t
"buf2html: キーワードの解析を行う")
(defvar *buf2html-color-regexp-keyword* t
"buf2html: 正規表現キーワードの解析を行う")
(defvar *buf2html-color-text-attribute* t
"buf2html: text-attribute の解析を行う")
(defvar *buf2html-auto-mode-parameter-string* "Mode: html"
"buf2html: HTML 文書に含める xyzzy 用のモード指定")
(defvar *buf2html-date-format* "%a, %d %b %Y %H:%M:%S %Z"
"buf2html: HTML 文書に含める日付書式")
(defvar *buf2html-time-stamp-start* "Last updated: <"
"buf2html: 日付の前の文字列")
(defvar *buf2html-time-stamp-end* ">"
"buf2html: 日付の後の文字列")
(defvar *buf2html-buffer-tmp* "*buf2html: Tmp*"
"buf2html: 作業バッファ名")
(defvar *buf2html-buffer-css* "*buf2html: CSS*"
"buf2html: スタイルシート出力バッファ名")
(defvar *buf2html-buffer-html* "*buf2html: HTML*"
"buf2html: HTML 文書出力バッファ名")
(defvar *buf2html-convert-half-space* nil
"buf2html: 半角スペースを必ず に変換")
(defvar *buf2html-number-link* t
"buf2html: 行番号出力時、行番号の <A> タグを付加")
(defvar *buf2html-string-encode-alist*
'(("&" . "&")
("<" . "<")
(">" . ">")
( "\"" . """)
)
"buf2html: 変換する文字参照リスト")
(defvar *buf2html-char-code-limit* 128
"buf2html: syntax-table を調べる char-code の限界
全て調べる場合は lisp:char-code-limit を指定")
(defun buf2html-with-number ()
"buf2html: xyzzy の表示に従ってバッファを行番号つきで HTML に変換"
(interactive)
(buf2html t))
(defun buf2html (&optional line-number-p)
"buf2html: xyzzy の表示に従ってバッファを HTML に変換"
(interactive)
(let ((point-max (point-max))
(compiled-color-tag-table (make-hash-table))
all-units keyword-units regexp-keyword-units text-attribute-units
tag-char-units line-feed-units
opitimized-keyword-color-list line-feed-p
(source-buffer (selected-buffer)))
(long-operation
(save-excursion
(buf2html-set-buffer *buf2html-buffer-html*)
(with-output-to-buffer (*buf2html-buffer-html*)
(if *buf2html-color-context*
(setq all-units (buf2html-get-units-context))
(setq all-units (cons nil (cons (point-min) (point-max)))))
(if html-highlight-mode
(setq tag-char-units
(buf2html-get-units-tag-char
(buf2html-get-ranges-if-context all-units '(:tag)))))
(when (and *buf2html-color-context*
*buf2html-color-keyword*
(boundp 'ed::keyword-hash-table))
(setq keyword-units
(buf2html-get-units-keyword
(buf2html-range-concatenate
(if html-highlight-mode
(buf2html-get-ranges-if-context all-units '(:tag))
(buf2html-get-ranges-if-not-context all-units '(:string :comment))))))
(buf2html-add-compiled-color-tag-hash-table
compiled-color-tag-table (mapcar #'cdar keyword-units))
(message "Merge keyword range.")
(setq all-units (buf2html-unit-cover all-units keyword-units))
(when (not (zerop (logand (get-syntax-option (syntax-table))
*syntax-option-c-preprocessor*)))
(setq keyword-units
(buf2html-get-units-keyword-c-preprocessor
(buf2html-range-concatenate
(if html-highlight-mode
(buf2html-get-ranges-if-context all-units '(:tag))
(buf2html-get-ranges-if-not-context all-units '(:string :comment))))))
(buf2html-add-compiled-color-tag-hash-table
compiled-color-tag-table (mapcar #'cdar keyword-units))
(message "Merge c preprocessor keyword range.")
(setq all-units (buf2html-unit-cover all-units keyword-units))
)
)
(when (and *buf2html-color-context*
*buf2html-color-regexp-keyword*
(boundp 'ed::regexp-keyword-list))
(buf2html-add-compiled-color-tag-hash-table
compiled-color-tag-table
(buf2html-make-regexp-keyword-color-list ed::regexp-keyword-list))
(let (regexp colors compiled-context begin end (i 0)
(regexp-keyword-list-length (length ed::regexp-keyword-list)))
(dolist (regexp-keyword ed::regexp-keyword-list)
(incf i)
(message "Parse regexp keyword: ~D/~D" i regexp-keyword-list-length)
(setq compiled-context (caddr regexp-keyword))
(setq regexp-keyword-units
(buf2html-get-units-regexp-keyword
(buf2html-range-concatenate
(buf2html-get-ranges-if-context
all-units
(buf2html-decode-compiled-context compiled-context)))
regexp-keyword))
(message "Merge regexp keyword range: ~D/~D"
i regexp-keyword-list-length)
(setq all-units
(buf2html-unit-cover all-units regexp-keyword-units))))
)
(when html-highlight-mode
(message "Merge tag-char range.")
(setq all-units (buf2html-unit-cover all-units tag-char-units)))
(setq all-units (buf2html-unit-concatenate all-units))
(setq line-feed-p line-number-p)
(when line-feed-p
(setq line-feed-units (buf2html-get-units-line-feed))
(setq all-units (buf2html-unit-cover all-units line-feed-units)))
(when *buf2html-color-text-attribute*
(message "Parse text attribute.")
(setq text-attribute-units (buf2html-get-units-text-attribute)))
(buf2html-print-header line-number-p)
(buf2html-print-body all-units compiled-color-tag-table
text-attribute-units line-number-p)
(buf2html-print-footer line-number-p)
(message "Output HTML: done."))
(set-buffer-modified-p nil *buf2html-buffer-html*))
(pop-to-buffer *buf2html-buffer-html*)
(set-buffer-fileio-encoding (buffer-fileio-encoding source-buffer))
(set-buffer-eol-code (buffer-eol-code source-buffer))
(html-mode)
)))
(defun buf2html-get-units-context (&key begin end nomsg)
"buf2html: context の範囲のリストを作成"
(let ((point-max (point-max)) rate pre-rate
all-units context pre-context from to range)
(save-excursion
(unless begin
(setq begin (point-min)))
(unless end
(setq end (point-max)))
(setq from begin)
(goto-char from)
(if (= begin 0)
(setq context nil)
(setq context (parse-point-syntax (1- (point)))))
(setq rate -1)
(while (and (<= (point) end) (not (eobp)))
(setq pre-context context)
(setq context (parse-point-syntax (point)))
(unless nomsg
(setq pre-rate rate)
(setq rate (floor (* 100 (/ (point) point-max))))
(if (/= pre-rate rate)
(message "Parse context: ~2D%" rate)))
(unless (eq pre-context context)
(do-events)
(cond
((eq pre-context nil)
(setq to (1- (point))))
((eq context nil)
(setq to (point)))
((eq pre-context :tag)
(setq to (1- (point))))
((and (eq context :tag)
(eq pre-context :string))
(setq to (1+ (point))))
(t
(setq to (point))))
(setq range (cons from to))
(when (< from to)
(push (cons (cons pre-context nil) range) all-units)
(setq from to))
)
(forward-char))
(setq range (cons from end))
(if (< from end)
(push (cons (cons pre-context nil) range) all-units)))
(unless nomsg
(message "Parse context: done."))
(nreverse all-units)))
(defun buf2html-get-units-line-feed ()
"buf2html: 改行文字の範囲(位置)のリストを作成"
(let (line-feed-units point)
(goto-char (point-min))
(while (scan-buffer "\n" :tail t)
(setq point (1- (point)))
(push (cons (cons :buf2html-line-feed nil) (cons point (1+ point)))
line-feed-units))
(nreverse line-feed-units)))
(defun buf2html-get-units-tag-char (ranges)
"buf2html: タグの開始、終了文字の範囲(位置)のリストを作成"
(let (tag-char-units from to c)
(dolist (range ranges)
(setq from (car range))
(setq to (cdr range))
(when (< from to)
(setq c (char (buffer-substring from (1+ from)) 0))
(if (or (syntax-open-tag-p c) (syntax-close-tag-p c))
(push (cons (cons :tag nil) (cons from (1+ from))) tag-char-units))
(when (< from (1- to))
(setq c (char (buffer-substring (1- to) to) 0))
(if (or (syntax-open-tag-p c) (syntax-close-tag-p c))
(push (cons (cons :tag nil) (cons (1- to) to)) tag-char-units)))))
(nreverse tag-char-units)))
(defun buf2html-get-units-text-attribute ()
"buf2html: text-attribute の範囲のリストを作成"
(let (text-attribute-units btag etag range key value)
(dolist (text-attributes (list-text-attributes (point-min) (point-max)))
(setq range (cons (car text-attributes) (cadr text-attributes)))
(setq text-attributes (cdddr text-attributes))
(setq btag "")
(setq etag "")
(while text-attributes
(setq key (car text-attributes))
(setq value (cadr text-attributes))
(setq text-attributes (cddr text-attributes))
(case key
(:foreground
(setq btag (format nil "~A<SPAN class=\"fg~D\">" btag value))
(setq etag (format nil "</SPAN>~A" etag)))
(:background
(setq btag (format nil "~A<SPAN class=\"bg~D\">" btag value))
(setq etag (format nil "</SPAN>~A" etag)))
(:bold
(when value
(setq btag (concat btag "<SPAN class=\"bold\">"))
(setq etag (concat "</SPAN>" etag))))
(:underline
(when value
(setq btag (concat btag "<SPAN class=\"underline\">"))
(setq etag (concat "</SPAN>" etag))))
(:strike-out
(when value
(setq btag (concat btag "<SPAN class=\"strike-out\">"))
(setq etag (concat "</SPAN>" etag))))))
(push (cons (cons :buf2html-text-attribute (cons btag etag)) range)
text-attribute-units))
(nreverse text-attribute-units)))
(defun buf2html-get-units-keyword (ranges)
"buf2html: キーワードの範囲のリストを作成"
(let ((point-max (point-max)) keyword-units from to regexp compiled-color
str begin end)
(dolist (range ranges)
(setq from (car range))
(setq to (cdr range))
(goto-char from)
(message "Parse keyword: ~2D%" (floor (* 100 (/ from point-max))))
(setq regexp (compile-regexp "\\(\\s@\\|\\s{\\|\\s\\\\)?\\(\\sw\\|\\s_\\)+"))
(while (scan-buffer regexp :limit to)
(setq str (match-string 0))
(setq begin (match-beginning 0))
(setq end (match-end 0))
(when (syntax-symbol-prefix-p (char str 0))
(setq str (substring 1 str))
(setq begin (1- begin)))
(multiple-value-bind (compiled-color init)
(gethash str ed::keyword-hash-table)
(when init
(push (cons (cons :buf2html-keyword compiled-color)
(cons begin end)) keyword-units)))
(goto-char end)))
(message "Parse keyword: done.")
(nreverse keyword-units)))
(defun buf2html-get-units-keyword-c-preprocessor (ranges)
"buf2html: C preprocessor 用キーワードの範囲のリストを作成"
(let ((point-max (point-max)) keyword-units from to regexp compiled-color
str begin end)
(dolist (range ranges)
(setq from (car range))
(setq to (cdr range))
(goto-char from)
(message "Parse c preprocessor keyword: ~2D%" (floor (* 100 (/ from point-max))))
(setq regexp (compile-regexp "#[ \t]*\\(\\(\\sw\\|\\s_\\)+\\)"))
(while (scan-buffer regexp :limit to)
(setq str (concat "#" (match-string 1)))
(setq begin (match-beginning 0))
(setq end (match-end 0))
(multiple-value-bind (compiled-color init)
(gethash str ed::keyword-hash-table)
(when init
(push (cons (cons :buf2html-keyword compiled-color)
(cons begin end)) keyword-units)))
(goto-char end)))
(message "Parse c preprocessor keyword: done.")
(nreverse keyword-units)))
(defun buf2html-get-units-regexp-keyword (ranges regexp-keyword)
"buf2html: 正規表現キーワードの範囲のリストを作成"
(let ((regexp (car regexp-keyword))
(colors (cadr regexp-keyword))
(compiled-context (caddr regexp-keyword))
(begin (cadddr regexp-keyword))
(end (car (cddddr regexp-keyword)))
regexp-keyword-units from to
(point-max (point-max))
whole-range enable-range regexp-keyword-group-units
group-number group-range compiled-color)
(dolist (range ranges)
(setq from (car range))
(setq to (cdr range))
(goto-char from)
(while (scan-buffer regexp :tail t :limit to)
(setq whole-range (cons (match-beginning 0) (match-end 0)))
(setq enable-range
(cons (if (minusp begin) (match-end (* -1 begin)) (match-beginning begin))
(if (minusp end) (match-beginning (* -1 end)) (match-end end))))
(setq whole-range enable-range)
(setq regexp-keyword-group-units
(list (cons (cons :buf2html-regexp-keyword-group nil)
(copy-list whole-range))))
(cond
((not (consp colors))
(setq compiled-color colors)
(setq regexp-keyword-group-units
(buf2html-unit-cover
regexp-keyword-group-units
(list (cons (cons :buf2html-regexp-keyword-group compiled-color)
enable-range)))))
(t
(dolist (color (sort colors #'< :key #'car))
(setq group-number (car color))
(setq compiled-color (cdr color))
(setq group-range (cons (match-beginning group-number)
(match-end group-number)))
(when (and compiled-color
(buf2html-in-range-p group-range enable-range))
(setq regexp-keyword-group-units
(buf2html-unit-cover
regexp-keyword-group-units
(list (cons (cons :buf2html-regexp-keyword-group compiled-color)
group-range))))))))
(push (cons (cons :buf2html-regexp-keyword regexp-keyword-group-units) whole-range)
regexp-keyword-units)))
(nreverse regexp-keyword-units)))
(defun buf2html-make-regexp-keyword-color-list (regexp-keyword-list)
"buf2html: regexp-keyword-list から color のリストを作成"
(let (compiled-color-list)
(when regexp-keyword-list
(pushnew nil compiled-color-list :test 'eql)
(dolist (compiled-colors (mapcar #'cadr regexp-keyword-list))
(cond
((consp compiled-colors)
(dolist (compiled-color (mapcar #'cdr compiled-colors))
(pushnew compiled-color compiled-color-list :test 'eql)))
((numberp compiled-colors)
(pushnew compiled-colors compiled-color-list :test 'eql))
(t
(pushnew compiled-colors compiled-color-list :test 'eql)))))
compiled-color-list))
(defun buf2html-add-compiled-color-tag-hash-table (hash-table compiled-colors)
"buf2html: compiled-colors に対応する HTML タグを hash-table に登録"
(when (hash-table-p hash-table)
(dolist (compiled-color compiled-colors)
(multiple-value-bind (value init)
(gethash compiled-color hash-table)
(unless init
(setf (gethash compiled-color hash-table)
(buf2html-make-compiled-color-tag compiled-color)))))
hash-table))
(defun buf2html-make-compiled-color-tag (compiled-color)
"buf2html: compiled-color に対応する HTML タグを作成"
(unless (numberp compiled-color)
(return-from buf2html-make-compiled-color-tag (cons "" "")))
(let ((fg-bg-p (= (logand compiled-color #x1) #x1))
(line-p (= (logand compiled-color #x2) #x2))
(bold-p (= (logand compiled-color #x200000) #x200000))
(underline-p (= (logand compiled-color #x800000) #x800000))
(strike-out-p (= (logand compiled-color #x1000000) #x1000000))
(color (logand compiled-color (lognot #x1)
(lognot #x2) (lognot #x200000) (lognot #x800000) (lognot #x1000000)))
(btag "") (etag ""))
(cond
(fg-bg-p
(setq btag (format nil "<SPAN class=\"fg~D bg~D\">"
(floor (logand color #x1f00) #x200)
(floor (logand color #x1f0000) #x20000)))
(setq etag "</SPAN>"))
(t
(cond
((= color 0)
(setq btag "" etag ""))
((= color (gethash #\0 ed::*keyword-translate-hash-table*))
(setq btag "<SPAN class=\"keyword1\">" etag "</SPAN>"))
((= color (gethash #\1 ed::*keyword-translate-hash-table*))
(setq btag "<SPAN class=\"keyword2\">" etag "</SPAN>"))
((= color (gethash #\2 ed::*keyword-translate-hash-table*))
(setq btag "<SPAN class=\"keyword3\">" etag "</SPAN>"))
((= color (gethash #\3 ed::*keyword-translate-hash-table*))
(setq btag "<SPAN class=\"keyword1inverse\">" etag "</SPAN>"))
((= color (gethash #\4 ed::*keyword-translate-hash-table*))
(setq btag "<SPAN class=\"keyword2inverse\">" etag "</SPAN>"))
((= color (gethash #\5 ed::*keyword-translate-hash-table*))
(setq btag "<SPAN class=\"keyword3inverse\">" etag "</SPAN>"))
((= color (gethash #\S ed::*keyword-translate-hash-table*))
(setq btag "<SPAN class=\"string\">" etag "</SPAN>"))
((= color (gethash #\T ed::*keyword-translate-hash-table*))
(setq btag "<SPAN class=\"tag\">" etag "</SPAN>"))
((= color (gethash #\C ed::*keyword-translate-hash-table*))
(setq btag "<SPAN class=\"comment\">" etag "</SPAN>")))))
(when bold-p
(setq btag (concat btag "<SPAN class=\"bold\">"))
(setq etag (concat "</SPAN>" etag)))
(when underline-p
(setq btag (concat btag "<SPAN class=\"underline\">"))
(setq etag (concat "</SPAN>" etag)))