Sponsored Link
buf2html-with-number
buf2html
ini2css-file
ini2css-buffer

  1. ;;; -*- Mode: Lisp -*-
  2. ;;;
  3. ;;; buf2html.l --- convert text of buffer to HTML
  4. ;;; Copyright (C) 2001 OHKUBO Hiroshi
  5. ;;; Author: OHKUBO Hiroshi <konata_o@hotmail.com>
  6. ;;; Version: 0.0.0.5
  7. ;;; Time-stamp: <2001/12/15 11:47:34 +0900>
  8. ;;; Xyzzy: 0.2.2.220
  9. ;;; buf2html:
  10. ;;;
  11. ;;;     なるべくバッファの表示を再現するような HTML を生成します。
  12. ;;;     キーワード、正規表現キーワード、text-attribute に対応していますが、
  13. ;;;     一行反転表示には対応していません。
  14. ;;;
  15. ;;;     勘で書いている部分があるのでおかしな変換があると思います。
  16. ;;;     気がついた点を知らせて頂けるとありがたいです。
  17. ;;;
  18. ;;; Install:
  19. ;;;
  20. ;;;     1. 解凍して buf2html.l を、~/site-lispにコピーします。
  21. ;;;
  22. ;;;     2. 必要ならばバイトコンパイルします。
  23. ;;;
  24. ;;;             M-x byte-compile-file
  25. ;;;
  26. ;;;     3. .xyzzy または siteinit.l に以下のコードを追加します。
  27. ;;;
  28. ;;;             (load-library "buf2html")
  29. ;;;
  30. ;;;     4. 上記の設定を反映させるために、xyzzyを再起動します。
  31. ;;;
  32. ;;; Usage:
  33. ;;;
  34. ;;;     1. M-x ini2css-file または M-x ini2css-buffer で xyzzy の
  35. ;;;        INI ファイル (標準では xyzzy.ini) からスタイルシートを生成し、
  36. ;;;        xyzzy.css というファイル名で保存。
  37. ;;;
  38. ;;;     2. 変換元のバッファで M-x buf2html または M-x buf2html-with-number し、
  39. ;;;        HTML の出力されたバッファを xyzzy.css を保存したフォルダに保存。
  40. ;;;
  41. ;;; Changes:
  42. ;;;     [Version 0.0.0.5]
  43. ;;;     Sat, 15 Dec 2001 11:19:03 +0900
  44. ;;;             ・ML で亀井さんに教えていただいたキーワード検索の方法に変更。
  45. ;;;               ・タグをハイライトするかどうかを html-highlight-mode の値で判定
  46. ;;;               ・syntax-symbol-prefix-p が non-nil の場合のハイライト
  47. ;;;               ・syntax-table の option に *syntax-option-c-preprocessor* が
  48. ;;;                 指定されていた場合の動作
  49. ;;;               上記 3 点について xyzzy と同様の動作になったと思います。
  50. ;;;
  51. ;;;     [Version 0.0.0.4]
  52. ;;;     Fri, 14 Dec 2001 18:25:03 +0900
  53. ;;;             ・tag のあるモードかどうかを syntax-table で判断するように。
  54. ;;;
  55. ;;;     Tue, 11 Dec 2001 10:30:34 +0900
  56. ;;;             ・Memo 修正。
  57. ;;;             ・<TITLE></TITLE> の間では半角スペースを &nbsp; に変換
  58. ;;;               しないように変更。
  59. ;;;
  60. ;;;     [Version 0.0.0.3]
  61. ;;;     Mon, 10 Dec 2001 17:58:20 +0900
  62. ;;;             ・context をパースする際の message の位置を変更。
  63. ;;;             ・行番号付き出力 buf2html-with-number 追加。
  64. ;;;             ・HTML 出力後バッファの modify flag を nil に。
  65. ;;;             ・その他修正。
  66. ;;;
  67. ;;;     [Version 0.0.0.2]
  68. ;;;     Fri, 07 Dec 2001 07:40:23 +0900
  69. ;;;             ・message の位置を修正。
  70. ;;;             ・bgr2rgb を buf2html-bgr2rgb に名称変更。
  71. ;;;             ・余分な HTML タグの削減。
  72. ;;;             ・キーワードが大文字小文字を区別するかの判定。
  73. ;;;             ・tag 文字 (syntax-open-tag-p, syntax-close-tag-p) を
  74. ;;;               キーワードより優先させるように修正。
  75. ;;;             ・その他修正。
  76. ;;;
  77. ;;;     [Version 0.0.0.1]
  78. ;;;     Fri, 07 Dec 2001 02:37:41 +0900
  79. ;;;             ・門田さんの mode2htm.l, ini2css.l を参考にして初版作成。
  80. ;;;
  81. ;;; Todo:
  82. ;;;     ・できれば行反転表示への対応
  83. ;;;     ・制御文字の表示
  84. ;;;     ・改行、タブ、EOF、全角スペース、半角スペースの表示
  85. ;;;     ・行間への対応
  86. ;;;     ・固定幅 bold 表示
  87. ;;;     ・lang や charset へのまともな対応
  88. ;;;     ・余分な HTML タグの削減
  89. ;;;     ・TAB 文字への対処
  90. ;;;     ・速度改善
  91. ;;;
  92. ;;; Memo:
  93. ;;;     ・正規表現キーワードよりもキーワードの方が優先される。
  94. ;;;       色が重ならないだけでなく、キーワード自体が重ならない。
  95. ;;;     ・キーワードの色よりもタグの開始・終了の色の方が優先される。
  96. ;;;       ただしタグの開始・終了文字の部分はキーワード構成部分となり得る。
  97. ;;;     ・html-highlight-mode が non-nil の場合は :tag の中でしか context は
  98. ;;;       切り替わらない。
  99. ;;;     ・context が nil 中での :string は 終了の " 自体までだが、
  100. ;;;       context が :tag 中での :string は終了の " の前まで。
  101. ;;;       "abcdefghijklmn"    "abcdefghijklmn"
  102. ;;;        ^^^^^^^^^^^^^^^ と  ^^^^^^^^^^^^^^ の違い。
  103. ;;;     ・正規表現キーワードは指定されたコンテキスト内であれば、隣接した
  104. ;;;       コンテキストをまたいでもよい。
  105. ;;;       単一のコンテキスト内でキーワードが完結する必要はない。
  106. ;;;       ("abc \"\" def" t (:color 1 0 :underline) (:string))
  107. ;;;       は 2 つの :string コンテキストによる「"abc "" def"」 をキーワードと
  108. ;;;       認識する。
  109. ;;;     ・正規表現キーワードにて個々の色設定がなされていても、begin end により除外
  110. ;;;       されている場合色はつかない。
  111. ;;;     ・("123\\(45\\(67\\)89\\)0" nil ((1 . (:color 1)) (2 . (:color 2))) t 1 1)
  112. ;;;       では、(:color 1) の色で 456789 に色がつくのではなく、67 には
  113. ;;;       (:color 2) の色で色がつく。
  114. ;;;       最後の begin end は色をつける point の範囲を group 番号で指定している。
  115. ;;;     ・text-attribute に (:underline nil) 等を指定しても、
  116. ;;;       (正規表現)キーワードで underline 等が指定されている場合は
  117. ;;;       それらは無効化されない。
  118. ;;;     ・color の nil と (:color nil) は異なる。
  119. ;;;     ・color に nil を指定するとその色指定は無視されるよう。
  120. ;;;
  121. ;;;
  122. ;;;     ・html-highlight-mode が non-nil の場合は基本的にキーワードは
  123. ;;;       タグ内部のみだが、0.2.2.207 で追加された記述方法で
  124. ;;;       nil context の中にもキーワード指定ができる。
  125. ;;;       keyword-hash-table をよくみていないがもしかしたら、キーワードファイル
  126. ;;;       自体を読んで parse しなければならない?
  127. ;;;     ・ed::regexp-keyword-list は必ず (compile-regexp-keyword-list) されている?
  128. ;;;     ・「正規表現のキーワード色分けの、グループごとの色指定」における
  129. ;;;       「colorがnilなら、同一範囲にマッチした若いグループ番号の色。tなら元の色。」
  130. ;;;       は具体的にどういうことなのか。「元の色」とは何か。
  131. ;;;       「元の色」は「地の色」(「文字色」「背景色」)であっているのか。
  132. ;;;       context は考慮する必要はないのか。
  133. ;;;
  134. ;;; Data structure:
  135. ;;;
  136. ;;;     <UNITS>  : (<UNIT>*)
  137. ;;;     <UNIT>   : (<TYPE> . <RANGE>)
  138. ;;;     <RANGES> : (<RANGE>*)
  139. ;;;     <RANGE>  : (<FROM> . <TO>)
  140. ;;;     <TYPE>   : (<keyword> . <INFO>)
  141. ;;;     <FROM>   : <POINT>
  142. ;;;     <TO>     : <POINT>
  143. ;;;     <POINT>  : <number>
  144. ;;;
  145. ;;;     <number> : /[0-9]+/
  146. ;;;     <keyword>: nil
  147. ;;;              | :string
  148. ;;;              | :comment
  149. ;;;              | :tag
  150. ;;;              | :buf2html-keyword
  151. ;;;              | :buf2html-regexp-keyword
  152. ;;;              | :buf2html-regexp-keyword-group
  153. ;;;              | :buf2html-text-attribute
  154. ;;;              | :buf2html-line-feed
  155. ;;;
  156. ;;;     <INFO>   : <TYPE> の <keyword> 毎に色々。
  157. ;;;
  158. ;;;       <keyword> == nil | :string | :comment | :tag
  159. ;;;              : nil
  160. ;;;
  161. ;;;       <keyword> == :buf2html-keyword
  162. ;;;              : compiled-color
  163. ;;;
  164. ;;;       <keyword> == :buf2html-regexp-keyword
  165. ;;;              : regexp-keyword-group-units
  166. ;;;
  167. ;;;       <keyword> == :buf2html-regexp-keyword-group
  168. ;;;              : compiled-color
  169. ;;;
  170. ;;;       <keyword> == :buf2html-text-attribute
  171. ;;;              : (btag . etag)
  172. ;;;
  173. ;;;       <keyword> == :buf2html-line-feed
  174. ;;;              : nil
  175. ;;;
  176. ;;;
  177. ;;;     ・<UNITS> を構成する <UNIT> は (<TYPE> . (<FROM> . <TO>)) の
  178. ;;;       <FROM> で昇順ソートされていなければならない。
  179. ;;;
  180. ;;;     ・<TO> は実際には範囲に含まれない。
  181. ;;;       <FROM>, <TO> は (buffer-substring <FROM> <TO>) となる値。
  182. ;;;
  183. ;;; Code:
  184. (provide "buf2html")
  185. (defconstant *buf2html-version* "0.0.0.5"
  186.   "buf2html: Version")
  187. (defvar *buf2html-color-context* t
  188.   "buf2html: context の解析を行う")
  189. (defvar *buf2html-color-keyword* t
  190.   "buf2html: キーワードの解析を行う")
  191. (defvar *buf2html-color-regexp-keyword* t
  192.   "buf2html: 正規表現キーワードの解析を行う")
  193. (defvar *buf2html-color-text-attribute* t
  194.   "buf2html: text-attribute の解析を行う")
  195. (defvar *buf2html-auto-mode-parameter-string* "Mode: html"
  196.   "buf2html: HTML 文書に含める xyzzy 用のモード指定")
  197. (defvar *buf2html-date-format* "%a, %d %b %Y %H:%M:%S %Z"
  198.   "buf2html: HTML 文書に含める日付書式")
  199. (defvar *buf2html-time-stamp-start* "Last updated: <"
  200.   "buf2html: 日付の前の文字列")
  201. (defvar *buf2html-time-stamp-end* ">"
  202.   "buf2html: 日付の後の文字列")
  203. (defvar *buf2html-buffer-tmp* "*buf2html: Tmp*"
  204.   "buf2html: 作業バッファ名")
  205. (defvar *buf2html-buffer-css* "*buf2html: CSS*"
  206.   "buf2html: スタイルシート出力バッファ名")
  207. (defvar *buf2html-buffer-html* "*buf2html: HTML*"
  208.   "buf2html: HTML 文書出力バッファ名")
  209. (defvar *buf2html-convert-half-space* nil
  210.   "buf2html: 半角スペースを必ず &nbsp; に変換")
  211. (defvar *buf2html-number-link* t
  212.   "buf2html: 行番号出力時、行番号の <A> タグを付加")
  213. (defvar *buf2html-string-encode-alist*
  214.   '(("&" . "&amp;")
  215.     ("<" . "&lt;")
  216.     (">" . "&gt;")
  217.     ( "\"" . "&quot;")
  218. ;   " " は状況に応じて変換
  219. ;   (" " . "&nbsp;")
  220.     )
  221.   "buf2html: 変換する文字参照リスト")
  222. (defvar *buf2html-char-code-limit* 128
  223.   "buf2html: syntax-table を調べる char-code の限界
  224. 全て調べる場合は lisp:char-code-limit を指定")
  225. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  226. ;; buf2html-with-number
  227. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  228. (defun buf2html-with-number ()
  229.   "buf2html: xyzzy の表示に従ってバッファを行番号つきで HTML に変換"
  230.   (interactive)
  231.   (buf2html t))
  232. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  233. ;; buf2html
  234. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  235. (defun buf2html (&optional line-number-p)
  236.   "buf2html: xyzzy の表示に従ってバッファを HTML に変換"
  237.   (interactive)
  238.   (let ((point-max (point-max))
  239.         (compiled-color-tag-table (make-hash-table))
  240.         all-units keyword-units regexp-keyword-units text-attribute-units
  241.         tag-char-units line-feed-units
  242.         opitimized-keyword-color-list line-feed-p
  243.         (source-buffer (selected-buffer)))
  244.     (long-operation
  245.       (save-excursion
  246.         (buf2html-set-buffer *buf2html-buffer-html*)
  247.         (with-output-to-buffer (*buf2html-buffer-html*)
  248.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  249.           ;; context
  250.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  251.           (if *buf2html-color-context*
  252.               (setq all-units (buf2html-get-units-context))
  253.             (setq all-units (cons nil (cons (point-min) (point-max)))))
  254.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  255.           ;; tag-char
  256.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  257.           (if html-highlight-mode
  258.               (setq tag-char-units
  259.                     (buf2html-get-units-tag-char
  260.                      (buf2html-get-ranges-if-context all-units '(:tag)))))
  261.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  262.           ;; keyword
  263.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  264.           (when (and *buf2html-color-context*
  265.                      *buf2html-color-keyword*
  266.                      (boundp 'ed::keyword-hash-table))
  267.             (setq keyword-units
  268.                   (buf2html-get-units-keyword
  269.                    (buf2html-range-concatenate
  270.                     (if html-highlight-mode
  271.                         (buf2html-get-ranges-if-context all-units '(:tag))
  272.                       (buf2html-get-ranges-if-not-context all-units '(:string :comment))))))
  273.             ;; keyword の compiled-color の値(数)にあった HTML タグの登録
  274.             (buf2html-add-compiled-color-tag-hash-table
  275.              compiled-color-tag-table (mapcar #'cdar keyword-units))
  276.             ;; keyword の範囲を適用
  277.             (message "Merge keyword range.")
  278.             (setq all-units (buf2html-unit-cover all-units keyword-units))
  279.             ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  280.             ;; c-preprocessor 用の特殊キーワード検索
  281.             (when (not (zerop (logand (get-syntax-option (syntax-table))
  282.                                       *syntax-option-c-preprocessor*)))
  283.               (setq keyword-units
  284.                     (buf2html-get-units-keyword-c-preprocessor
  285.                      (buf2html-range-concatenate
  286.                       (if html-highlight-mode
  287.                           (buf2html-get-ranges-if-context all-units '(:tag))
  288.                         (buf2html-get-ranges-if-not-context all-units '(:string :comment))))))
  289.               ;; keyword の compiled-color の値(数)にあった HTML タグの登録
  290.               (buf2html-add-compiled-color-tag-hash-table
  291.                compiled-color-tag-table (mapcar #'cdar keyword-units))
  292.               ;; keyword の範囲を適用
  293.               (message "Merge c preprocessor keyword range.")
  294.               (setq all-units (buf2html-unit-cover all-units keyword-units))
  295.               )
  296.             )
  297.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  298.           ;; regexp-keyword
  299.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  300.           (when (and *buf2html-color-context*
  301.                      *buf2html-color-regexp-keyword*
  302.                      (boundp 'ed::regexp-keyword-list))
  303.             ;; 正規表現キーワードの compiled-color の値にあった HTML タグの登録
  304.             (buf2html-add-compiled-color-tag-hash-table
  305.              compiled-color-tag-table
  306.              (buf2html-make-regexp-keyword-color-list ed::regexp-keyword-list))
  307.             (let (regexp colors compiled-context begin end (i 0)
  308.                   (regexp-keyword-list-length (length ed::regexp-keyword-list)))
  309.               (dolist (regexp-keyword ed::regexp-keyword-list)
  310.                 (incf i)
  311.                 (message "Parse regexp keyword: ~D/~D" i regexp-keyword-list-length)
  312. ;               (setq regexp (car regexp-keyword))
  313. ;               (setq colors (cadr regexp-keyword))
  314.                 (setq compiled-context (caddr regexp-keyword))
  315. ;               (setq begin (cadddr regexp-keyword))
  316. ;               (setq end (car (cddddr regexp-keyword)))
  317.                 (setq regexp-keyword-units
  318.                       (buf2html-get-units-regexp-keyword
  319.                        (buf2html-range-concatenate
  320.                         (buf2html-get-ranges-if-context
  321.                          all-units
  322.                          (buf2html-decode-compiled-context compiled-context)))
  323.                        regexp-keyword))
  324.                 ;; regexp-keyword の範囲を適用
  325.                 (message "Merge regexp keyword range: ~D/~D"
  326.                          i regexp-keyword-list-length)
  327.                 (setq all-units
  328.                       (buf2html-unit-cover all-units regexp-keyword-units))))
  329.             )
  330.           
  331.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  332.           ;; tag-char をキーワードよりも優先
  333.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  334.           (when html-highlight-mode
  335.             (message "Merge tag-char range.")
  336.             (setq all-units (buf2html-unit-cover all-units tag-char-units)))
  337.           
  338.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  339.           ;; 最適化
  340.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  341.           (setq all-units (buf2html-unit-concatenate all-units))
  342.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  343.           ;; 行分割 (line-feed)
  344.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  345.           (setq line-feed-p line-number-p)
  346.           (when line-feed-p
  347.             (setq line-feed-units (buf2html-get-units-line-feed))
  348.             (setq all-units (buf2html-unit-cover all-units line-feed-units)))
  349.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  350.           ;; text-attribute
  351.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  352.           (when *buf2html-color-text-attribute*
  353.             (message "Parse text attribute.")
  354.             (setq text-attribute-units (buf2html-get-units-text-attribute)))
  355.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  356.           ;; 出力
  357.           ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  358.           (buf2html-print-header line-number-p)
  359.           (buf2html-print-body all-units compiled-color-tag-table
  360.                                text-attribute-units line-number-p)
  361.           (buf2html-print-footer line-number-p)
  362.           (message "Output HTML: done."))
  363.         (set-buffer-modified-p nil *buf2html-buffer-html*))
  364.       (pop-to-buffer *buf2html-buffer-html*)
  365.       (set-buffer-fileio-encoding (buffer-fileio-encoding source-buffer))
  366.       (set-buffer-eol-code (buffer-eol-code source-buffer))
  367.       (html-mode)
  368.       )))
  369. (defun buf2html-get-units-context (&key begin end nomsg)
  370.   "buf2html: context の範囲のリストを作成"
  371.   (let ((point-max (point-max)) rate pre-rate
  372.         all-units context pre-context from to range)
  373.     (save-excursion
  374.       (unless begin
  375.         (setq begin (point-min)))
  376.       (unless end
  377.         (setq end (point-max)))
  378.       (setq from begin)
  379.       (goto-char from)
  380.       (if (= begin 0)
  381.           (setq context nil)
  382.         (setq context (parse-point-syntax (1- (point)))))
  383.       (setq rate -1)
  384.       (while (and (<= (point) end) (not (eobp)))
  385.         (setq pre-context context)
  386.         (setq context (parse-point-syntax (point)))
  387.         (unless nomsg
  388.           (setq pre-rate rate)
  389.           (setq rate (floor (* 100 (/ (pointpoint-max))))
  390.           (if (/= pre-rate rate)
  391.               (message "Parse context: ~2D%" rate)))
  392.         (unless (eq pre-context context)
  393.           (do-events)
  394. ;         (unless nomsg
  395. ;           (message "Parse context: ~2D%" (floor (* 100 (/ (point) point-max)))))
  396.           ;; とりあえず 0.2.2.219 での context を元に適当にやってみる
  397.           (cond
  398.            ; nil から context が切り替わる際は一つ前から
  399.            ((eq pre-context nil)
  400.             (setq to (1- (point))))
  401.            ; nil に切り替わる際はそのまま
  402.            ((eq context nil)
  403.             (setq to (point)))
  404.            ;; :tag については html(+)-mode でしか試していないのであってないかも
  405.            ((eq pre-context :tag)
  406.             (setq to (1- (point))))
  407.            ((and (eq context :tag)
  408.                  (eq pre-context :string))
  409.             (setq to (1+ (point))))
  410.            (t
  411.             (setq to (point))))
  412.           (setq range (cons from to))
  413.           (when (< from to)
  414.             (push (cons (cons pre-context nil) range) all-units)
  415.             (setq from to))
  416. #|
  417.           ; こんな感じのことをすると少しは早くなるかも。でもバグの元かも。
  418.           (cond
  419.            ((eq context :string)
  420.             (skip-syntax-spec-forward "^\"")
  421.             (backward-char)))
  422. |#
  423.           )
  424.         (forward-char))
  425.       (setq range (cons from end))
  426.       (if (< from end)
  427.           (push (cons (cons pre-context nil) range) all-units)))
  428.     (unless nomsg
  429.       (message "Parse context: done."))
  430.     (nreverse all-units)))
  431. (defun buf2html-get-units-line-feed ()
  432.   "buf2html: 改行文字の範囲(位置)のリストを作成"
  433.   (let (line-feed-units point)
  434.     (goto-char (point-min))
  435.     (while (scan-buffer "\n" :tail t)
  436.       (setq point (1- (point)))
  437.       (push (cons (cons :buf2html-line-feed nil) (cons point (1+ point)))
  438.             line-feed-units))
  439.     (nreverse line-feed-units)))
  440. (defun buf2html-get-units-tag-char (ranges)
  441.   "buf2html: タグの開始、終了文字の範囲(位置)のリストを作成"
  442.   (let (tag-char-units from to c)
  443.     (dolist (range ranges)
  444.       (setq from (car range))
  445.       (setq to (cdr range))
  446.       (when (< from to)
  447.         (setq c (char (buffer-substring from (1+ from)) 0))
  448.         (if (or (syntax-open-tag-p c) (syntax-close-tag-p c))
  449.             (push (cons (cons :tag nil) (cons from (1+ from))) tag-char-units))
  450.         (when (< from (1- to))
  451.           (setq c (char (buffer-substring (1- to) to) 0))
  452.           (if (or (syntax-open-tag-p c) (syntax-close-tag-p c))
  453.               (push (cons (cons :tag nil) (cons (1- to) to)) tag-char-units)))))
  454.     (nreverse tag-char-units)))
  455. (defun buf2html-get-units-text-attribute ()
  456.   "buf2html: text-attribute の範囲のリストを作成"
  457.   (let (text-attribute-units btag etag range key value)
  458.     (dolist (text-attributes (list-text-attributes (point-min) (point-max)))
  459.       (setq range (cons (car text-attributes) (cadr text-attributes)))
  460.       (setq text-attributes (cdddr text-attributes))
  461.       (setq btag "")
  462.       (setq etag "")
  463.       (while text-attributes
  464.         (setq key (car text-attributes))
  465.         (setq value (cadr text-attributes))
  466.         (setq text-attributes (cddr text-attributes))
  467.         (case key
  468.           (:foreground
  469.            (setq btag (format nil "~A<SPAN class=\"fg~D\">" btag value))
  470.            (setq etag (format nil "</SPAN>~A" etag)))
  471.           (:background
  472.            (setq btag (format nil "~A<SPAN class=\"bg~D\">" btag value))
  473.            (setq etag (format nil "</SPAN>~A" etag)))
  474.           (:bold
  475.            (when value
  476.              (setq btag (concat btag "<SPAN class=\"bold\">"))
  477.              (setq etag (concat "</SPAN>" etag))))
  478.           (:underline
  479.            (when value
  480.              (setq btag (concat btag "<SPAN class=\"underline\">"))
  481.              (setq etag (concat "</SPAN>" etag))))
  482.           (:strike-out
  483.            (when value
  484.              (setq btag (concat btag "<SPAN class=\"strike-out\">"))
  485.              (setq etag (concat "</SPAN>" etag))))))
  486.       (push (cons (cons :buf2html-text-attribute (cons btag etag)) range)
  487.             text-attribute-units))
  488.     (nreverse text-attribute-units)))
  489. (defun buf2html-get-units-keyword (ranges)
  490.   "buf2html: キーワードの範囲のリストを作成"
  491.   (let ((point-max (point-max)) keyword-units from to regexp compiled-color
  492.         str begin end)
  493.     (dolist (range ranges)
  494.       (setq from (car range))
  495.       (setq to (cdr range))
  496.       (goto-char from)
  497.       (message "Parse keyword: ~2D%" (floor (* 100 (/ from point-max))))
  498.       (setq regexp (compile-regexp "\\(\\s@\\|\\s{\\|\\s\\\\)?\\(\\sw\\|\\s_\\)+"))
  499.       (while (scan-buffer regexp :limit to)
  500.         (setq str (match-string 0))
  501.         (setq begin (match-beginning 0))
  502.         (setq end (match-end 0))
  503.         (when (syntax-symbol-prefix-p (char str 0))
  504.           (setq str (substring 1 str))
  505.           (setq begin (1- begin)))
  506.         (multiple-value-bind (compiled-color init)
  507.             (gethash str ed::keyword-hash-table)
  508.           (when init
  509.             (push (cons (cons :buf2html-keyword compiled-color)
  510.                         (cons begin end)) keyword-units)))
  511.         (goto-char end)))
  512.     (message "Parse keyword: done.")
  513.     (nreverse keyword-units)))
  514. (defun buf2html-get-units-keyword-c-preprocessor (ranges)
  515.   "buf2html: C preprocessor 用キーワードの範囲のリストを作成"
  516.   (let ((point-max (point-max)) keyword-units from to regexp compiled-color
  517.         str begin end)
  518.     (dolist (range ranges)
  519.       (setq from (car range))
  520.       (setq to (cdr range))
  521.       (goto-char from)
  522.       (message "Parse c preprocessor keyword: ~2D%" (floor (* 100 (/ from point-max))))
  523.       (setq regexp (compile-regexp "#[ \t]*\\(\\(\\sw\\|\\s_\\)+\\)"))
  524.       (while (scan-buffer regexp :limit to)
  525.         (setq str (concat "#" (match-string 1)))
  526.         (setq begin (match-beginning 0))
  527.         (setq end (match-end 0))
  528.         (multiple-value-bind (compiled-color init)
  529.             (gethash str ed::keyword-hash-table)
  530.           (when init
  531.             (push (cons (cons :buf2html-keyword compiled-color)
  532.                         (cons begin end)) keyword-units)))
  533.         (goto-char end)))
  534.     (message "Parse c preprocessor keyword: done.")
  535.     (nreverse keyword-units)))
  536. (defun buf2html-get-units-regexp-keyword (ranges regexp-keyword)
  537.   "buf2html: 正規表現キーワードの範囲のリストを作成"
  538.   (let ((regexp (car regexp-keyword))
  539.         (colors (cadr regexp-keyword))
  540.         (compiled-context (caddr regexp-keyword))
  541.         (begin (cadddr regexp-keyword))
  542.         (end (car (cddddr regexp-keyword)))
  543.         regexp-keyword-units from to
  544.         (point-max (point-max))
  545.         whole-range enable-range regexp-keyword-group-units
  546.         group-number group-range compiled-color)
  547.     (dolist (range ranges)
  548.       (setq from (car range))
  549.       (setq to (cdr range))
  550.       (goto-char from)
  551.       (while (scan-buffer regexp :tail t :limit to)
  552.         (setq whole-range (cons (match-beginning 0) (match-end 0)))
  553.         (setq enable-range
  554.               (cons (if (minusp begin) (match-end (* -1 begin)) (match-beginning begin))
  555.                     (if (minusp end) (match-beginning (* -1 end)) (match-end end))))
  556.         (setq whole-range enable-range)
  557.         (setq regexp-keyword-group-units
  558.               (list (cons (cons :buf2html-regexp-keyword-group nil)
  559.                           (copy-list whole-range))))
  560.         (cond
  561.          ((not (consp colors))
  562.           (setq compiled-color colors)
  563.           (setq regexp-keyword-group-units
  564.                 (buf2html-unit-cover
  565.                  regexp-keyword-group-units
  566.                  (list (cons (cons :buf2html-regexp-keyword-group compiled-color)
  567.                              enable-range)))))
  568.          (t
  569.           (dolist (color (sort colors #'< :key #'car)); group 順にソート
  570.             (setq group-number (car color))
  571.             (setq compiled-color (cdr color))
  572.             (setq group-range (cons (match-beginning group-number)
  573.                                     (match-end group-number)))
  574.             
  575.             (when (and compiled-color                 ; compiled-color が nil でない
  576.                        (buf2html-in-range-p group-range enable-range))
  577.               (setq regexp-keyword-group-units
  578.                     (buf2html-unit-cover
  579.                      regexp-keyword-group-units
  580.                      (list (cons (cons :buf2html-regexp-keyword-group compiled-color)
  581.                                  group-range))))))))
  582.         (push (cons (cons :buf2html-regexp-keyword regexp-keyword-group-units) whole-range)
  583.               regexp-keyword-units)))
  584.     (nreverse regexp-keyword-units)))
  585. (defun buf2html-make-regexp-keyword-color-list (regexp-keyword-list)
  586.   "buf2html: regexp-keyword-list から color のリストを作成"
  587.   (let (compiled-color-list)
  588.     (when regexp-keyword-list
  589.       ;; nil は使うので必ずいれておく。
  590.       (pushnew nil compiled-color-list :test 'eql)
  591.       (dolist (compiled-colors (mapcar #'cadr regexp-keyword-list))
  592.         (cond
  593.          ((consp compiled-colors)
  594.           (dolist (compiled-color (mapcar #'cdr compiled-colors))
  595.             (pushnew compiled-color compiled-color-list :test 'eql)))
  596.          ((numberp compiled-colors)
  597.           (pushnew compiled-colors compiled-color-list :test 'eql))
  598.          (t
  599.           (pushnew compiled-colors compiled-color-list :test 'eql)))))
  600.     compiled-color-list))
  601. (defun buf2html-add-compiled-color-tag-hash-table (hash-table compiled-colors)
  602.   "buf2html: compiled-colors に対応する HTML タグを hash-table に登録"
  603.   (when (hash-table-p hash-table)
  604.     (dolist (compiled-color compiled-colors)
  605.       (multiple-value-bind (value init)
  606.           (gethash compiled-color hash-table)
  607.         (unless init
  608.           (setf (gethash compiled-color hash-table)
  609.                 (buf2html-make-compiled-color-tag compiled-color)))))
  610.     hash-table))
  611. ;; 正規表現キーワードのグループ毎の色指定での
  612. ;; color 部分が t の場合の動作がよくわからない。
  613. ;; nil のときは、compiled-color は nil
  614. ;; t   のときは、compiled-color は 0
  615. (defun buf2html-make-compiled-color-tag (compiled-color)
  616.   "buf2html: compiled-color に対応する HTML タグを作成"
  617.   (unless (numberp compiled-color)
  618.     (return-from buf2html-make-compiled-color-tag (cons "" "")))
  619.   (let ((fg-bg-p (= (logand compiled-color #x1) #x1))
  620.         (line-p (= (logand compiled-color #x2) #x2))
  621.         (bold-p (= (logand compiled-color #x200000) #x200000))
  622.         (underline-p (= (logand compiled-color #x800000) #x800000))
  623.         (strike-out-p (= (logand compiled-color #x1000000) #x1000000))
  624.         (color (logand compiled-color (lognot #x1)
  625.                        (lognot #x2) (lognot #x200000) (lognot #x800000) (lognot #x1000000)))
  626.         (btag "") (etag ""))
  627.     (cond
  628.      (fg-bg-p
  629.       (setq btag (format nil "<SPAN class=\"fg~D bg~D\">"
  630.                          (floor (logand color #x1f00) #x200)
  631.                          (floor (logand color #x1f0000) #x20000)))
  632.       (setq etag "</SPAN>"))
  633.      (t
  634.       (cond
  635.        ((= color 0)
  636.         (setq btag "" etag ""))
  637.        ((= color (gethash #\0 ed::*keyword-translate-hash-table*));keyword1
  638.         (setq btag "<SPAN class=\"keyword1\">" etag "</SPAN>"))
  639.        ((= color (gethash #\1 ed::*keyword-translate-hash-table*));keyword2
  640.         (setq btag "<SPAN class=\"keyword2\">" etag "</SPAN>"))
  641.        ((= color (gethash #\2 ed::*keyword-translate-hash-table*));keyword3
  642.         (setq btag "<SPAN class=\"keyword3\">" etag "</SPAN>"))
  643.        ((= color (gethash #\3 ed::*keyword-translate-hash-table*));keyword1 反転
  644.         (setq btag "<SPAN class=\"keyword1inverse\">" etag "</SPAN>"))
  645.        ((= color (gethash #\4 ed::*keyword-translate-hash-table*));keyword2 反転
  646.         (setq btag "<SPAN class=\"keyword2inverse\">" etag "</SPAN>"))
  647.        ((= color (gethash #\5 ed::*keyword-translate-hash-table*));keyword3 反転
  648.         (setq btag "<SPAN class=\"keyword3inverse\">" etag "</SPAN>"))
  649.        ((= color (gethash #\S ed::*keyword-translate-hash-table*));string
  650.         (setq btag "<SPAN class=\"string\">" etag "</SPAN>"))
  651.        ((= color (gethash #\T ed::*keyword-translate-hash-table*));tag
  652.         (setq btag "<SPAN class=\"tag\">" etag "</SPAN>"))
  653.        ((= color (gethash #\C ed::*keyword-translate-hash-table*));comment
  654.         (setq btag "<SPAN class=\"comment\">" etag "</SPAN>")))))
  655.     ;; bold
  656.     (when bold-p
  657.       (setq btag (concat btag "<SPAN class=\"bold\">"))
  658.       (setq etag (concat "</SPAN>" etag)))
  659.     ;; underline
  660.     (when underline-p
  661.       (setq btag (concat btag "<SPAN class=\"underline\">"))
  662.       (setq etag (concat "</SPAN>" etag)))
  663.     ;; strike-out