buffer2html.el

buffer2html b2h-trim

;;; Copyright (C) 1996,1997 August Hoerandl <hoerandl@elina.htlw1.ac.at>
;;;
;;; Version: 0.3   April 1997
;;;
;;; 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.
;;;
;;; Commentary:
;;;   convert a fontified buffer to html source - use information
;;;   from font-lock-mode (use colors or bold/italic etc).
;;;
;;; This program is a quick hack: if you like it - use it
;;; You need Xemacs 19.14 (it may not work with Xemacs 19.13 or Emacs 19.30)
;;;
;;; HOWTO:
;;;
;;; setup:
;;;   put this in your .emacs file:    (load "buffer2html")
;;;   or M-x load-file buffer2html.el
;;;
;;; convert file to html:
;;; 1) open a file, fontify (see font-lock.el for help) 
;;; 2) M-x buffer2html and select color/nocolor
;;;    this will change the buffers name to `oldname`.html and
;;;    add all the HTML Tags
;;; 3) save buffer
;;; 4) view with your favorite browser
;;;
;;; change setup:
;;;  change HTML-Tags for start (b2h-start-...) and end (b2h-end-...) of
;;;  each font-face
;;;
;;; TODO:
;;;   - optimize for speed 
;;;   - add hooks for text change - allow easy change ?
;;;   - change all #include "..." to html-references 
;;;   - change all function calls to html-references ?
;;;   - get colors from directly from font-lock-mode

;; version with color
(defvar b2h-start-color
  '((font-lock-comment-face . "<FONT COLOR=\"#A000A0\">")
    (font-lock-doc-string-face ."<FONT COLOR=\"#008B00\">")
    (font-lock-string-face . "<FONT COLOR=\"#008B00\">")
    (font-lock-keyword-face . "<FONT COLOR=\"#0000CD\">")
    ;;    create headline for each function
    ;;    (font-lock-function-name-face . "<H2>")
    (font-lock-function-name-face . "<FONT COLOR=\"#CD0000\">")
    (font-lock-variable-name-face . "<FONT COLOR=\"#0000CD\">")
    (font-lock-type-face . "<FONT COLOR=\"#00008B\">")
    (font-lock-reference-face . "<FONT COLOR=\"#0000CD\">")
    (font-lock-preprocessor-face . "<FONT COLOR=\"#0000CD\">")
    (default . ""))
  "Association List for buffer2html (color): font . HTML Tag to start")

(defvar b2h-end-color
  '((font-lock-comment-face . "</FONT>")
    (font-lock-preprocessor-face . "</FONT>")
    (font-lock-string-face . "</FONT>")
    (font-lock-doc-string-face ."</FONT>")
    ;; just plain function names
    (font-lock-function-name-face . "</FONT>")
    ;; create headline for each function
    ;;    (font-lock-function-name-face . "</H2>")
    ;; create a label for each function
    ;;    (font-lock-function-name-face . "</FONT><A NAME=\"%s\">")
    (font-lock-variable-name-face . "</FONT>")
    (font-lock-reference-face . "</FONT>")
    (font-lock-keyword-face . "</FONT>")
    (font-lock-type-face . "</FONT>")
    (default . ""))
  "Association List for buffer2html (color): font . HTML Tag to end
use %s to get text of the fontified region")

;; version without color
(defvar b2h-start-nocolor
  '((font-lock-comment-face . "<I>")
    (font-lock-preprocessor-face . "<I>")
    (font-lock-string-face . "<I>")
    (font-lock-doc-string-face ."<I>")
    (font-lock-function-name-face . "<STRONG>")
    (font-lock-variable-name-face . "<I>")
    (font-lock-reference-face . "<I>")
    (font-lock-keyword-face . "<B><EM>")
    (font-lock-type-face . "<EM>")
    (default . ""))
  "Association List for buffer2html (nocolor): font . HTML Tag to start")

(defvar b2h-end-nocolor
  '((font-lock-comment-face . "</I>")
    (font-lock-preprocessor-face . "</I>")
    (font-lock-string-face . "</I>")
    (font-lock-doc-string-face ."</I>")
    (font-lock-function-name-face . "</STRONG><A NAME=\"%s\">")
;;    (font-lock-function-name-face . "</STRONG>")
    (font-lock-variable-name-face . "</I>")
    (font-lock-reference-face . "</I>")
    (font-lock-keyword-face . "</B></EM>")
    (font-lock-type-face . "</EM>")
    (default . ""))
  "Association List for buffer2html (nocolor): font . HTML Tag to end
use %s to get text of the fontified region")

(defun b2h-trim (string)
"trim a STRING: replace all ' ' by '' "
(replace-in-string string " " ""))

(defun buffer2html ()
"convert current buffer to html
 Howto convert a file to html:
 1) open a file, fontify
 2) M-x buffer2html
    this will change the buffers name to oldname.html and
    add all the HTML Tags
 3) save buffer
 4) view with your favorite browser"
(interactive)
(if (buffer-modified-p)
    (message "Please save buffer before using buffer2html !!")
  (let (pos 
	old-prop 
	startpos 
	func-list
	(name (buffer-name)) 
	(b2h-start b2h-start-color) 
	(b2h-end b2h-end-color)
	(ins-func-list (y-or-n-p "Insert function list ")))
    (if (y-or-n-p "Use color ")
	()
      (setq b2h-start b2h-start-nocolor) 
      (setq b2h-end b2h-end-nocolor))
    ;; change buffer name 
    (set-visited-file-name (concat name ".html" ))
    ;; stop (auto-)fontifying on changes
    (remove-hook 'after-change-functions 'font-lock-after-change-function t)
    (remove-hook 'pre-idle-hook 'font-lock-pre-idle-hook t)
    ;; replace <, >, & with html version
    (goto-char (point-min))
    (replace-string "&" "&amp;")
    (goto-char (point-min))
    (replace-string "<" "&lt;")
    (goto-char (point-min))
    (replace-string ">" "&gt;")
    (message "Inserting HTML Tags ...")
    ;; insert header
    (goto-char (point-min))
    (insert "<html><head><title> Source: " name " </title>\n" 
	    "</head><body>"
	    "<H1> " name " </H1>\n" 
	    "<!-- created by buffer2html.el -->\n"
	    "\n\n<pre>\n")
    (backward-char)
    (put-nonduplicable-text-property (point-min) (point) 'face nil)
    (goto-char (point-max))
    (insert "\n</pre></body></html>\n")
    ;; loop for all face changes
    (goto-char (point-min))
    (while (not (eobp))
      (let ((plist (text-properties-at (point)))
	    (next-change (or (next-property-change (point) (current-buffer))
			     (point-max))))
	;; Process text from point to NEXT-CHANGE...
	(goto-char next-change)
	(if old-prop
	    (progn  
	      (insert (format (cdr (assoc old-prop b2h-end)) 
			      (b2h-trim (buffer-substring startpos 
							  next-change))))
	      (if ins-func-list
		  (if (eq old-prop font-lock-function-name-face)
		      (setq func-list 
			    (cons (buffer-substring startpos next-change) 
				  func-list))))))
	;; get new face
	(setq old-prop (get-text-property next-change 'face))
	;; start new HTML-tag
	(if old-prop
	    (progn
	      (insert (cdr (assoc old-prop b2h-start)))
	      (setq startpos (point))))))
    ;; add-functions
    (goto-char (point-min))
    (forward-line 4)
    (if ins-func-list
	(while func-list
	  (let ((name (car func-list)))
	    (insert (format "<a href=\"#%s\">%s</a>\n" (b2h-trim name) name))
	    (setq func-list (cdr-safe func-list)))))
    (insert "<HR>\n")
    (message "done"))))