From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Jambunathan K Newsgroups: gmane.emacs.bugs Subject: bug#9914: 24.0.91; htmlfontify.el: Add support for code block fontification on ODT export Date: Mon, 31 Oct 2011 14:34:48 +0530 Message-ID: <818vo1ilan.fsf@gmail.com> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: dough.gmane.org 1320052032 3265 80.91.229.12 (31 Oct 2011 09:07:12 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Mon, 31 Oct 2011 09:07:12 +0000 (UTC) To: 9914@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Mon Oct 31 10:07:06 2011 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([140.186.70.17]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1RKnpg-0002Tf-Bg for geb-bug-gnu-emacs@m.gmane.org; Mon, 31 Oct 2011 10:07:05 +0100 Original-Received: from localhost ([::1]:33652 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RKnpe-0007i5-UF for geb-bug-gnu-emacs@m.gmane.org; Mon, 31 Oct 2011 05:07:02 -0400 Original-Received: from eggs.gnu.org ([140.186.70.92]:46930) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RKnpX-0007hv-Vg for bug-gnu-emacs@gnu.org; Mon, 31 Oct 2011 05:06:59 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RKnpU-00040B-VH for bug-gnu-emacs@gnu.org; Mon, 31 Oct 2011 05:06:55 -0400 Original-Received: from debbugs.gnu.org ([140.186.70.43]:52063) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RKnpU-000403-MA for bug-gnu-emacs@gnu.org; Mon, 31 Oct 2011 05:06:52 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.69) (envelope-from ) id 1RKnra-0005nW-Pz for bug-gnu-emacs@gnu.org; Mon, 31 Oct 2011 05:09:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Jambunathan K Original-Sender: debbugs-submit-bounces@debbugs.gnu.org Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 31 Oct 2011 09:09:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 9914 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.132005209522230 (code B ref -1); Mon, 31 Oct 2011 09:09:02 +0000 Original-Received: (at submit) by debbugs.gnu.org; 31 Oct 2011 09:08:15 +0000 Original-Received: from localhost ([127.0.0.1] helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1RKnqn-0005mT-P3 for submit@debbugs.gnu.org; Mon, 31 Oct 2011 05:08:15 -0400 Original-Received: from eggs.gnu.org ([140.186.70.92]) by debbugs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1RKnqk-0005mL-4u for submit@debbugs.gnu.org; Mon, 31 Oct 2011 05:08:12 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RKnoa-0003lN-GI for submit@debbugs.gnu.org; Mon, 31 Oct 2011 05:05:59 -0400 Original-Received: from lists.gnu.org ([140.186.70.17]:38598) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RKnoa-0003lE-8s for submit@debbugs.gnu.org; Mon, 31 Oct 2011 05:05:56 -0400 Original-Received: from eggs.gnu.org ([140.186.70.92]:41553) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RKnoX-0007dh-Hg for bug-gnu-emacs@gnu.org; Mon, 31 Oct 2011 05:05:56 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RKnoU-0003kn-Mn for bug-gnu-emacs@gnu.org; Mon, 31 Oct 2011 05:05:53 -0400 Original-Received: from mail-qw0-f41.google.com ([209.85.216.41]:65378) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RKnoT-0003kg-OQ for bug-gnu-emacs@gnu.org; Mon, 31 Oct 2011 05:05:50 -0400 Original-Received: by qadc11 with SMTP id c11so5608638qad.0 for ; Mon, 31 Oct 2011 02:05:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:subject:date:message-id:mime-version:content-type; bh=o8MNICr60lZhRL1BAEsSo/8Y4IWDgRaIAMZUyVlg7ZU=; b=Vk74XQdSbW5QdsE8sisEvd/p6ZGopMrx5XOsiPXlvh9WPeHjWauO0lYxd+a5gFO0Y1 s9AiwY4hWtjCQ5MDg0wiXB6SFVZcir08eNrkASofzc6rHPmb1JBkv/Irmol9dCjiioCg 0MIgfCCE+wdoksdo0XVg7jsdHdJbQQaxufZFI= Original-Received: by 10.68.72.103 with SMTP id c7mr22183660pbv.1.1320051948014; Mon, 31 Oct 2011 02:05:48 -0700 (PDT) Original-Received: from JAMBU-NETBOOK ([115.242.250.106]) by mx.google.com with ESMTPS id jm5sm48871925pbc.1.2011.10.31.02.05.00 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 31 Oct 2011 02:05:44 -0700 (PDT) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.11 Precedence: list Resent-Date: Mon, 31 Oct 2011 05:09:02 -0400 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 140.186.70.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:53337 Archived-At: --=-=-= Content-Type: text/plain I have added support for exporting of Orgmode files to OpenDocument Text format. See http://lists.gnu.org/archive/html/bug-gnu-emacs/2011-10/msg01313.html. As part of the above work, I have enhanced htmlfontify.el so that Org babel blocks are fontified in the exported document. See the attached README.org for details. --=-=-= Content-Type: text/x-org Content-Disposition: attachment; filename=README.org * htmlfontify.el changes Directory structure 1. a/htmlfontify.el - stock htmlfontify.el downloaded from Emacs-24 trunk around Aug 10, 2011 or so. 2. b/htmlfontify.el - enhanced htmlfontify.el 3. htmlfontify.el.patch - Single-shot diff between a/htmlfontify.el and b/htmlfontify.el 4. patches - This directory contains 5 numbers of patches generated with "git format-patch ...". These are incremental patches that moves htmlfontify.el from a to b. See the changelog entry in the patches for more information 5. test - This directory contains a sample test.org and test.odt files for unit-testing purposes. test.odt was produced by the ODT exporter using the enhanced version of htmlfontify.el. Note: For producing fontified src blocks with the ODT exporter just make sure that the enhanced htmlfontify.el is in the load-path. --=-=-= Content-Type: text/plain The standalone files are bundled in to the htmlfontify.tar.gz for ease of examination. --=-=-= Content-Type: application/octet-stream Content-Disposition: attachment; filename=htmlfontify.tar.gz Content-Transfer-Encoding: base64 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 --=-=-= Content-Type: text/plain Sample test files: --=-=-= Content-Type: application/vnd.oasis.opendocument.text Content-Disposition: attachment; filename=test.odt Content-Transfer-Encoding: base64 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 AQIAAFBLBQYAAAAABgAGAM8BAADWIwAAAAA= --=-=-= Content-Type: text/x-org Content-Disposition: attachment; filename=test.org #+TITLE: test.org #+AUTHOR: Jambunathan K #+EMAIL: kjambunathan@gmail.com #+DATE: 2011-10-31 Mon #+DESCRIPTION: #+KEYWORDS: #+LANGUAGE: en #+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t #+OPTIONS: TeX:t LaTeX:dvipng skip:nil d:nil todo:t pri:nil tags:not-in-toc #+EXPORT_SELECT_TAGS: export #+EXPORT_EXCLUDE_TAGS: noexport #+LINK_UP: #+LINK_HOME: #+XSLT: * Sample src code Customize babel to include emacs-lisp and C. #+begin_src emacs-lisp (custom-set-variables '(org-babel-load-languages (quote ((emacs-lisp . t) (C . t))))) #+end_src See that the following src block taken from [[http://elpa.gnu.org/themes/][GNU Emacs Theme Generator]] is nicely fontified. #+begin_src C /* Sample Emacs buffer. */ int main (int argc, char **argv) { void *unused = NULL; if (argc == 0) /* Mark & point here. */ { printf ("Hello World\n"); goto end; } return 1; end: return 0; } #+end_src --=-=-= Content-Type: text/plain Attachments: --=-=-= Content-Type: application/emacs-lisp; charset=utf-8 Content-Disposition: attachment; filename=htmlfontify.el Content-Transfer-Encoding: quoted-printable Content-Description: a/htmlfontify.el ;;; htmlfontify.el --- htmlise a buffer/source tree with optional hyperlinks ;; Copyright (C) 2002-2003, 2009-2011 Free Software Foundation, Inc. ;; Emacs Lisp Archive Entry ;; Package: htmlfontify ;; Filename: htmlfontify.el ;; Version: 0.21 ;; Keywords: html, hypermedia, markup, etags ;; Author: Vivek Dasmohapatra ;; Maintainer: Vivek Dasmohapatra ;; Created: 2002-01-05 ;; Description: htmlise a buffer/source tree with optional hyperlinks ;; URL: http://rtfm.etla.org/emacs/htmlfontify/ ;; Compatibility: Emacs23, Emacs22 ;; Incompatibility: Emacs19, Emacs20, Emacs21 ;; Last Updated: Thu 2009-11-19 01:31:21 +0000 ;; Version: 0.21 ;; This file is part of GNU Emacs. ;; GNU Emacs 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 3 of the License, or ;; (at your option) any later version. ;; GNU Emacs 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 GNU Emacs. If not, see . ;;; Commentary: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; I have made some changes to make it work for Emacs 22. A lot of ;; small bug fixes related to the format of text and overlay ;; properties (which might have changed since the beginning of 2003 ;; when this file was originally written). ;; ;; The function `hfy-face-at' currently carries much of the burden of ;; my lacking understanding of the formats mentioned above and should ;; need some knowledgeable help. ;; ;; Another thing that maybe could be fixed is that overlay background ;; colors which are now only seen where there is text (in the XHTML ;; output). A bit of CSS tweaking is necessary there. ;; ;; The face 'default has a value :background "SystemWindow" for the ;; background color. There is no explicit notion that this should be ;; considered transparent, but I have assumed that it could be handled ;; like if it was here. (I am unsure that background and foreground ;; priorities are handled ok, but it looks ok in my tests now.) ;; ;; 2007-12-27 Lennart Borgman ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Here's some elisp code to html-pretty-print an Emacs buffer, preserving ;; the Emacs syntax/whatever highlighting. It also knows how to drive etags ;; (exuberant-ctags or Emacs etags) and hyperlink the code according ;; to its (etags') output. ;; NOTE: Currently the hyperlinking code only knows how to drive GNU find ;; and the exuberant and GNU variants of etags : I do not know of any other ;; etags variants, but mechanisms have been provided to allow htmlfontify ;; to be taught how to drive them. As long as your version of find has ;; the -path test and is reasonably sane, you should be fine. ;; A sample of the htmlfontified / hyperlinked output of this module can be ;; found at http://rtfm.etla.org/sql/dbishell/src/ - it's not perfect, but ;; it's a hell of a lot faster and more thorough than I could hope to be ;; doing this by hand. ;; some user / horrified onlooker comments: ;; What? No! There's something deeply wrong here... (R. Shufflebotham) ;; You're a freak. (D. Silverstone) ;; Aren't we giving you enough to do? (J. Busuttil) ;; You're almost as messed up as Lexx is! (N. Graves-Morris) ;;; History: ;; Changes: moved to changelog (CHANGES) file. ;;; Code: (eval-when-compile (require 'cl)) (require 'faces) ;; (`facep' `face-attr-construct' `x-color-values' `color-values' `face-na= me') (require 'custom) ;; (`defgroup' `defcustom') (require 'font-lock) ;; (`font-lock-fontify-region') (require 'cus-edit) (defconst htmlfontify-version 0.21) (defconst hfy-meta-tags (format "" emacs-version htmlfontify-version) "The generator meta tag for this version of htmlfontify.") (defconst htmlfontify-manual "Htmlfontify Manual" "Copy and convert buffers and files to HTML, adding hyperlinks between fi= les \(driven by etags) if requested. \nInteractive functions: `htmlfontify-buffer' `htmlfontify-run-etags' `htmlfontify-copy-and-link-dir' `htmlfontify-load-rgb-file' `htmlfontify-unload-rgb-file'\n In order to:\n fontify a file you have open: \\[htmlfontify-buffer] prepare the etags map for a directory: \\[htmlfontify-run-etags] copy a directory, fontifying as you go: \\[htmlfontify-copy-and-link-dir]\n The following might be useful when running non-windowed or in batch mode: \(note that they shouldn't be necessary - we have a built in map)\n load an X11 style rgb.txt file: \\[htmlfontify-load-rgb-file] unload the current rgb.txt file: \\[htmlfontify-unload-rgb-file]\n And here's a programmatic example:\n \(defun rtfm-build-page-header (file style) (format \"#define TEMPLATE red+black.html #define DEBUG 1 #include \\n html-css-url :=3D /css/red+black.css title :=3D rtfm.etla.org ( %s / src/%s ) bodytag :=3D head <=3DSTYLESHEET;\\n %s STYLESHEET main-title :=3D rtfm / %s / src/%s\\n main-content <=3DMAIN_CONTENT;\\n\" rtfm-section file style rtfm-section fi= le)) \(defun rtfm-build-page-footer (file) \"\\nMAIN_CONTENT\\n\") \(defun rtfm-build-source-docs (section srcdir destdir) (interactive \"s section[eg- emacs / p4-blame]:\\nD source-dir: \\nD output-dir: \") (require 'htmlfontify) (hfy-load-tags-cache srcdir) (let ((hfy-page-header 'rtfm-build-page-header) (hfy-page-footer 'rtfm-build-page-footer) (rtfm-section section) (hfy-index-file \"index\")) (htmlfontify-run-etags srcdir) (htmlfontify-copy-and-link-dir srcdir destdir \".src\" \".html\")))") (defgroup htmlfontify nil "Convert buffers and files to HTML." :group 'applications :link '(variable-link htmlfontify-manual) :prefix "hfy-") (defcustom hfy-page-header 'hfy-default-header "Function called to build the header of the html source. This is called with two arguments (the filename relative to the top level source directory being etag'd and fontified), and a string containing the text to embed in the document. It should return the string returned will be used as the header for the htmlfontified version of the source file.\n See also `hfy-page-footer'." :group 'htmlfontify ;; FIXME: Why place such a :tag everywhere? Isn't it imposing your ;; own Custom preference on your users? --Stef :tag "page-header" :type '(function)) (defcustom hfy-split-index nil "Whether or not to split the index `hfy-index-file' alphabetically. If non-nil, the index is split on the first letter of each tag. Useful when the index would otherwise be large and take a long time to render or be difficult to navigate." :group 'htmlfontify :tag "split-index" :type '(boolean)) (defcustom hfy-page-footer 'hfy-default-footer "As `hfy-page-header', but generates the output footer. It takes only one argument, the filename." :group 'htmlfontify :tag "page-footer" :type '(function)) (defcustom hfy-extn ".html" "File extension used for output files." :group 'htmlfontify :tag "extension" :type '(string)) (defcustom hfy-src-doc-link-style "text-decoration: underline;" "String to add to the '\n"))) (funcall hfy-page-header file stylesheet))) ;; tag all the dangerous characters we want to escape ;; (ie any "<> chars we _didn't_ put there explicitly for css markup) (defun hfy-html-enkludge-buffer () "Mark dangerous [\"<>] characters with the `hfy-quoteme' property.\n See also `hfy-html-dekludge-buffer'." ;;(message "hfy-html-enkludge-buffer");;DBUG (save-excursion (goto-char (point-min)) (while (re-search-forward hfy-html-quote-regex nil t) (put-text-property (match-beginning 0) (point) 'hfy-quoteme t))) ) ;; dangerous char -> &entity; (defun hfy-html-quote (char-string) "Map CHAR-STRING to an HTML safe string (entity) if need be." ;;(message "hfy-html-quote");;DBUG (or (cadr (assoc char-string hfy-html-quote-map)) char-string) ) ;; actually entity-ise dangerous chars. ;; note that we can't do this until _after_ we have inserted the css ;; markup, since we use a position-based map to insert this, and if we ;; enter any other text before we do this, we'd have to track another ;; map of offsets, which would be tedious... (defun hfy-html-dekludge-buffer () "Transform all dangerous characters marked with the `hfy-quoteme' property using `hfy-html-quote'.\n See also `hfy-html-enkludge-buffer'." ;;(message "hfy-html-dekludge-buffer");;DBUG (save-excursion (goto-char (point-min)) (while (re-search-forward hfy-html-quote-regex nil t) (if (get-text-property (match-beginning 0) 'hfy-quoteme) (replace-match (hfy-html-quote (match-string 1))) )) )) ;; Borrowed from font-lock.el (defmacro hfy-save-buffer-state (varlist &rest body) "Bind variables according to VARLIST and eval BODY restoring buffer state. Do not record undo information during evaluation of BODY." (declare (indent 1) (debug let)) (let ((modified (make-symbol "modified"))) `(let* ,(append varlist `((,modified (buffer-modified-p)) (buffer-undo-list t) (inhibit-read-only t) (inhibit-point-motion-hooks t) (inhibit-modification-hooks t) deactivate-mark buffer-file-name buffer-file-truename)) (progn ,@body) (unless ,modified (restore-buffer-modified-p nil))))) (defun hfy-mark-trailing-whitespace () "Tag trailing whitespace with a hfy property if it is currently highlight= ed." (when show-trailing-whitespace (let ((inhibit-read-only t)) (save-excursion (goto-char (point-min)) (hfy-save-buffer-state nil (while (re-search-forward "[ \t]+$" nil t) (put-text-property (match-beginning 0) (match-end 0) 'hfy-show-trailing-whitespace t))))))) (defun hfy-unmark-trailing-whitespace () "Undo the effect of `hfy-mark-trailing-whitespace'." (when show-trailing-whitespace (hfy-save-buffer-state nil (remove-text-properties (point-min) (point-max) '(hfy-show-trailing-whitespace))))) (defun hfy-fontify-buffer (&optional srcdir file) "Implement the guts of `htmlfontify-buffer'. SRCDIR, if set, is the directory being htmlfontified. FILE, if set, is the file name." (if srcdir (setq srcdir (directory-file-name srcdir))) (let* ( (html-buffer (hfy-buffer)) (css-sheet nil) (css-map nil) (invis-ranges nil) (rovl nil) (orig-ovls (overlays-in (point-min) (point-max))) (rmin (when mark-active (region-beginning))) (rmax (when mark-active (region-end ))) ) (when (and mark-active transient-mark-mode) (unless (and (=3D rmin (point-min)) (=3D rmax (point-max))) (setq rovl (make-overlay rmin rmax)) (overlay-put rovl 'priority 1000) (overlay-put rovl 'face 'region))) ;; copy the buffer, including fontification, and switch to it: (hfy-mark-trailing-whitespace) (setq css-sheet (hfy-compile-stylesheet ) css-map (hfy-compile-face-map ) invis-ranges (hfy-find-invisible-ranges)) (hfy-unmark-trailing-whitespace) (when rovl (delete-overlay rovl)) (copy-to-buffer html-buffer (point-min) (point-max)) (set-buffer html-buffer) ;; rip out props that could interfere with our htmlisation of the buffe= r: (remove-text-properties (point-min) (point-max) hfy-ignored-properties) ;; Apply overlay invisible spec (setq orig-ovls (sort orig-ovls (lambda (A B) (> (or (cadr (memq 'priority (overlay-properties A))) 0) (or (cadr (memq 'priority (overlay-properties B))) 0))= ))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;= ;;;; ;; at this point, html-buffer retains the fontification of the parent: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;= ;;;; ;; we don't really need or want text in the html buffer to be invisible= , as ;; that can make it look like we've rendered invalid xhtml when all tha= t's ;; happened is some tags are in the invisible portions of the buffer: (setq buffer-invisibility-spec nil) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;= ;;;; ;; ##################################################################### ;; if we are in etags mode, add properties to mark the anchors and links (if (and srcdir file) (progn (hfy-mark-tag-names srcdir file) ;; mark anchors (hfy-mark-tag-hrefs srcdir file))) ;; mark links ;; ##################################################################### ;; mark the 'dangerous' characters ;;(message "marking dangerous characters") (hfy-html-enkludge-buffer) ;; trawl the position-based face-map, inserting span tags as we go ;; note that we cannot change any character positions before this point ;; or we will invalidate the map: ;; NB: This also means we have to trawl the map in descending file-offs= et ;; order, obviously. ;; --------------------------------------------------------------------- ;; Remember, inserting pushes properties to the right, which we don't ;; actually want to happen for link properties, so we have to flag ;; them and move them by hand - if you don't, you end up with ;; ;; texta... ;; ;; instead of: ;; ;; texta... ;; ;; If my analysis of the problem is correct, we can detect link-ness by ;; either hfy-linkp or hfy-endl properties at the insertion point, but I ;; think we only need to relocate the hfy-endl property, as the hfy-lin= kp ;; property has already served its main purpose by this point. ;;(message "mapcar over the CSS-MAP") (message "invis-ranges:\n%S" invis-ranges) (dolist (point-face css-map) (let ((pt (car point-face)) (fn (cdr point-face)) (move-link nil)) (goto-char pt) (setq move-link (or (get-text-property pt 'hfy-linkp) (get-text-property pt 'hfy-endl ))) (if (eq 'end fn) (insert "") (if (not (and srcdir file)) nil (when move-link (remove-text-properties (point) (1+ (point)) '(hfy-endl nil)) (put-text-property pt (1+ pt) 'hfy-endl t) )) ;; if we have invisible blocks, we need to do some extra magic: (if invis-ranges (let ((iname (hfy-invisible-name pt invis-ranges)) (fname (hfy-lookup fn css-sheet ))) (when (assq pt invis-ranges) (insert (format "" iname= )) (insert "=E2=80=A6")) (insert (format "" fname iname= pt))) (insert (format "" (hfy-lookup fn css-shee= t)))) (if (not move-link) nil ;;(message "removing prop2 @ %d" (point)) (if (remove-text-properties (point) (1+ (point)) '(hfy-endl nil= )) (put-text-property pt (1+ pt) 'hfy-endl t)))))) ;; ##################################################################### ;; Invisibility ;; Maybe just make the text invisible in XHTML? ;; DONE -- big block of obsolete invisibility code elided here -- v ;; ##################################################################### ;; (message "checking to see whether we should link...") (if (and srcdir file) (let ((lp 'hfy-link) (pt (point-min)) (pr nil) (rr nil)) ;; (message " yes we should.") ;; translate 'hfy-anchor properties to anchors (while (setq pt (next-single-property-change pt 'hfy-anchor)) (if (setq pr (get-text-property pt 'hfy-anchor)) (progn (goto-char pt) (remove-text-properties pt (1+ pt) '(hfy-anchor nil)) (insert (concat ""))))) ;; translate alternate 'hfy-link and 'hfy-endl props to opening ;; and closing links. (this should avoid those spurious closes ;; we sometimes get by generating only paired tags) (setq pt (point-min)) (while (setq pt (next-single-property-change pt lp)) (if (not (setq pr (get-text-property pt lp))) nil (goto-char pt) (remove-text-properties pt (1+ pt) (list lp nil)) (case lp (hfy-link (if (setq rr (get-text-property pt 'hfy-inst)) (insert (format "" rr))) (insert (format "" pr)) (setq lp 'hfy-endl)) (hfy-endl (insert "") (setq lp 'hfy-link)) ))) )) ;; ##################################################################### ;; transform the dangerous chars. This changes character positions ;; since entities have > char length. ;; note that this deletes the dangerous characters, and therefore ;; destroys any properties they may contain (such as 'hfy-endl), ;; so we have to do this after we use said properties: ;; (message "munging dangerous characters") (hfy-html-dekludge-buffer) ;; insert the stylesheet at the top: (goto-char (point-min)) ;;(message "inserting stylesheet") (insert (hfy-sprintf-stylesheet css-sheet file)) (if (hfy-opt 'div-wrapper) (insert "
")) (insert "\n
")
    (goto-char (point-max))
    (insert "
\n") (if (hfy-opt 'div-wrapper) (insert "
")) ;;(message "inserting footer") (insert (funcall hfy-page-footer file)) ;; call any post html-generation hooks: (run-hooks 'hfy-post-html-hooks) ;; return the html buffer (set-buffer-modified-p nil) html-buffer)) (defun hfy-force-fontification () "Try to force font-locking even when it is optimized away." (run-hooks 'hfy-init-kludge-hook) (eval-and-compile (require 'font-lock)) (if (boundp 'font-lock-cache-position) (or font-lock-cache-position (set 'font-lock-cache-position (make-marker)))) (if (not noninteractive) (progn (message "hfy interactive mode (%S %S)" window-system major-mode) (when (and font-lock-defaults font-lock-mode) (font-lock-fontify-region (point-min) (point-max) nil))) (message "hfy batch mode (%s:%S)" (or (buffer-file-name) (buffer-name)) major-mode) (when font-lock-defaults (font-lock-fontify-buffer)) )) ;;;###autoload (defun htmlfontify-buffer (&optional srcdir file) "Create a new buffer, named for the current buffer + a .html extension, containing an inline CSS-stylesheet and formatted CSS-markup HTML that reproduces the look of the current Emacs buffer as closely as possible. Dangerous characters in the existing buffer are turned into HTML entities, so you should even be able to do HTML-within-HTML fontified display. You should, however, note that random control or eight-bit characters such as ^L (\x0c) or =C2=A4 (\xa4) won't get mapped yet. If the SRCDIR and FILE arguments are set, lookup etags derived entries in the `hfy-tags-cache' and add HTML anchors and hyperlinks as appropriate." (interactive) ;; pick up the file name in case we didn't receive it (if (not file) (progn (setq file (or (buffer-file-name) (buffer-name))) (if (string-match "/\\([^/]*\\)\\'" file) (setq file (match-string 1 file)))) ) (if (not (hfy-opt 'skip-refontification)) (save-excursion ;; Keep region (hfy-force-fontification))) (if (called-interactively-p 'any) ;; display the buffer in interactive mo= de: (switch-to-buffer (hfy-fontify-buffer srcdir file)) (hfy-fontify-buffer srcdir file))) ;; recursive file listing (defun hfy-list-files (directory) "Return a list of files under DIRECTORY. Strips any leading \"./\" from each filename." ;;(message "hfy-list-files");;DBUG ;; FIXME: this changes the dir of the currrent buffer. Is that right?? (cd directory) (mapcar (lambda (F) (if (string-match "^./\\(.*\\)" F) (match-string 1 F)= F)) (split-string (shell-command-to-string hfy-find-cmd))) ) ;; strip the filename off, return a directiry name ;; not a particularly thorough implementaion, but it will be ;; fed pretty carefully, so it should be Ok: (defun hfy-dirname (file) "Return everything preceding the last \"/\" from a relative filename FILE, on the assumption that this will produce a relative directory name. Hardly bombproof, but good enough in the context in which it is being used." ;;(message "hfy-dirname");;DBUG (let ((f (directory-file-name file))) (and (string-match "^\\(.*\\)/" f) (match-string 1 f)))) ;; create a directory, cf mkdir -p (defun hfy-make-directory (dir) "Approx. equivalent of mkdir -p DIR." ;;(message "hfy-make-directory");;DBUG (if (file-exists-p dir) (if (file-directory-p dir) t) (make-directory dir t))) (defun hfy-text-p (srcdir file) "Is SRCDIR/FILE text? Uses `hfy-istext-command' to determine this." (let* ((cmd (format hfy-istext-command (expand-file-name file srcdir))) (rsp (shell-command-to-string cmd))) (string-match "text" rsp))) ;; open a file, check fontification, if fontified, write a fontified copy ;; to the destination directory, otherwise just copy the file: (defun hfy-copy-and-fontify-file (srcdir dstdir file) "Open FILE in SRCDIR - if fontified, write a fontified copy to DSTDIR adding an extension of `hfy-extn'. Fontification is actually done by `htmlfontify-buffer'. If the buffer is not fontified, just copy it." ;;(message "hfy-copy-and-fontify-file");;DBUG (let (;;(fast-lock-minimum-size hfy-fast-lock-save) ;;(font-lock-support-mode 'fast-lock-mode) ;;(window-system (or window-system 'htmlfontify)) (target nil) (source nil) (html nil)) (cd srcdir) (with-current-buffer (setq source (find-file-noselect file)) ;; FIXME: Shouldn't this use expand-file-name? --Stef (setq target (concat dstdir "/" file)) (hfy-make-directory (hfy-dirname target)) (if (not (hfy-opt 'skip-refontification)) (hfy-force-fontification)) (if (or (hfy-fontified-p) (hfy-text-p srcdir file)) (progn (setq html (hfy-fontify-buffer srcdir file)) (set-buffer html) (write-file (concat target hfy-extn)) (kill-buffer html)) ;; #o0200 =3D=3D 128, but emacs20 doesn't know that (if (and (file-exists-p target) (not (file-writable-p target))) (set-file-modes target (logior (file-modes target) 128))) (copy-file (buffer-file-name source) target 'overwrite)) (kill-buffer source)) )) ;; list of tags in file in srcdir (defun hfy-tags-for-file (cache-hash file) "List of etags tags that have definitions in this FILE. CACHE-HASH is the tags cache." ;;(message "hfy-tags-for-file");;DBUG (let* ((tag-list nil)) (if cache-hash (maphash (lambda (K V) (if (assoc file V) (setq tag-list (cons K tag-list)))) cache-hash)) tag-list)) ;; mark the tags native to this file for anchors (defun hfy-mark-tag-names (srcdir file) "Mark tags in FILE (lookup SRCDIR in `hfy-tags-cache') with the `hfy-anch= or' property, with a value of \"tag.line-number\"." ;;(message "(hfy-mark-tag-names %s %s)" srcdir file);;DBUG (let* ((cache-entry (assoc srcdir hfy-tags-cache)) (cache-hash (cadr cache-entry))) (if cache-hash (mapcar (lambda (TAG) (mapcar (lambda (TLIST) (if (string=3D file (car TLIST)) (let* ((line (cadr TLIST) ) (chr (caddr TLIST) ) (link (format "%s.%d" TAG line) )) (put-text-property (+ 1 chr) (+ 2 chr) 'hfy-anchor link)))) (gethash TAG cache-hash))) (hfy-tags-for-file cache-hash file))))) (defun hfy-relstub (file &optional start) "Return a \"../\" stub of the appropriate length for the current source tree depth, as determined from FILE (a filename). START is the offset at which to start looking for the / character in FILE." ;;(message "hfy-relstub");;DBUG (let ((c "")) (while (setq start (string-match "/" file start)) (setq start (1+ start)) (setq c (concat c "../"))) c)) (defun hfy-href-stub (this-file def-files tag) "Return an href stub for a tag href in THIS-FILE. If DEF-FILES (list of files containing definitions for the tag in question) contains only one entry, the href should link straight to that file. Otherwise, the link should be to the index file.\n We are not yet concerned with the file extensions/tag line number and so on= at this point.\n If `hfy-split-index' is set, and the href wil be to an index file rather th= an a source file, append a .X to `hfy-index-file', where X is the uppercased first character of TAG.\n See also `hfy-relstub', `hfy-index-file'." ;;(message "hfy-href-stub");;DBUG ;; FIXME: Why not use something like ;; (file-relative-name (if ...) (file-name-directory this-file)) ? --Stef (concat (hfy-relstub this-file) (if (=3D 1 (length def-files)) (car def-files) (if (not hfy-split-index) hfy-index-file (concat hfy-index-file "." (upcase (substring tag 0 1)))))) ) (defun hfy-href (this-file def-files tag tag-map) "Return a relative href to the tag in question, based on\n THIS-FILE `hfy-link-extn' `hfy-extn' DEF-FILES TAG and TAG-MAP\n THIS-FILE is the current source file DEF-FILES is a list of file containing possible link endpoints for TAG TAG is the tag in question TAG-MAP is the entry in `hfy-tags-cache'." ;;(message "hfy-href");;DBUG (concat (hfy-href-stub this-file def-files tag) (or hfy-link-extn hfy-extn) "#" tag ;;(.src -> .html) (if (=3D 1 (length def-files)) (concat "." (format "%d" (cadr (assoc (car def-files) tag-map)))))) ) (defun hfy-word-regex (string) "Return a regex that matches STRING as the first `match-string', with non word characters on either side." ;; FIXME: Should this use [^$[:alnum:]_] instead? --Stef (concat "[^$A-Za-z_0-9]\\(" (regexp-quote string) "\\)[^A-Za-z_0-9]")) ;; mark all tags for hyperlinking, except the tags at ;; their own points of definition, iyswim: (defun hfy-mark-tag-hrefs (srcdir file) "Mark href start points with the `hfy-link' prop (value: href string).\n Mark href end points with the `hfy-endl' prop (value t).\n Avoid overlapping links, and mark links in descending length of tag name in order to prevent subtags from usurping supertags, \(eg \"term\" for \"terminal\"). SRCDIR is the directory being \"published\". FILE is the specific file we are rendering." ;;(message "hfy-mark-tag-hrefs");;DBUG (let ((cache-entry (assoc srcdir hfy-tags-cache)) (list-cache (assoc srcdir hfy-tags-sortl)) (rmap-cache (assoc srcdir hfy-tags-rmap )) (no-comment (hfy-opt 'zap-comment-links)) (no-strings (hfy-opt 'zap-string-links )) (cache-hash nil) (tags-list nil) (tags-rmap nil) (case-fold-search nil)) ;; extract the tag mapping hashes (fwd and rev) and the tag list: (if (and (setq cache-hash (cadr cache-entry)) (setq tags-rmap (cadr rmap-cache )) (setq tags-list (cadr list-cache ))) (mapcar (lambda (TAG) (let* ((start nil) (stop nil) (href nil) (name nil) (case-fold-search nil) (tmp-point nil) (maybe-start nil) (face-at nil) (rmap-entry nil) (rnew-elt nil) (rmap-line nil) (tag-regex (hfy-word-regex TAG)) (tag-map (gethash TAG cache-hash)) (tag-files (mapcar #'car tag-map))) ;; find instances of TAG and do what needs to be done: (goto-char (point-min)) (while (search-forward TAG nil 'NOERROR) (setq tmp-point (point) maybe-start (- (match-beginning 0) 1)) (goto-char maybe-start) (if (not (looking-at tag-regex)) nil (setq start (match-beginning 1)) (setq stop (match-end 1)) (setq face-at (and (or no-comment no-strings) (hfy-face-at start))) (if (listp face-at) (setq face-at (cadr (memq :inherit face-at)))) (if (or (text-property-any start (1+ stop) 'hfy-linkp = t) (and no-comment (eq 'font-lock-comment-face face-a= t)) (and no-strings (eq 'font-lock-string-face face-a= t))) nil ;; already a link, NOOP ;; set a reverse map entry: (setq rmap-line (line-number-at-pos) rmap-entry (gethash TAG tags-rmap) rnew-elt (list file rmap-line start) rmap-entry (cons rnew-elt rmap-entry) name (format "%s.%d" TAG rmap-line)) (put-text-property start (1+ start) 'hfy-inst name) (puthash TAG rmap-entry tags-rmap) ;; mark the link. link to index if the tag has > 1 def ;; add the line number to the #name if it does not: (setq href (hfy-href file tag-files TAG tag-map)) (put-text-property start (1+ start) 'hfy-link href) (put-text-property stop (1+ stop ) 'hfy-endl t ) (put-text-property start (1+ stop ) 'hfy-linkp t ))) (goto-char tmp-point)) )) tags-list) ))) (defun hfy-shell () "Return `shell-file-name', or \"/bin/sh\" if it is a non-bourne shell." (if (string-match "\\\\|\\\\|\\" shell-file-name) shell-file-name (or hfy-shell-file-name "/bin/sh"))) ;; cache the #(tag =3D> file line point) entries for files under srcdir ;; and cache the descending sorted list of tags in the relevant alist, ;; also keyed by srcdir: (defun hfy-load-tags-cache (srcdir) "Run `hfy-etags-cmd' on SRCDIR, then call `hfy-parse-tags-buffer'." ;;(message "hfy-load-tags-cache");;DBUG (let ((etags-buffer (get-buffer-create "*hfy-tags*")) (etags-command (format hfy-etags-cmd hfy-etags-bin)) (shell-file-name (hfy-shell))) (cd srcdir) (shell-command etags-command etags-buffer) (hfy-parse-tags-buffer srcdir etags-buffer)) ) ;; break this out from `hfy-load-tags-cache' to make the tar file ;; functionality easier to implement. ;; ( tar file functionality not merged here because it requires a ;; hacked copy of etags capable of tagging stdin: if Francesco ;; Potorti accepts a patch, or otherwise implements stdin tagging, ;; then I will provide a `htmlfontify-tar-file' defun ) (defun hfy-parse-tags-buffer (srcdir buffer) "Parse a BUFFER containing etags formatted output, loading the `hfy-tags-cache' and `hfy-tags-sortl' entries for SRCDIR." (let ((cache-entry (assoc srcdir hfy-tags-cache)) (tlist-cache (assoc srcdir hfy-tags-sortl)) (trmap-cache (assoc srcdir hfy-tags-rmap )) (cache-hash nil) (trmap-hash nil) (tags-list nil) (hash-entry nil) (tag-string nil) (tag-line nil) (tag-point nil) (new-entry nil) (etags-file nil)) ;; (re)initialise the tag reverse map: (if trmap-cache (setq trmap-hash (cadr trmap-cache)) (setq trmap-hash (make-hash-table :test 'equal)) (setq hfy-tags-rmap (list (list srcdir trmap-hash) hfy-tags-rmap))) (clrhash trmap-hash) ;; (re)initialise the tag cache: (if cache-entry (setq cache-hash (cadr cache-entry)) (setq cache-hash (make-hash-table :test 'equal)) (setq hfy-tags-cache (list (list srcdir cache-hash) hfy-tags-cache))) (clrhash cache-hash) ;; cache the TAG =3D> ((file line point) (file line point) ... ) entrie= s: (with-current-buffer buffer (goto-char (point-min)) (while (and (looking-at "^\x0c") (=3D 0 (forward-line 1))) ;;(message "^L boundary") (if (and (looking-at "^\\(.+\\),\\([0-9]+\\)$") (=3D 0 (forward-line 1))) (progn (setq etags-file (match-string 1)) ;;(message "TAGS for file: %s" etags-file) (while (and (looking-at hfy-etag-regex) (=3D 0 (forward-line = 1))) (setq tag-string (match-string 1)) (if (=3D 0 (length tag-string)) nil ;; noop (setq tag-line (round (string-to-number (match-string 2= )))) (setq tag-point (round (string-to-number (match-string 3= )))) (setq hash-entry (gethash tag-string cache-hash)) (setq new-entry (list etags-file tag-line tag-point)) (push new-entry hash-entry) ;;(message "HASH-ENTRY %s %S" tag-string new-entry) (puthash tag-string hash-entry cache-hash)))) ))) ;; cache a list of tags in descending length order: (maphash (lambda (K _V) (push K tags-list)) cache-hash) (setq tags-list (sort tags-list (lambda (A B) (< (length B) (length A))= ))) ;; put the tag list into the cache: (if tlist-cache (setcar (cdr tlist-cache) tags-list) (push (list srcdir tags-list) hfy-tags-sortl)) ;; return the number of tags found: (length tags-list) )) (defun hfy-prepare-index-i (srcdir dstdir filename &optional stub map) "Prepare a tags index buffer for SRCDIR. `hfy-tags-cache' must already have an entry for SRCDIR for this to work. `hfy-page-header', `hfy-page-footer', `hfy-link-extn' and `hfy-extn' all play a part here.\n If STUB is set, prepare an (appropriately named) index buffer specifically for entries beginning with STUB.\n If MAP is set, use that instead of `hfy-tags-cache'. FILENAME is the name of the file being indexed. DSTDIR is the output directory, where files will be written." ;;(message "hfy-write-index");;DBUG (let ((cache-entry (assoc srcdir (or map hfy-tags-cache))) (cache-hash nil) (tag-list nil) (index-file (concat filename (if stub (concat "." stub) "") hfy-extn)) (index-buf nil)) (if (not (and cache-entry (setq cache-hash (cadr cache-entry)) (setq index-buf (get-buffer-create index-file)))) nil ;; noop (maphash (lambda (K _V) (push K tag-list)) cache-hash) (setq tag-list (sort tag-list 'string<)) (set-buffer index-buf) (erase-buffer) (insert (funcall hfy-page-header filename "")) (insert "\n") (dolist (TAG tag-list) (let ((tag-started nil)) (dolist (DEF (gethash TAG cache-hash)) (if (and stub (not (string-match (concat "^" stub) TAG))) nil ;; we have a stub and it didn't match: NOOP (let ((file (car DEF)) (line (cadr DEF))) (insert (format (concat " \n" " \n" " \n" " \n" " \n") (if (string=3D TAG tag-started) " " (format "%s" TAG TAG)) file (or hfy-link-extn hfy-extn) file file (or hfy-link-extn hfy-extn) TAG line line)) (setq tag-started TAG)))))) (insert "
%s%s%d
\n") (insert (funcall hfy-page-footer filename)) (and dstdir (cd dstdir)) (set-visited-file-name index-file) index-buf) )) (defun hfy-prepare-index (srcdir dstdir) "Return a list of index buffer(s), as determined by `hfy-split-index'. SRCDIR and DSTDIR are the source and output directories respectively." (if (not hfy-split-index) (list (hfy-prepare-index-i srcdir dstdir hfy-index-file nil)) (let ((stub-list nil) (cache-hash nil) (index-list nil) (cache-entry (assoc srcdir hfy-tags-cache))) (if (and cache-entry (setq cache-hash (cadr cache-entry))) (maphash (lambda (K _V) (let ((stub (upcase (substring K 0 1)))) (if (member stub stub-list) nil ;; seen this already: NOOP (setq stub-list (cons stub stub-list) index-list (cons (hfy-prepare-index-i srcdir dstdir hfy-index-file stub) index-list)) ))) cache-hash) ) index-list))) (defun hfy-prepare-tag-map (srcdir dstdir) "Prepare the counterpart(s) to the index buffer(s) - a list of buffers with the same structure, but listing (and linking to) instances of tags \(as opposed to their definitions).\n SRCDIR and DSTDIR are the source and output directories respectively. See also `hfy-prepare-index', `hfy-split-index'." (if (not hfy-split-index) (list (hfy-prepare-index-i srcdir dstdir hfy-instance-file nil hfy-tags-rmap)) (let ((stub-list nil) (cache-hash nil) (index-list nil) (cache-entry (assoc srcdir hfy-tags-rmap))) (if (and cache-entry (setq cache-hash (cadr cache-entry))) (maphash (lambda (K _V) (let ((stub (upcase (substring K 0 1)))) (if (member stub stub-list) nil ;; seen this already: NOOP (setq stub-list (cons stub stub-list) index-list (cons (hfy-prepare-index-i srcdir dstdir hfy-instance-file stub hfy-tags-rmap) index-list)) ))) cache-hash) ) index-list))) (defun hfy-subtract-maps (srcdir) "Internal function - strips definitions of tags from the instance map. SRCDIR is the directory being \"published\". See also `hfy-tags-cache', `hfy-tags-rmap'." (let ((new-list nil) (old-list nil) (def-list nil) (exc-list nil) (fwd-map (cadr (assoc srcdir hfy-tags-cache))) (rev-map (cadr (assoc srcdir hfy-tags-rmap ))) (taglist (cadr (assoc srcdir hfy-tags-sortl)))) (dolist (TAG taglist) (setq def-list (gethash TAG fwd-map) old-list (gethash TAG rev-map) exc-list (mapcar (lambda (P) (list (car P) (cadr P))) def-list) new-list nil) (dolist (P old-list) (or (member (list (car P) (cadr P)) exc-list) (push P new-list))) (puthash TAG new-list rev-map)))) (defun htmlfontify-run-etags (srcdir) "Load the etags cache for SRCDIR. See also `hfy-load-tags-cache'." (interactive "D source directory: ") (hfy-load-tags-cache (directory-file-name srcdir))) ;;(defun hfy-test-read-args (foo bar) ;; (interactive "D source directory: \nD target directory: ") ;; (message "foo: %S\nbar: %S" foo bar)) (defun hfy-save-kill-buffers (buffer-list &optional dstdir) (dolist (B buffer-list) (set-buffer B) (and dstdir (file-directory-p dstdir) (cd dstdir)) (save-buffer) (kill-buffer B))) ;;;###autoload (defun htmlfontify-copy-and-link-dir (srcdir dstdir &optional f-ext l-ext) "Trawl SRCDIR and write fontified-and-hyperlinked output in DSTDIR. F-EXT and L-EXT specify values for `hfy-extn' and `hfy-link-extn'.\n You may also want to set `hfy-page-header' and `hfy-page-footer'." (interactive "D source directory: \nD output directory: ") ;;(message "htmlfontify-copy-and-link-dir") (setq srcdir (directory-file-name srcdir)) (setq dstdir (directory-file-name dstdir)) (let ((source-files "SETME: list of source files, relative to srcdir") (tr-cache (assoc srcdir hfy-tags-rmap)) (hfy-extn (or f-ext ".html")) (hfy-link-extn (or l-ext ".html"))) ;; oops, forgot to load etags for srcdir: (if tr-cache nil (message "autoload of tags cache") (hfy-load-tags-cache srcdir) (setq tr-cache (assoc srcdir hfy-tags-rmap))) ;; clear out the old cache: (clrhash (cadr tr-cache)) (hfy-make-directory dstdir) (setq source-files (hfy-list-files srcdir)) (dolist (file source-files) (hfy-copy-and-fontify-file srcdir dstdir file)) (hfy-subtract-maps srcdir) (hfy-save-kill-buffers (hfy-prepare-index srcdir dstdir) dstdir) (hfy-save-kill-buffers (hfy-prepare-tag-map srcdir dstdir) dstdir) )) ;; name of the init file we want: (defun hfy-initfile () "Return the expected location of the htmlfontify specific init/custom fil= e." (let* ((file (or (getenv "HFY_INITFILE") ".hfy.el"))) (expand-file-name file "~") )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; incomplete as yet : transfer hook settings to hfy init file: ;; (defalias 'hfy-set-hooks 'custom-set-variables) ;; (defun hfy-pp-hook (H) ;; (and (string-match "-hook\\'" (symbol-name H)) ;; (boundp H) ;; (symbol-value H) ;; (insert (format "\n '(%S %S)" H (symbol-value H))) ;; ) ;; ) ;; (defun hfy-save-hooks () ;; (let ((custom-file (hfy-initfile))) ;; (custom-save-delete 'hfy-set-hooks) ;; (let ((standard-output (current-buffer))) ;; (princ "(hfy-set-hooks\n;;auto-generated, only one copy allowed\n") ;; (mapatoms 'hfy-pp-hook) ;; (insert "\n)") ;; ) ;; ) ;; ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defalias 'hfy-init-progn 'progn) (defun hfy-save-initvar (sym) (princ (format "(setq %s\n '" sym)) (pp (symbol-value sym)) (princ ")\n")) (defun htmlfontify-save-initfile () "Save the htmlfontify settings to the htmlfontify init file." (interactive) (let* ((start-pos nil) (custom-file (hfy-initfile)) (standard-output (find-file-noselect custom-file 'nowarn))) (save-excursion (custom-save-delete 'hfy-init-progn) (setq start-pos (point)) (princ "(hfy-init-progn\n;;auto-generated, only one copy allowed\n") ;; FIXME: This saving&restoring of global customization ;; variables can interfere with other customization settings for ;; those vars (in .emacs or in Customize). (mapc 'hfy-save-initvar '(auto-mode-alist interpreter-mode-alist)) (princ ")\n") (indent-region start-pos (point) nil)) (custom-save-all) )) (defun htmlfontify-load-initfile () "Load the htmlfontify specific init/custom file." (interactive) (let ((file (hfy-initfile))) (load file 'NOERROR nil nil) )) ;;;### (autoloads (hfy-fallback-colour-values htmlfontify-load-rgb-file) ;;;;;; "hfy-cmap" "hfy-cmap.el" "8dce008297f15826cc6ab82203c46fa6") ;;; Generated autoloads from hfy-cmap.el (autoload 'htmlfontify-load-rgb-file "hfy-cmap" "\ Load an X11 style rgb.txt FILE. Search `hfy-rgb-load-path' if FILE is not specified. Loads the variable `hfy-rgb-txt-colour-map', which is used by `hfy-fallback-colour-values'. \(fn &optional FILE)" t nil) (autoload 'hfy-fallback-colour-values "hfy-cmap" "\ Use a fallback method for obtaining the rgb values for a color. \(fn COLOUR-STRING)" nil nil) ;;;*** (provide 'htmlfontify) ;; Local Variables: ;; coding: utf-8 ;; End: ;;; htmlfontify.el ends here --=-=-= Content-Type: application/emacs-lisp; charset=utf-8 Content-Disposition: attachment; filename=htmlfontify.el Content-Transfer-Encoding: quoted-printable Content-Description: b/htmlfontify.el ;;; htmlfontify.el --- htmlise a buffer/source tree with optional hyperlinks ;; Copyright (C) 2002-2003, 2009-2011 Free Software Foundation, Inc. ;; Emacs Lisp Archive Entry ;; Package: htmlfontify ;; Filename: htmlfontify.el ;; Version: 0.21 ;; Keywords: html, hypermedia, markup, etags ;; Author: Vivek Dasmohapatra ;; Maintainer: Vivek Dasmohapatra ;; Created: 2002-01-05 ;; Description: htmlise a buffer/source tree with optional hyperlinks ;; URL: http://rtfm.etla.org/emacs/htmlfontify/ ;; Compatibility: Emacs23, Emacs22 ;; Incompatibility: Emacs19, Emacs20, Emacs21 ;; Last Updated: Thu 2009-11-19 01:31:21 +0000 ;; Version: 0.21 ;; This file is part of GNU Emacs. ;; GNU Emacs 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 3 of the License, or ;; (at your option) any later version. ;; GNU Emacs 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 GNU Emacs. If not, see . ;;; Commentary: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; I have made some changes to make it work for Emacs 22. A lot of ;; small bug fixes related to the format of text and overlay ;; properties (which might have changed since the beginning of 2003 ;; when this file was originally written). ;; ;; The function `hfy-face-at' currently carries much of the burden of ;; my lacking understanding of the formats mentioned above and should ;; need some knowledgeable help. ;; ;; Another thing that maybe could be fixed is that overlay background ;; colors which are now only seen where there is text (in the XHTML ;; output). A bit of CSS tweaking is necessary there. ;; ;; The face 'default has a value :background "SystemWindow" for the ;; background color. There is no explicit notion that this should be ;; considered transparent, but I have assumed that it could be handled ;; like if it was here. (I am unsure that background and foreground ;; priorities are handled ok, but it looks ok in my tests now.) ;; ;; 2007-12-27 Lennart Borgman ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Here's some elisp code to html-pretty-print an Emacs buffer, preserving ;; the Emacs syntax/whatever highlighting. It also knows how to drive etags ;; (exuberant-ctags or Emacs etags) and hyperlink the code according ;; to its (etags') output. ;; NOTE: Currently the hyperlinking code only knows how to drive GNU find ;; and the exuberant and GNU variants of etags : I do not know of any other ;; etags variants, but mechanisms have been provided to allow htmlfontify ;; to be taught how to drive them. As long as your version of find has ;; the -path test and is reasonably sane, you should be fine. ;; A sample of the htmlfontified / hyperlinked output of this module can be ;; found at http://rtfm.etla.org/sql/dbishell/src/ - it's not perfect, but ;; it's a hell of a lot faster and more thorough than I could hope to be ;; doing this by hand. ;; some user / horrified onlooker comments: ;; What? No! There's something deeply wrong here... (R. Shufflebotham) ;; You're a freak. (D. Silverstone) ;; Aren't we giving you enough to do? (J. Busuttil) ;; You're almost as messed up as Lexx is! (N. Graves-Morris) ;;; History: ;; Changes: moved to changelog (CHANGES) file. ;;; Code: (eval-when-compile (require 'cl)) (require 'faces) ;; (`facep' `face-attr-construct' `x-color-values' `color-values' `face-na= me') (require 'custom) ;; (`defgroup' `defcustom') (require 'font-lock) ;; (`font-lock-fontify-region') (require 'cus-edit) (defconst htmlfontify-version 0.21) (defconst hfy-meta-tags (format "" emacs-version htmlfontify-version) "The generator meta tag for this version of htmlfontify.") (defconst htmlfontify-manual "Htmlfontify Manual" "Copy and convert buffers and files to HTML, adding hyperlinks between fi= les \(driven by etags) if requested. \nInteractive functions: `htmlfontify-buffer' `htmlfontify-run-etags' `htmlfontify-copy-and-link-dir' `htmlfontify-load-rgb-file' `htmlfontify-unload-rgb-file'\n In order to:\n fontify a file you have open: \\[htmlfontify-buffer] prepare the etags map for a directory: \\[htmlfontify-run-etags] copy a directory, fontifying as you go: \\[htmlfontify-copy-and-link-dir]\n The following might be useful when running non-windowed or in batch mode: \(note that they shouldn't be necessary - we have a built in map)\n load an X11 style rgb.txt file: \\[htmlfontify-load-rgb-file] unload the current rgb.txt file: \\[htmlfontify-unload-rgb-file]\n And here's a programmatic example:\n \(defun rtfm-build-page-header (file style) (format \"#define TEMPLATE red+black.html #define DEBUG 1 #include \\n html-css-url :=3D /css/red+black.css title :=3D rtfm.etla.org ( %s / src/%s ) bodytag :=3D head <=3DSTYLESHEET;\\n %s STYLESHEET main-title :=3D rtfm / %s / src/%s\\n main-content <=3DMAIN_CONTENT;\\n\" rtfm-section file style rtfm-section fi= le)) \(defun rtfm-build-page-footer (file) \"\\nMAIN_CONTENT\\n\") \(defun rtfm-build-source-docs (section srcdir destdir) (interactive \"s section[eg- emacs / p4-blame]:\\nD source-dir: \\nD output-dir: \") (require 'htmlfontify) (hfy-load-tags-cache srcdir) (let ((hfy-page-header 'rtfm-build-page-header) (hfy-page-footer 'rtfm-build-page-footer) (rtfm-section section) (hfy-index-file \"index\")) (htmlfontify-run-etags srcdir) (htmlfontify-copy-and-link-dir srcdir destdir \".src\" \".html\")))") (defgroup htmlfontify nil "Convert buffers and files to HTML." :group 'applications :link '(variable-link htmlfontify-manual) :prefix "hfy-") (defcustom hfy-page-header 'hfy-default-header "Function called to build the header of the html source. This is called with two arguments (the filename relative to the top level source directory being etag'd and fontified), and a string containing the text to embed in the document. It should return the string returned will be used as the header for the htmlfontified version of the source file.\n See also `hfy-page-footer'." :group 'htmlfontify ;; FIXME: Why place such a :tag everywhere? Isn't it imposing your ;; own Custom preference on your users? --Stef :tag "page-header" :type '(function)) (defcustom hfy-split-index nil "Whether or not to split the index `hfy-index-file' alphabetically. If non-nil, the index is split on the first letter of each tag. Useful when the index would otherwise be large and take a long time to render or be difficult to navigate." :group 'htmlfontify :tag "split-index" :type '(boolean)) (defcustom hfy-page-footer 'hfy-default-footer "As `hfy-page-header', but generates the output footer. It takes only one argument, the filename." :group 'htmlfontify :tag "page-footer" :type '(function)) (defcustom hfy-extn ".html" "File extension used for output files." :group 'htmlfontify :tag "extension" :type '(string)) (defcustom hfy-src-doc-link-style "text-decoration: underline;" "String to add to the '\n"))) (funcall hfy-page-header file stylesheet))) ;; tag all the dangerous characters we want to escape ;; (ie any "<> chars we _didn't_ put there explicitly for css markup) (defun hfy-html-enkludge-buffer () "Mark dangerous [\"<>] characters with the `hfy-quoteme' property.\n See also `hfy-html-dekludge-buffer'." ;;(message "hfy-html-enkludge-buffer");;DBUG (save-excursion (goto-char (point-min)) (while (re-search-forward hfy-html-quote-regex nil t) (put-text-property (match-beginning 0) (point) 'hfy-quoteme t))) ) ;; dangerous char -> &entity; (defun hfy-html-quote (char-string) "Map CHAR-STRING to an HTML safe string (entity) if need be." ;;(message "hfy-html-quote");;DBUG (or (cadr (assoc char-string hfy-html-quote-map)) char-string) ) ;; actually entity-ise dangerous chars. ;; note that we can't do this until _after_ we have inserted the css ;; markup, since we use a position-based map to insert this, and if we ;; enter any other text before we do this, we'd have to track another ;; map of offsets, which would be tedious... (defun hfy-html-dekludge-buffer () "Transform all dangerous characters marked with the `hfy-quoteme' property using `hfy-html-quote'.\n See also `hfy-html-enkludge-buffer'." ;;(message "hfy-html-dekludge-buffer");;DBUG (save-excursion (goto-char (point-min)) (while (re-search-forward hfy-html-quote-regex nil t) (if (get-text-property (match-beginning 0) 'hfy-quoteme) (replace-match (hfy-html-quote (match-string 1))) )) )) ;; Borrowed from font-lock.el (defmacro hfy-save-buffer-state (varlist &rest body) "Bind variables according to VARLIST and eval BODY restoring buffer state. Do not record undo information during evaluation of BODY." (declare (indent 1) (debug let)) (let ((modified (make-symbol "modified"))) `(let* ,(append varlist `((,modified (buffer-modified-p)) (buffer-undo-list t) (inhibit-read-only t) (inhibit-point-motion-hooks t) (inhibit-modification-hooks t) deactivate-mark buffer-file-name buffer-file-truename)) (progn ,@body) (unless ,modified (restore-buffer-modified-p nil))))) (defun hfy-mark-trailing-whitespace () "Tag trailing whitespace with a hfy property if it is currently highlight= ed." (when show-trailing-whitespace (let ((inhibit-read-only t)) (save-excursion (goto-char (point-min)) (hfy-save-buffer-state nil (while (re-search-forward "[ \t]+$" nil t) (put-text-property (match-beginning 0) (match-end 0) 'hfy-show-trailing-whitespace t))))))) (defun hfy-unmark-trailing-whitespace () "Undo the effect of `hfy-mark-trailing-whitespace'." (when show-trailing-whitespace (hfy-save-buffer-state nil (remove-text-properties (point-min) (point-max) '(hfy-show-trailing-whitespace))))) (defun hfy-begin-span (style text-block text-id text-begins-block-p) "Default handler to begin a span of text. Insert \"\". See `hfy-begin-span-handler' for more information." (when text-begins-block-p (insert (format "=E2=80=A6" tex= t-block))) (insert (if text-block (format "" style text-block text= -id) (format "" style)))) (defun hfy-end-span () "Default handler to end a span of text. Insert \"\". See `hfy-end-span-handler' for more information." (insert "")) (defvar hfy-begin-span-handler 'hfy-begin-span "Handler to begin a span of text. The signature of the handler is \(lambda (STYLE TEXT-BLOCK TEXT-ID TEXT-BEGINS-BLOCK-P) ...\). The handler must insert appropriate tags to begin a span of text. STYLE is the name of the style that begins at point. It is derived from the face attributes as part of `hfy-face-to-css' callback. The other arguments TEXT-BLOCK, TEXT-ID, TEXT-BEGINS-BLOCK-P are non-nil only if the buffer contains invisible text. TEXT-BLOCK is a string that identifies a single chunk of visible or invisible text of which the current position is a part. For visible portions, it's value is \"nil\". For invisible portions, it's value is computed as part of `hfy-invisible-name'. TEXT-ID marks a unique position within a block. It is set to value of `point' at the current buffer position. TEXT-BEGINS-BLOCK-P is a boolean and is non-nil if the current span also begins a invisible portion of text. An implementation can use TEXT-BLOCK, TEXT-ID, TEXT-BEGINS-BLOCK-P to implement fold/unfold-on-mouse-click like behaviour. The default handler is `hfy-begin-span'.") (defvar hfy-end-span-handler 'hfy-end-span "Handler to end a span of text. The signature of the handler is \(lambda () ...\). The handler must insert appropriate tags to end a span of text. The default handler is `hfy-end-span'.") (defun hfy-fontify-buffer (&optional srcdir file) "Implement the guts of `htmlfontify-buffer'. SRCDIR, if set, is the directory being htmlfontified. FILE, if set, is the file name." (if srcdir (setq srcdir (directory-file-name srcdir))) (let* ( (html-buffer (hfy-buffer)) (css-sheet nil) (css-map nil) (invis-ranges nil) (rovl nil) (orig-ovls (overlays-in (point-min) (point-max))) (rmin (when mark-active (region-beginning))) (rmax (when mark-active (region-end ))) ) (when (and mark-active transient-mark-mode) (unless (and (=3D rmin (point-min)) (=3D rmax (point-max))) (setq rovl (make-overlay rmin rmax)) (overlay-put rovl 'priority 1000) (overlay-put rovl 'face 'region))) ;; copy the buffer, including fontification, and switch to it: (hfy-mark-trailing-whitespace) (setq css-sheet (hfy-compile-stylesheet ) css-map (hfy-compile-face-map ) invis-ranges (hfy-find-invisible-ranges)) (hfy-unmark-trailing-whitespace) (when rovl (delete-overlay rovl)) (copy-to-buffer html-buffer (point-min) (point-max)) (set-buffer html-buffer) ;; rip out props that could interfere with our htmlisation of the buffe= r: (remove-text-properties (point-min) (point-max) hfy-ignored-properties) ;; Apply overlay invisible spec (setq orig-ovls (sort orig-ovls (lambda (A B) (> (or (cadr (memq 'priority (overlay-properties A))) 0) (or (cadr (memq 'priority (overlay-properties B))) 0))= ))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;= ;;;; ;; at this point, html-buffer retains the fontification of the parent: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;= ;;;; ;; we don't really need or want text in the html buffer to be invisible= , as ;; that can make it look like we've rendered invalid xhtml when all tha= t's ;; happened is some tags are in the invisible portions of the buffer: (setq buffer-invisibility-spec nil) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;= ;;;; ;; ##################################################################### ;; if we are in etags mode, add properties to mark the anchors and links (if (and srcdir file) (progn (hfy-mark-tag-names srcdir file) ;; mark anchors (hfy-mark-tag-hrefs srcdir file))) ;; mark links ;; ##################################################################### ;; mark the 'dangerous' characters ;;(message "marking dangerous characters") (hfy-html-enkludge-buffer) ;; trawl the position-based face-map, inserting span tags as we go ;; note that we cannot change any character positions before this point ;; or we will invalidate the map: ;; NB: This also means we have to trawl the map in descending file-offs= et ;; order, obviously. ;; --------------------------------------------------------------------- ;; Remember, inserting pushes properties to the right, which we don't ;; actually want to happen for link properties, so we have to flag ;; them and move them by hand - if you don't, you end up with ;; ;; texta... ;; ;; instead of: ;; ;; texta... ;; ;; If my analysis of the problem is correct, we can detect link-ness by ;; either hfy-linkp or hfy-endl properties at the insertion point, but I ;; think we only need to relocate the hfy-endl property, as the hfy-lin= kp ;; property has already served its main purpose by this point. ;;(message "mapcar over the CSS-MAP") (message "invis-ranges:\n%S" invis-ranges) (dolist (point-face css-map) (let ((pt (car point-face)) (fn (cdr point-face)) (move-link nil)) (goto-char pt) (setq move-link (or (get-text-property pt 'hfy-linkp) (get-text-property pt 'hfy-endl ))) (if (eq 'end fn) (funcall hfy-end-span-handler) (if (not (and srcdir file)) nil (when move-link (remove-text-properties (point) (1+ (point)) '(hfy-endl nil)) (put-text-property pt (1+ pt) 'hfy-endl t) )) ;; if we have invisible blocks, we need to do some extra magic: (funcall hfy-begin-span-handler (hfy-lookup fn css-sheet) (and invis-ranges (format "%s" (hfy-invisible-name pt invis-ranges))) (and invis-ranges pt) (and invis-ranges (assq pt invis-ranges))) (if (not move-link) nil ;;(message "removing prop2 @ %d" (point)) (if (remove-text-properties (point) (1+ (point)) '(hfy-endl nil= )) (put-text-property pt (1+ pt) 'hfy-endl t)))))) ;; ##################################################################### ;; Invisibility ;; Maybe just make the text invisible in XHTML? ;; DONE -- big block of obsolete invisibility code elided here -- v ;; ##################################################################### ;; (message "checking to see whether we should link...") (if (and srcdir file) (let ((lp 'hfy-link) (pt (point-min)) (pr nil) (rr nil)) ;; (message " yes we should.") ;; translate 'hfy-anchor properties to anchors (while (setq pt (next-single-property-change pt 'hfy-anchor)) (if (setq pr (get-text-property pt 'hfy-anchor)) (progn (goto-char pt) (remove-text-properties pt (1+ pt) '(hfy-anchor nil)) (insert (concat ""))))) ;; translate alternate 'hfy-link and 'hfy-endl props to opening ;; and closing links. (this should avoid those spurious closes ;; we sometimes get by generating only paired tags) (setq pt (point-min)) (while (setq pt (next-single-property-change pt lp)) (if (not (setq pr (get-text-property pt lp))) nil (goto-char pt) (remove-text-properties pt (1+ pt) (list lp nil)) (case lp (hfy-link (if (setq rr (get-text-property pt 'hfy-inst)) (insert (format "" rr))) (insert (format "" pr)) (setq lp 'hfy-endl)) (hfy-endl (insert "") (setq lp 'hfy-link)) ))) )) ;; ##################################################################### ;; transform the dangerous chars. This changes character positions ;; since entities have > char length. ;; note that this deletes the dangerous characters, and therefore ;; destroys any properties they may contain (such as 'hfy-endl), ;; so we have to do this after we use said properties: ;; (message "munging dangerous characters") (hfy-html-dekludge-buffer) (unless (hfy-opt 'body-text-only) ;; insert the stylesheet at the top: (goto-char (point-min)) ;;(message "inserting stylesheet") (insert (hfy-sprintf-stylesheet css-sheet file)) (if (hfy-opt 'div-wrapper) (insert "
")) (insert "\n
")
      (goto-char (point-max))
      (insert "
\n") (if (hfy-opt 'div-wrapper) (insert "
")) ;;(message "inserting footer") (insert (funcall hfy-page-footer file))) ;; call any post html-generation hooks: (run-hooks 'hfy-post-html-hooks) ;; return the html buffer (set-buffer-modified-p nil) html-buffer)) (defun htmlfontify-string (string) "Take a STRING and return a fontified version of it. It is assumed that STRING has text properties that allow it to be fontified. This is a simple convenience wrapper around `htmlfontify-buffer'." (let* ((hfy-optimisations-1 (copy-list hfy-optimisations)) (hfy-optimisations (add-to-list 'hfy-optimisations-1 'skip-refontification))) (with-temp-buffer (insert string) (htmlfontify-buffer) (prog1 (buffer-string) (setq buffer-modified-p nil) (kill-buffer))))) (defun hfy-force-fontification () "Try to force font-locking even when it is optimized away." (run-hooks 'hfy-init-kludge-hook) (eval-and-compile (require 'font-lock)) (if (boundp 'font-lock-cache-position) (or font-lock-cache-position (set 'font-lock-cache-position (make-marker)))) (if (not noninteractive) (progn (message "hfy interactive mode (%S %S)" window-system major-mode) (when (and font-lock-defaults font-lock-mode) (font-lock-fontify-region (point-min) (point-max) nil))) (message "hfy batch mode (%s:%S)" (or (buffer-file-name) (buffer-name)) major-mode) (when font-lock-defaults (font-lock-fontify-buffer)) )) ;;;###autoload (defun htmlfontify-buffer (&optional srcdir file) "Create a new buffer, named for the current buffer + a .html extension, containing an inline CSS-stylesheet and formatted CSS-markup HTML that reproduces the look of the current Emacs buffer as closely as possible. Dangerous characters in the existing buffer are turned into HTML entities, so you should even be able to do HTML-within-HTML fontified display. You should, however, note that random control or eight-bit characters such as ^L (\x0c) or =C2=A4 (\xa4) won't get mapped yet. If the SRCDIR and FILE arguments are set, lookup etags derived entries in the `hfy-tags-cache' and add HTML anchors and hyperlinks as appropriate." (interactive) ;; pick up the file name in case we didn't receive it (if (not file) (progn (setq file (or (buffer-file-name) (buffer-name))) (if (string-match "/\\([^/]*\\)\\'" file) (setq file (match-string 1 file)))) ) (if (not (hfy-opt 'skip-refontification)) (save-excursion ;; Keep region (hfy-force-fontification))) (if (called-interactively-p 'any) ;; display the buffer in interactive mo= de: (switch-to-buffer (hfy-fontify-buffer srcdir file)) (hfy-fontify-buffer srcdir file))) ;; recursive file listing (defun hfy-list-files (directory) "Return a list of files under DIRECTORY. Strips any leading \"./\" from each filename." ;;(message "hfy-list-files");;DBUG ;; FIXME: this changes the dir of the currrent buffer. Is that right?? (cd directory) (mapcar (lambda (F) (if (string-match "^./\\(.*\\)" F) (match-string 1 F)= F)) (split-string (shell-command-to-string hfy-find-cmd))) ) ;; strip the filename off, return a directiry name ;; not a particularly thorough implementaion, but it will be ;; fed pretty carefully, so it should be Ok: (defun hfy-dirname (file) "Return everything preceding the last \"/\" from a relative filename FILE, on the assumption that this will produce a relative directory name. Hardly bombproof, but good enough in the context in which it is being used." ;;(message "hfy-dirname");;DBUG (let ((f (directory-file-name file))) (and (string-match "^\\(.*\\)/" f) (match-string 1 f)))) ;; create a directory, cf mkdir -p (defun hfy-make-directory (dir) "Approx. equivalent of mkdir -p DIR." ;;(message "hfy-make-directory");;DBUG (if (file-exists-p dir) (if (file-directory-p dir) t) (make-directory dir t))) (defun hfy-text-p (srcdir file) "Is SRCDIR/FILE text? Uses `hfy-istext-command' to determine this." (let* ((cmd (format hfy-istext-command (expand-file-name file srcdir))) (rsp (shell-command-to-string cmd))) (string-match "text" rsp))) ;; open a file, check fontification, if fontified, write a fontified copy ;; to the destination directory, otherwise just copy the file: (defun hfy-copy-and-fontify-file (srcdir dstdir file) "Open FILE in SRCDIR - if fontified, write a fontified copy to DSTDIR adding an extension of `hfy-extn'. Fontification is actually done by `htmlfontify-buffer'. If the buffer is not fontified, just copy it." ;;(message "hfy-copy-and-fontify-file");;DBUG (let (;;(fast-lock-minimum-size hfy-fast-lock-save) ;;(font-lock-support-mode 'fast-lock-mode) ;;(window-system (or window-system 'htmlfontify)) (target nil) (source nil) (html nil)) (cd srcdir) (with-current-buffer (setq source (find-file-noselect file)) ;; FIXME: Shouldn't this use expand-file-name? --Stef (setq target (concat dstdir "/" file)) (hfy-make-directory (hfy-dirname target)) (if (not (hfy-opt 'skip-refontification)) (hfy-force-fontification)) (if (or (hfy-fontified-p) (hfy-text-p srcdir file)) (progn (setq html (hfy-fontify-buffer srcdir file)) (set-buffer html) (write-file (concat target hfy-extn)) (kill-buffer html)) ;; #o0200 =3D=3D 128, but emacs20 doesn't know that (if (and (file-exists-p target) (not (file-writable-p target))) (set-file-modes target (logior (file-modes target) 128))) (copy-file (buffer-file-name source) target 'overwrite)) (kill-buffer source)) )) ;; list of tags in file in srcdir (defun hfy-tags-for-file (cache-hash file) "List of etags tags that have definitions in this FILE. CACHE-HASH is the tags cache." ;;(message "hfy-tags-for-file");;DBUG (let* ((tag-list nil)) (if cache-hash (maphash (lambda (K V) (if (assoc file V) (setq tag-list (cons K tag-list)))) cache-hash)) tag-list)) ;; mark the tags native to this file for anchors (defun hfy-mark-tag-names (srcdir file) "Mark tags in FILE (lookup SRCDIR in `hfy-tags-cache') with the `hfy-anch= or' property, with a value of \"tag.line-number\"." ;;(message "(hfy-mark-tag-names %s %s)" srcdir file);;DBUG (let* ((cache-entry (assoc srcdir hfy-tags-cache)) (cache-hash (cadr cache-entry))) (if cache-hash (mapcar (lambda (TAG) (mapcar (lambda (TLIST) (if (string=3D file (car TLIST)) (let* ((line (cadr TLIST) ) (chr (caddr TLIST) ) (link (format "%s.%d" TAG line) )) (put-text-property (+ 1 chr) (+ 2 chr) 'hfy-anchor link)))) (gethash TAG cache-hash))) (hfy-tags-for-file cache-hash file))))) (defun hfy-relstub (file &optional start) "Return a \"../\" stub of the appropriate length for the current source tree depth, as determined from FILE (a filename). START is the offset at which to start looking for the / character in FILE." ;;(message "hfy-relstub");;DBUG (let ((c "")) (while (setq start (string-match "/" file start)) (setq start (1+ start)) (setq c (concat c "../"))) c)) (defun hfy-href-stub (this-file def-files tag) "Return an href stub for a tag href in THIS-FILE. If DEF-FILES (list of files containing definitions for the tag in question) contains only one entry, the href should link straight to that file. Otherwise, the link should be to the index file.\n We are not yet concerned with the file extensions/tag line number and so on= at this point.\n If `hfy-split-index' is set, and the href wil be to an index file rather th= an a source file, append a .X to `hfy-index-file', where X is the uppercased first character of TAG.\n See also `hfy-relstub', `hfy-index-file'." ;;(message "hfy-href-stub");;DBUG ;; FIXME: Why not use something like ;; (file-relative-name (if ...) (file-name-directory this-file)) ? --Stef (concat (hfy-relstub this-file) (if (=3D 1 (length def-files)) (car def-files) (if (not hfy-split-index) hfy-index-file (concat hfy-index-file "." (upcase (substring tag 0 1)))))) ) (defun hfy-href (this-file def-files tag tag-map) "Return a relative href to the tag in question, based on\n THIS-FILE `hfy-link-extn' `hfy-extn' DEF-FILES TAG and TAG-MAP\n THIS-FILE is the current source file DEF-FILES is a list of file containing possible link endpoints for TAG TAG is the tag in question TAG-MAP is the entry in `hfy-tags-cache'." ;;(message "hfy-href");;DBUG (concat (hfy-href-stub this-file def-files tag) (or hfy-link-extn hfy-extn) "#" tag ;;(.src -> .html) (if (=3D 1 (length def-files)) (concat "." (format "%d" (cadr (assoc (car def-files) tag-map)))))) ) (defun hfy-word-regex (string) "Return a regex that matches STRING as the first `match-string', with non word characters on either side." ;; FIXME: Should this use [^$[:alnum:]_] instead? --Stef (concat "[^$A-Za-z_0-9]\\(" (regexp-quote string) "\\)[^A-Za-z_0-9]")) ;; mark all tags for hyperlinking, except the tags at ;; their own points of definition, iyswim: (defun hfy-mark-tag-hrefs (srcdir file) "Mark href start points with the `hfy-link' prop (value: href string).\n Mark href end points with the `hfy-endl' prop (value t).\n Avoid overlapping links, and mark links in descending length of tag name in order to prevent subtags from usurping supertags, \(eg \"term\" for \"terminal\"). SRCDIR is the directory being \"published\". FILE is the specific file we are rendering." ;;(message "hfy-mark-tag-hrefs");;DBUG (let ((cache-entry (assoc srcdir hfy-tags-cache)) (list-cache (assoc srcdir hfy-tags-sortl)) (rmap-cache (assoc srcdir hfy-tags-rmap )) (no-comment (hfy-opt 'zap-comment-links)) (no-strings (hfy-opt 'zap-string-links )) (cache-hash nil) (tags-list nil) (tags-rmap nil) (case-fold-search nil)) ;; extract the tag mapping hashes (fwd and rev) and the tag list: (if (and (setq cache-hash (cadr cache-entry)) (setq tags-rmap (cadr rmap-cache )) (setq tags-list (cadr list-cache ))) (mapcar (lambda (TAG) (let* ((start nil) (stop nil) (href nil) (name nil) (case-fold-search nil) (tmp-point nil) (maybe-start nil) (face-at nil) (rmap-entry nil) (rnew-elt nil) (rmap-line nil) (tag-regex (hfy-word-regex TAG)) (tag-map (gethash TAG cache-hash)) (tag-files (mapcar #'car tag-map))) ;; find instances of TAG and do what needs to be done: (goto-char (point-min)) (while (search-forward TAG nil 'NOERROR) (setq tmp-point (point) maybe-start (- (match-beginning 0) 1)) (goto-char maybe-start) (if (not (looking-at tag-regex)) nil (setq start (match-beginning 1)) (setq stop (match-end 1)) (setq face-at (and (or no-comment no-strings) (hfy-face-at start))) (if (listp face-at) (setq face-at (cadr (memq :inherit face-at)))) (if (or (text-property-any start (1+ stop) 'hfy-linkp = t) (and no-comment (eq 'font-lock-comment-face face-a= t)) (and no-strings (eq 'font-lock-string-face face-a= t))) nil ;; already a link, NOOP ;; set a reverse map entry: (setq rmap-line (line-number-at-pos) rmap-entry (gethash TAG tags-rmap) rnew-elt (list file rmap-line start) rmap-entry (cons rnew-elt rmap-entry) name (format "%s.%d" TAG rmap-line)) (put-text-property start (1+ start) 'hfy-inst name) (puthash TAG rmap-entry tags-rmap) ;; mark the link. link to index if the tag has > 1 def ;; add the line number to the #name if it does not: (setq href (hfy-href file tag-files TAG tag-map)) (put-text-property start (1+ start) 'hfy-link href) (put-text-property stop (1+ stop ) 'hfy-endl t ) (put-text-property start (1+ stop ) 'hfy-linkp t ))) (goto-char tmp-point)) )) tags-list) ))) (defun hfy-shell () "Return `shell-file-name', or \"/bin/sh\" if it is a non-bourne shell." (if (string-match "\\\\|\\\\|\\" shell-file-name) shell-file-name (or hfy-shell-file-name "/bin/sh"))) ;; cache the #(tag =3D> file line point) entries for files under srcdir ;; and cache the descending sorted list of tags in the relevant alist, ;; also keyed by srcdir: (defun hfy-load-tags-cache (srcdir) "Run `hfy-etags-cmd' on SRCDIR, then call `hfy-parse-tags-buffer'." ;;(message "hfy-load-tags-cache");;DBUG (let ((etags-buffer (get-buffer-create "*hfy-tags*")) (etags-command (format hfy-etags-cmd hfy-etags-bin)) (shell-file-name (hfy-shell))) (cd srcdir) (shell-command etags-command etags-buffer) (hfy-parse-tags-buffer srcdir etags-buffer)) ) ;; break this out from `hfy-load-tags-cache' to make the tar file ;; functionality easier to implement. ;; ( tar file functionality not merged here because it requires a ;; hacked copy of etags capable of tagging stdin: if Francesco ;; Potorti accepts a patch, or otherwise implements stdin tagging, ;; then I will provide a `htmlfontify-tar-file' defun ) (defun hfy-parse-tags-buffer (srcdir buffer) "Parse a BUFFER containing etags formatted output, loading the `hfy-tags-cache' and `hfy-tags-sortl' entries for SRCDIR." (let ((cache-entry (assoc srcdir hfy-tags-cache)) (tlist-cache (assoc srcdir hfy-tags-sortl)) (trmap-cache (assoc srcdir hfy-tags-rmap )) (cache-hash nil) (trmap-hash nil) (tags-list nil) (hash-entry nil) (tag-string nil) (tag-line nil) (tag-point nil) (new-entry nil) (etags-file nil)) ;; (re)initialise the tag reverse map: (if trmap-cache (setq trmap-hash (cadr trmap-cache)) (setq trmap-hash (make-hash-table :test 'equal)) (setq hfy-tags-rmap (list (list srcdir trmap-hash) hfy-tags-rmap))) (clrhash trmap-hash) ;; (re)initialise the tag cache: (if cache-entry (setq cache-hash (cadr cache-entry)) (setq cache-hash (make-hash-table :test 'equal)) (setq hfy-tags-cache (list (list srcdir cache-hash) hfy-tags-cache))) (clrhash cache-hash) ;; cache the TAG =3D> ((file line point) (file line point) ... ) entrie= s: (with-current-buffer buffer (goto-char (point-min)) (while (and (looking-at "^\x0c") (=3D 0 (forward-line 1))) ;;(message "^L boundary") (if (and (looking-at "^\\(.+\\),\\([0-9]+\\)$") (=3D 0 (forward-line 1))) (progn (setq etags-file (match-string 1)) ;;(message "TAGS for file: %s" etags-file) (while (and (looking-at hfy-etag-regex) (=3D 0 (forward-line = 1))) (setq tag-string (match-string 1)) (if (=3D 0 (length tag-string)) nil ;; noop (setq tag-line (round (string-to-number (match-string 2= )))) (setq tag-point (round (string-to-number (match-string 3= )))) (setq hash-entry (gethash tag-string cache-hash)) (setq new-entry (list etags-file tag-line tag-point)) (push new-entry hash-entry) ;;(message "HASH-ENTRY %s %S" tag-string new-entry) (puthash tag-string hash-entry cache-hash)))) ))) ;; cache a list of tags in descending length order: (maphash (lambda (K _V) (push K tags-list)) cache-hash) (setq tags-list (sort tags-list (lambda (A B) (< (length B) (length A))= ))) ;; put the tag list into the cache: (if tlist-cache (setcar (cdr tlist-cache) tags-list) (push (list srcdir tags-list) hfy-tags-sortl)) ;; return the number of tags found: (length tags-list) )) (defun hfy-prepare-index-i (srcdir dstdir filename &optional stub map) "Prepare a tags index buffer for SRCDIR. `hfy-tags-cache' must already have an entry for SRCDIR for this to work. `hfy-page-header', `hfy-page-footer', `hfy-link-extn' and `hfy-extn' all play a part here.\n If STUB is set, prepare an (appropriately named) index buffer specifically for entries beginning with STUB.\n If MAP is set, use that instead of `hfy-tags-cache'. FILENAME is the name of the file being indexed. DSTDIR is the output directory, where files will be written." ;;(message "hfy-write-index");;DBUG (let ((cache-entry (assoc srcdir (or map hfy-tags-cache))) (cache-hash nil) (tag-list nil) (index-file (concat filename (if stub (concat "." stub) "") hfy-extn)) (index-buf nil)) (if (not (and cache-entry (setq cache-hash (cadr cache-entry)) (setq index-buf (get-buffer-create index-file)))) nil ;; noop (maphash (lambda (K _V) (push K tag-list)) cache-hash) (setq tag-list (sort tag-list 'string<)) (set-buffer index-buf) (erase-buffer) (insert (funcall hfy-page-header filename "")) (insert "\n") (dolist (TAG tag-list) (let ((tag-started nil)) (dolist (DEF (gethash TAG cache-hash)) (if (and stub (not (string-match (concat "^" stub) TAG))) nil ;; we have a stub and it didn't match: NOOP (let ((file (car DEF)) (line (cadr DEF))) (insert (format (concat " \n" " \n" " \n" " \n" " \n") (if (string=3D TAG tag-started) " " (format "%s" TAG TAG)) file (or hfy-link-extn hfy-extn) file file (or hfy-link-extn hfy-extn) TAG line line)) (setq tag-started TAG)))))) (insert "
%s%s%d
\n") (insert (funcall hfy-page-footer filename)) (and dstdir (cd dstdir)) (set-visited-file-name index-file) index-buf) )) (defun hfy-prepare-index (srcdir dstdir) "Return a list of index buffer(s), as determined by `hfy-split-index'. SRCDIR and DSTDIR are the source and output directories respectively." (if (not hfy-split-index) (list (hfy-prepare-index-i srcdir dstdir hfy-index-file nil)) (let ((stub-list nil) (cache-hash nil) (index-list nil) (cache-entry (assoc srcdir hfy-tags-cache))) (if (and cache-entry (setq cache-hash (cadr cache-entry))) (maphash (lambda (K _V) (let ((stub (upcase (substring K 0 1)))) (if (member stub stub-list) nil ;; seen this already: NOOP (setq stub-list (cons stub stub-list) index-list (cons (hfy-prepare-index-i srcdir dstdir hfy-index-file stub) index-list)) ))) cache-hash) ) index-list))) (defun hfy-prepare-tag-map (srcdir dstdir) "Prepare the counterpart(s) to the index buffer(s) - a list of buffers with the same structure, but listing (and linking to) instances of tags \(as opposed to their definitions).\n SRCDIR and DSTDIR are the source and output directories respectively. See also `hfy-prepare-index', `hfy-split-index'." (if (not hfy-split-index) (list (hfy-prepare-index-i srcdir dstdir hfy-instance-file nil hfy-tags-rmap)) (let ((stub-list nil) (cache-hash nil) (index-list nil) (cache-entry (assoc srcdir hfy-tags-rmap))) (if (and cache-entry (setq cache-hash (cadr cache-entry))) (maphash (lambda (K _V) (let ((stub (upcase (substring K 0 1)))) (if (member stub stub-list) nil ;; seen this already: NOOP (setq stub-list (cons stub stub-list) index-list (cons (hfy-prepare-index-i srcdir dstdir hfy-instance-file stub hfy-tags-rmap) index-list)) ))) cache-hash) ) index-list))) (defun hfy-subtract-maps (srcdir) "Internal function - strips definitions of tags from the instance map. SRCDIR is the directory being \"published\". See also `hfy-tags-cache', `hfy-tags-rmap'." (let ((new-list nil) (old-list nil) (def-list nil) (exc-list nil) (fwd-map (cadr (assoc srcdir hfy-tags-cache))) (rev-map (cadr (assoc srcdir hfy-tags-rmap ))) (taglist (cadr (assoc srcdir hfy-tags-sortl)))) (dolist (TAG taglist) (setq def-list (gethash TAG fwd-map) old-list (gethash TAG rev-map) exc-list (mapcar (lambda (P) (list (car P) (cadr P))) def-list) new-list nil) (dolist (P old-list) (or (member (list (car P) (cadr P)) exc-list) (push P new-list))) (puthash TAG new-list rev-map)))) (defun htmlfontify-run-etags (srcdir) "Load the etags cache for SRCDIR. See also `hfy-load-tags-cache'." (interactive "D source directory: ") (hfy-load-tags-cache (directory-file-name srcdir))) ;;(defun hfy-test-read-args (foo bar) ;; (interactive "D source directory: \nD target directory: ") ;; (message "foo: %S\nbar: %S" foo bar)) (defun hfy-save-kill-buffers (buffer-list &optional dstdir) (dolist (B buffer-list) (set-buffer B) (and dstdir (file-directory-p dstdir) (cd dstdir)) (save-buffer) (kill-buffer B))) ;;;###autoload (defun htmlfontify-copy-and-link-dir (srcdir dstdir &optional f-ext l-ext) "Trawl SRCDIR and write fontified-and-hyperlinked output in DSTDIR. F-EXT and L-EXT specify values for `hfy-extn' and `hfy-link-extn'.\n You may also want to set `hfy-page-header' and `hfy-page-footer'." (interactive "D source directory: \nD output directory: ") ;;(message "htmlfontify-copy-and-link-dir") (setq srcdir (directory-file-name srcdir)) (setq dstdir (directory-file-name dstdir)) (let ((source-files "SETME: list of source files, relative to srcdir") (tr-cache (assoc srcdir hfy-tags-rmap)) (hfy-extn (or f-ext ".html")) (hfy-link-extn (or l-ext ".html"))) ;; oops, forgot to load etags for srcdir: (if tr-cache nil (message "autoload of tags cache") (hfy-load-tags-cache srcdir) (setq tr-cache (assoc srcdir hfy-tags-rmap))) ;; clear out the old cache: (clrhash (cadr tr-cache)) (hfy-make-directory dstdir) (setq source-files (hfy-list-files srcdir)) (dolist (file source-files) (hfy-copy-and-fontify-file srcdir dstdir file)) (hfy-subtract-maps srcdir) (hfy-save-kill-buffers (hfy-prepare-index srcdir dstdir) dstdir) (hfy-save-kill-buffers (hfy-prepare-tag-map srcdir dstdir) dstdir) )) ;; name of the init file we want: (defun hfy-initfile () "Return the expected location of the htmlfontify specific init/custom fil= e." (let* ((file (or (getenv "HFY_INITFILE") ".hfy.el"))) (expand-file-name file "~") )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; incomplete as yet : transfer hook settings to hfy init file: ;; (defalias 'hfy-set-hooks 'custom-set-variables) ;; (defun hfy-pp-hook (H) ;; (and (string-match "-hook\\'" (symbol-name H)) ;; (boundp H) ;; (symbol-value H) ;; (insert (format "\n '(%S %S)" H (symbol-value H))) ;; ) ;; ) ;; (defun hfy-save-hooks () ;; (let ((custom-file (hfy-initfile))) ;; (custom-save-delete 'hfy-set-hooks) ;; (let ((standard-output (current-buffer))) ;; (princ "(hfy-set-hooks\n;;auto-generated, only one copy allowed\n") ;; (mapatoms 'hfy-pp-hook) ;; (insert "\n)") ;; ) ;; ) ;; ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defalias 'hfy-init-progn 'progn) (defun hfy-save-initvar (sym) (princ (format "(setq %s\n '" sym)) (pp (symbol-value sym)) (princ ")\n")) (defun htmlfontify-save-initfile () "Save the htmlfontify settings to the htmlfontify init file." (interactive) (let* ((start-pos nil) (custom-file (hfy-initfile)) (standard-output (find-file-noselect custom-file 'nowarn))) (save-excursion (custom-save-delete 'hfy-init-progn) (setq start-pos (point)) (princ "(hfy-init-progn\n;;auto-generated, only one copy allowed\n") ;; FIXME: This saving&restoring of global customization ;; variables can interfere with other customization settings for ;; those vars (in .emacs or in Customize). (mapc 'hfy-save-initvar '(auto-mode-alist interpreter-mode-alist)) (princ ")\n") (indent-region start-pos (point) nil)) (custom-save-all) )) (defun htmlfontify-load-initfile () "Load the htmlfontify specific init/custom file." (interactive) (let ((file (hfy-initfile))) (load file 'NOERROR nil nil) )) ;;;### (autoloads (hfy-fallback-colour-values htmlfontify-load-rgb-file) ;;;;;; "hfy-cmap" "hfy-cmap.el" "8dce008297f15826cc6ab82203c46fa6") ;;; Generated autoloads from hfy-cmap.el (autoload 'htmlfontify-load-rgb-file "hfy-cmap" "\ Load an X11 style rgb.txt FILE. Search `hfy-rgb-load-path' if FILE is not specified. Loads the variable `hfy-rgb-txt-colour-map', which is used by `hfy-fallback-colour-values'. \(fn &optional FILE)" t nil) (autoload 'hfy-fallback-colour-values "hfy-cmap" "\ Use a fallback method for obtaining the rgb values for a color. \(fn COLOUR-STRING)" nil nil) ;;;*** (provide 'htmlfontify) ;; Local Variables: ;; coding: utf-8 ;; End: ;;; htmlfontify.el ends here --=-=-= Content-Type: text/x-patch; charset=utf-8 Content-Disposition: attachment; filename=htmlfontify.el.patch Content-Transfer-Encoding: quoted-printable Content-Description: htmlfontify.el.patch --- a/htmlfontify.el 2011-10-31 12:50:26.812500000 +0530 +++ b/htmlfontify.el 2011-10-31 12:54:04.093750000 +0530 @@ -450,6 +450,12 @@ and so on." keep-overlays : More of a bell (or possibly whistle) than an optimization - If on, preserve overlay highlighting (cf ediff or goo-font-lock) as well as basic faces.= \n + body-text-only : Emit only body-text. In concrete terms, + 1. Suppress calls to `hfy-page-header'and + `hfy-page-footer' + 2. Pretend that `div-wrapper' option above is + turned off + 3. Don't enclose output in
 
tags And the following are planned but not yet available:\n kill-context-leak : Suppress hyperlinking between files highlighted by different modes.\n @@ -463,7 +469,8 @@ which can never slow you down, but may r (const :tag "skip-refontification" skip-refontification) (const :tag "kill-context-leak" kill-context-leak ) (const :tag "div-wrapper" div-wrapper ) - (const :tag "keep-overlays" keep-overlays )) + (const :tag "keep-overlays" keep-overlays ) + (const :tag "body-text-only" body-text-only )) :group 'htmlfontify :tag "optimizations") =20 @@ -1107,10 +1114,9 @@ See also `hfy-face-to-style-i', `hfy-fla =20 ;; construct an assoc of (stripped-name . "{ css-stuff-here }") pairs ;; from a face: -(defun hfy-face-to-css (fn) - "Take FN, a font or `defface' specification (cf `face-attr-construct') -and return a CSS style specification.\n -See also `hfy-face-to-style'." +(defun hfy-face-to-css-default (fn) + "Default handler for mapping faces to styles. +See also `hfy-face-to-css'." ;;(message "hfy-face-to-css");;DBUG (let* ((css-list (hfy-face-to-style fn)) (seen nil) @@ -1124,6 +1130,17 @@ See also `hfy-face-to-style'." css-list))) (cons (hfy-css-name fn) (format "{%s}" (apply 'concat css-text)))) ) =20 +(defvar hfy-face-to-css 'hfy-face-to-css-default + "Handler for mapping faces to styles. +The signature of the handler is of the form \(lambda (FN) ...\). +FN is a font or `defface' specification (cf +`face-attr-construct'). The handler should return a cons cell of +the form (STYLE-NAME . STYLE-SPEC). + +The default handler is `hfy-face-to-css-default'. + +See also `hfy-face-to-style'.") + (defalias 'hfy-prop-invisible-p (if (fboundp 'invisible-p) #'invisible-p (lambda (prop) @@ -1310,20 +1327,27 @@ The plists are returned in descending pr =20 ;; construct an assoc of (face-name . (css-name . "{ css-style }")) elemen= ts: (defun hfy-compile-stylesheet () - "Trawl the current buffer, construct and return a `hfy-sheet-assoc'." + "Trawl the current buffer, construct and return a `hfy-sheet-assoc'. +If `hfy-user-sheet-assoc' is currently bound then use it to +collect new styles discovered during this run. Otherwise create +a new assoc." ;;(message "hfy-compile-stylesheet");;DBUG (let ((pt (point-min)) ;; Make the font stack stay: ;;(hfy-tmpfont-stack nil) (fn nil) - (style nil)) + (style (and (boundp 'hfy-user-sheet-assoc) hfy-user-sheet-ass= oc))) (save-excursion (goto-char pt) (while (< pt (point-max)) (if (and (setq fn (hfy-face-at pt)) (not (assoc fn style))) - (push (cons fn (hfy-face-to-css fn)) style)) - (setq pt (next-char-property-change pt))) ) - (push (cons 'default (hfy-face-to-css 'default)) style))) + (push (cons fn (funcall hfy-face-to-css fn)) style)) + (setq pt (next-char-property-change pt)))) + (unless (assoc 'default style) + (push (cons 'default (funcall hfy-face-to-css 'default)) style)) + (when (boundp 'hfy-user-sheet-assoc) + (setq hfy-user-sheet-assoc style)) + style)) =20 (defun hfy-fontified-p () "`font-lock' doesn't like to say it's been fontified when in batch @@ -1424,7 +1448,7 @@ Returns a modified copy of FACE-MAP." (setq pt (next-char-property-change pt)) (setq pt-narrow (+ offset pt))) (if (and map (not (eq 'end (cdar map)))) - (push (cons (- (point-max) (point-min)) 'end) map))) + (push (cons (1+ (- (point-max) (point-min))) 'end) map))) (if (hfy-opt 'merge-adjacent-tags) (hfy-merge-adjacent-spans map) map)= )) =20 (defun hfy-buffer () @@ -1546,6 +1570,61 @@ Do not record undo information during ev (remove-text-properties (point-min) (point-max) '(hfy-show-trailing-whitespace))))) =20 +(defun hfy-begin-span (style text-block text-id text-begins-block-p) + "Default handler to begin a span of text. +Insert \"\". See +`hfy-begin-span-handler' for more information." + (when text-begins-block-p + (insert + (format "=E2=80=A6" te= xt-block))) + + (insert + (if text-block + (format "" style text-block tex= t-id) + (format "" style)))) + +(defun hfy-end-span () + "Default handler to end a span of text. +Insert \"\". See `hfy-end-span-handler' for more +information." + (insert "")) + +(defvar hfy-begin-span-handler 'hfy-begin-span + "Handler to begin a span of text. +The signature of the handler is \(lambda (STYLE TEXT-BLOCK +TEXT-ID TEXT-BEGINS-BLOCK-P) ...\). The handler must insert +appropriate tags to begin a span of text. + +STYLE is the name of the style that begins at point. It is +derived from the face attributes as part of `hfy-face-to-css' +callback. The other arguments TEXT-BLOCK, TEXT-ID, +TEXT-BEGINS-BLOCK-P are non-nil only if the buffer contains +invisible text. + +TEXT-BLOCK is a string that identifies a single chunk of visible +or invisible text of which the current position is a part. For +visible portions, it's value is \"nil\". For invisible portions, +it's value is computed as part of `hfy-invisible-name'. + +TEXT-ID marks a unique position within a block. It is set to +value of `point' at the current buffer position. + +TEXT-BEGINS-BLOCK-P is a boolean and is non-nil if the current +span also begins a invisible portion of text. + +An implementation can use TEXT-BLOCK, TEXT-ID, +TEXT-BEGINS-BLOCK-P to implement fold/unfold-on-mouse-click like +behaviour. + +The default handler is `hfy-begin-span'.") + +(defvar hfy-end-span-handler 'hfy-end-span + "Handler to end a span of text. +The signature of the handler is \(lambda () ...\). The handler +must insert appropriate tags to end a span of text. + +The default handler is `hfy-end-span'.") + (defun hfy-fontify-buffer (&optional srcdir file) "Implement the guts of `htmlfontify-buffer'. SRCDIR, if set, is the directory being htmlfontified. @@ -1633,23 +1712,19 @@ FILE, if set, is the file name." (or (get-text-property pt 'hfy-linkp) (get-text-property pt 'hfy-endl ))) (if (eq 'end fn) - (insert "") + (funcall hfy-end-span-handler) (if (not (and srcdir file)) nil (when move-link (remove-text-properties (point) (1+ (point)) '(hfy-endl nil)) (put-text-property pt (1+ pt) 'hfy-endl t) )) ;; if we have invisible blocks, we need to do some extra magic: - (if invis-ranges - (let ((iname (hfy-invisible-name pt invis-ranges)) - (fname (hfy-lookup fn css-sheet ))) - (when (assq pt invis-ranges) - (insert - (format "" inam= e)) - (insert "=E2=80=A6")) - (insert - (format "" fname inam= e pt))) - (insert (format "" (hfy-lookup fn css-she= et)))) + (funcall hfy-begin-span-handler + (hfy-lookup fn css-sheet) + (and invis-ranges + (format "%s" (hfy-invisible-name pt invis-ranges))) + (and invis-ranges pt) + (and invis-ranges (assq pt invis-ranges))) (if (not move-link) nil ;;(message "removing prop2 @ %d" (point)) (if (remove-text-properties (point) (1+ (point)) '(hfy-endl ni= l)) @@ -1697,23 +1772,41 @@ FILE, if set, is the file name." ;; so we have to do this after we use said properties: ;; (message "munging dangerous characters") (hfy-html-dekludge-buffer) + (unless (hfy-opt 'body-text-only) ;; insert the stylesheet at the top: (goto-char (point-min)) + ;;(message "inserting stylesheet") (insert (hfy-sprintf-stylesheet css-sheet file)) + (if (hfy-opt 'div-wrapper) (insert "
")) (insert "\n
")
     (goto-char (point-max))
     (insert "
\n") (if (hfy-opt 'div-wrapper) (insert "
")) ;;(message "inserting footer") - (insert (funcall hfy-page-footer file)) + (insert (funcall hfy-page-footer file))) ;; call any post html-generation hooks: (run-hooks 'hfy-post-html-hooks) ;; return the html buffer (set-buffer-modified-p nil) html-buffer)) =20 +(defun htmlfontify-string (string) + "Take a STRING and return a fontified version of it. +It is assumed that STRING has text properties that allow it to be +fontified. This is a simple convenience wrapper around +`htmlfontify-buffer'." + (let* ((hfy-optimisations-1 (copy-list hfy-optimisations)) + (hfy-optimisations (add-to-list 'hfy-optimisations-1 + 'skip-refontification))) + (with-temp-buffer + (insert string) + (htmlfontify-buffer) + (prog1 (buffer-string) + (setq buffer-modified-p nil) + (kill-buffer))))) + (defun hfy-force-fontification () "Try to force font-locking even when it is optimized away." (run-hooks 'hfy-init-kludge-hook) --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-htmlfontify.el-Add-new-output-option-body-text-only.patch >From b15e66c86024cc5f0350e96d26197c60241954ec Mon Sep 17 00:00:00 2001 From: Jambunathan K Date: Fri, 19 Aug 2011 01:44:19 +0530 Subject: [PATCH 1/5] htmlfontify.el: Add new output option - `body-text-only' * contrib/lisp/htmlfontify.el (hfy-optimisations): Define new option `body-text-only' (hfy-fontify-buffer): Honor above setting. --- contrib/lisp/htmlfontify.el | 34 ++++++++++++++++++++++------------ 1 files changed, 22 insertions(+), 12 deletions(-) diff --git a/contrib/lisp/htmlfontify.el b/contrib/lisp/htmlfontify.el index c8e9558..5415e58 100755 --- a/contrib/lisp/htmlfontify.el +++ b/contrib/lisp/htmlfontify.el @@ -450,6 +450,12 @@ and so on." keep-overlays : More of a bell (or possibly whistle) than an optimization - If on, preserve overlay highlighting (cf ediff or goo-font-lock) as well as basic faces.\n + body-text-only : Emit only body-text. In concrete terms, + 1. Suppress calls to `hfy-page-header'and + `hfy-page-footer' + 2. Pretend that `div-wrapper' option above is + turned off + 3. Don't enclose output in
 
tags And the following are planned but not yet available:\n kill-context-leak : Suppress hyperlinking between files highlighted by different modes.\n @@ -463,7 +469,8 @@ which can never slow you down, but may result in incomplete fontification." (const :tag "skip-refontification" skip-refontification) (const :tag "kill-context-leak" kill-context-leak ) (const :tag "div-wrapper" div-wrapper ) - (const :tag "keep-overlays" keep-overlays )) + (const :tag "keep-overlays" keep-overlays ) + (const :tag "body-text-only" body-text-only )) :group 'htmlfontify :tag "optimizations") @@ -1697,17 +1704,20 @@ FILE, if set, is the file name." ;; so we have to do this after we use said properties: ;; (message "munging dangerous characters") (hfy-html-dekludge-buffer) - ;; insert the stylesheet at the top: - (goto-char (point-min)) - ;;(message "inserting stylesheet") - (insert (hfy-sprintf-stylesheet css-sheet file)) - (if (hfy-opt 'div-wrapper) (insert "
")) - (insert "\n
")
-    (goto-char (point-max))
-    (insert "
\n") - (if (hfy-opt 'div-wrapper) (insert "
")) - ;;(message "inserting footer") - (insert (funcall hfy-page-footer file)) + (unless (hfy-opt 'body-text-only) + ;; insert the stylesheet at the top: + (goto-char (point-min)) + + ;;(message "inserting stylesheet") + (insert (hfy-sprintf-stylesheet css-sheet file)) + + (if (hfy-opt 'div-wrapper) (insert "
")) + (insert "\n
")
+      (goto-char (point-max))
+      (insert "
\n") + (if (hfy-opt 'div-wrapper) (insert "
")) + ;;(message "inserting footer") + (insert (funcall hfy-page-footer file))) ;; call any post html-generation hooks: (run-hooks 'hfy-post-html-hooks) ;; return the html buffer -- 1.7.5.1 --=-=-= Content-Type: text/x-patch; charset=utf-8 Content-Disposition: attachment; filename=0002-htmlfontify.el-Allow-customization-of-begin-and-end-.patch Content-Transfer-Encoding: quoted-printable >From 6670131285304500156b6e2f557f7728b9ad5e1a Mon Sep 17 00:00:00 2001 From: Jambunathan K Date: Fri, 19 Aug 2011 01:45:59 +0530 Subject: [PATCH 2/5] htmlfontify.el: Allow customization of begin and end span markers * contrib/lisp/htmlfontify.el (hfy-begin-span, hfy-end-span): New routines factored out form hfy-fontify-buffer. (hfy-begin-span-handler, hfy-end-span-handler): New variables that permit insertion of custom tags. (hfy-fontify-buffer): Use above handlers. --- contrib/lisp/htmlfontify.el | 73 ++++++++++++++++++++++++++++++++++++---= --- 1 files changed, 62 insertions(+), 11 deletions(-) diff --git a/contrib/lisp/htmlfontify.el b/contrib/lisp/htmlfontify.el index 5415e58..b4b1af2 100755 --- a/contrib/lisp/htmlfontify.el +++ b/contrib/lisp/htmlfontify.el @@ -1553,6 +1553,61 @@ Do not record undo information during evaluation of = BODY." (remove-text-properties (point-min) (point-max) '(hfy-show-trailing-whitespace))))) =20 +(defun hfy-begin-span (style text-block text-id text-begins-block-p) + "Default handler to begin a span of text. +Insert \"\". See +`hfy-begin-span-handler' for more information." + (when text-begins-block-p + (insert + (format "=E2=80=A6" te= xt-block))) + + (insert + (if text-block + (format "" style text-block tex= t-id) + (format "" style)))) + +(defun hfy-end-span () + "Default handler to end a span of text. +Insert \"\". See `hfy-end-span-handler' for more +information." + (insert "")) + +(defvar hfy-begin-span-handler 'hfy-begin-span + "Handler to begin a span of text. +The signature of the handler is \(lambda (STYLE TEXT-BLOCK +TEXT-ID TEXT-BEGINS-BLOCK-P) ...\). The handler must insert +appropriate tags to begin a span of text. + +STYLE is the name of the style that begins at point. It is +derived from the face attributes as part of `hfy-face-to-css' +callback. The other arguments TEXT-BLOCK, TEXT-ID, +TEXT-BEGINS-BLOCK-P are non-nil only if the buffer contains +invisible text. + +TEXT-BLOCK is a string that identifies a single chunk of visible +or invisible text of which the current position is a part. For +visible portions, it's value is \"nil\". For invisible portions, +it's value is computed as part of `hfy-invisible-name'. + +TEXT-ID marks a unique position within a block. It is set to +value of `point' at the current buffer position. + +TEXT-BEGINS-BLOCK-P is a boolean and is non-nil if the current +span also begins a invisible portion of text. + +An implementation can use TEXT-BLOCK, TEXT-ID, +TEXT-BEGINS-BLOCK-P to implement fold/unfold-on-mouse-click like +behaviour. + +The default handler is `hfy-begin-span'.") + +(defvar hfy-end-span-handler 'hfy-end-span + "Handler to end a span of text. +The signature of the handler is \(lambda () ...\). The handler +must insert appropriate tags to end a span of text. + +The default handler is `hfy-end-span'.") + (defun hfy-fontify-buffer (&optional srcdir file) "Implement the guts of `htmlfontify-buffer'. SRCDIR, if set, is the directory being htmlfontified. @@ -1640,23 +1695,19 @@ FILE, if set, is the file name." (or (get-text-property pt 'hfy-linkp) (get-text-property pt 'hfy-endl ))) (if (eq 'end fn) - (insert "") + (funcall hfy-end-span-handler) (if (not (and srcdir file)) nil (when move-link (remove-text-properties (point) (1+ (point)) '(hfy-endl nil)) (put-text-property pt (1+ pt) 'hfy-endl t) )) ;; if we have invisible blocks, we need to do some extra magic: - (if invis-ranges - (let ((iname (hfy-invisible-name pt invis-ranges)) - (fname (hfy-lookup fn css-sheet ))) - (when (assq pt invis-ranges) - (insert - (format "" inam= e)) - (insert "=E2=80=A6")) - (insert - (format "" fname inam= e pt))) - (insert (format "" (hfy-lookup fn css-she= et)))) + (funcall hfy-begin-span-handler + (hfy-lookup fn css-sheet) + (and invis-ranges + (format "%s" (hfy-invisible-name pt invis-ranges))) + (and invis-ranges pt) + (and invis-ranges (assq pt invis-ranges))) (if (not move-link) nil ;;(message "removing prop2 @ %d" (point)) (if (remove-text-properties (point) (1+ (point)) '(hfy-endl ni= l)) --=20 1.7.5.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0003-htmlfontify.el-Allow-customization-of-face-to-style-.patch >From 0c74cd517e6ecc41bebf6053f0512d42b13dcb77 Mon Sep 17 00:00:00 2001 From: Jambunathan K Date: Fri, 19 Aug 2011 01:47:48 +0530 Subject: [PATCH 3/5] htmlfontify.el: Allow customization of face to style mappings * contrib/lisp/htmlfontify.el (hfy-face-to-css-default): Same as the earlier hfy-face-to-css. (hfy-face-to-css): Re-defined to be a variable. (hfy-compile-stylesheet): Related changes. --- contrib/lisp/htmlfontify.el | 22 ++++++++++++++++------ 1 files changed, 16 insertions(+), 6 deletions(-) diff --git a/contrib/lisp/htmlfontify.el b/contrib/lisp/htmlfontify.el index b4b1af2..3f5bdbd 100755 --- a/contrib/lisp/htmlfontify.el +++ b/contrib/lisp/htmlfontify.el @@ -1114,10 +1114,9 @@ See also `hfy-face-to-style-i', `hfy-flatten-style'." ;; construct an assoc of (stripped-name . "{ css-stuff-here }") pairs ;; from a face: -(defun hfy-face-to-css (fn) - "Take FN, a font or `defface' specification (cf `face-attr-construct') -and return a CSS style specification.\n -See also `hfy-face-to-style'." +(defun hfy-face-to-css-default (fn) + "Default handler for mapping faces to styles. +See also `hfy-face-to-css'." ;;(message "hfy-face-to-css");;DBUG (let* ((css-list (hfy-face-to-style fn)) (seen nil) @@ -1131,6 +1130,17 @@ See also `hfy-face-to-style'." css-list))) (cons (hfy-css-name fn) (format "{%s}" (apply 'concat css-text)))) ) +(defvar hfy-face-to-css 'hfy-face-to-css-default + "Handler for mapping faces to styles. +The signature of the handler is of the form \(lambda (FN) ...\). +FN is a font or `defface' specification (cf +`face-attr-construct'). The handler should return a cons cell of +the form (STYLE-NAME . STYLE-SPEC). + +The default handler is `hfy-face-to-css-default'. + +See also `hfy-face-to-style'.") + (defalias 'hfy-prop-invisible-p (if (fboundp 'invisible-p) #'invisible-p (lambda (prop) @@ -1328,9 +1338,9 @@ The plists are returned in descending priority order." (goto-char pt) (while (< pt (point-max)) (if (and (setq fn (hfy-face-at pt)) (not (assoc fn style))) - (push (cons fn (hfy-face-to-css fn)) style)) + (push (cons fn (funcall hfy-face-to-css fn)) style)) (setq pt (next-char-property-change pt))) ) - (push (cons 'default (hfy-face-to-css 'default)) style))) + (push (cons 'default (funcall hfy-face-to-css 'default)) style))) (defun hfy-fontified-p () "`font-lock' doesn't like to say it's been fontified when in batch -- 1.7.5.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0004-htmlfontify.el-Add-support-for-building-stylesheet-o.patch >From c71fb16dfc24f25a12bf5d84fac2f3d9d427e06a Mon Sep 17 00:00:00 2001 From: Jambunathan K Date: Fri, 19 Aug 2011 01:49:05 +0530 Subject: [PATCH 4/5] htmlfontify.el: Add support for building stylesheet over multiple runs * contrib/lisp/htmlfontify.el (hfy-compile-stylesheet): Modified. Allow stylesheet to be built over multiple runs. This is made possible by having the caller let bind a special variable hfy-user-sheet-assoc. --- contrib/lisp/htmlfontify.el | 15 +++++++++++---- 1 files changed, 11 insertions(+), 4 deletions(-) diff --git a/contrib/lisp/htmlfontify.el b/contrib/lisp/htmlfontify.el index 3f5bdbd..6a4d62f 100755 --- a/contrib/lisp/htmlfontify.el +++ b/contrib/lisp/htmlfontify.el @@ -1327,20 +1327,27 @@ The plists are returned in descending priority order." ;; construct an assoc of (face-name . (css-name . "{ css-style }")) elements: (defun hfy-compile-stylesheet () - "Trawl the current buffer, construct and return a `hfy-sheet-assoc'." + "Trawl the current buffer, construct and return a `hfy-sheet-assoc'. +If `hfy-user-sheet-assoc' is currently bound then use it to +collect new styles discovered during this run. Otherwise create +a new assoc." ;;(message "hfy-compile-stylesheet");;DBUG (let ((pt (point-min)) ;; Make the font stack stay: ;;(hfy-tmpfont-stack nil) (fn nil) - (style nil)) + (style (and (boundp 'hfy-user-sheet-assoc) hfy-user-sheet-assoc))) (save-excursion (goto-char pt) (while (< pt (point-max)) (if (and (setq fn (hfy-face-at pt)) (not (assoc fn style))) (push (cons fn (funcall hfy-face-to-css fn)) style)) - (setq pt (next-char-property-change pt))) ) - (push (cons 'default (funcall hfy-face-to-css 'default)) style))) + (setq pt (next-char-property-change pt)))) + (unless (assoc 'default style) + (push (cons 'default (funcall hfy-face-to-css 'default)) style)) + (when (boundp 'hfy-user-sheet-assoc) + (setq hfy-user-sheet-assoc style)) + style)) (defun hfy-fontified-p () "`font-lock' doesn't like to say it's been fontified when in batch -- 1.7.5.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0005-htmlfontify.el-Add-htmlfontify-string-fix-a-bug-in-f.patch >From a81bb6fa6afce64badbaa4c47eb77073fc807ee2 Mon Sep 17 00:00:00 2001 From: Jambunathan K Date: Fri, 19 Aug 2011 01:50:23 +0530 Subject: [PATCH 5/5] htmlfontify.el: Add htmlfontify-string & fix a bug in fontification * htmlfontify.el (htmlfontify-string): New defun. (hfy-compile-face-map): Make sure that the last char in the buffer is correctly fontified. --- contrib/lisp/htmlfontify.el | 17 ++++++++++++++++- 1 files changed, 16 insertions(+), 1 deletions(-) diff --git a/contrib/lisp/htmlfontify.el b/contrib/lisp/htmlfontify.el index 6a4d62f..5b86d98 100755 --- a/contrib/lisp/htmlfontify.el +++ b/contrib/lisp/htmlfontify.el @@ -1448,7 +1448,7 @@ Returns a modified copy of FACE-MAP." (setq pt (next-char-property-change pt)) (setq pt-narrow (+ offset pt))) (if (and map (not (eq 'end (cdar map)))) - (push (cons (- (point-max) (point-min)) 'end) map))) + (push (cons (1+ (- (point-max) (point-min))) 'end) map))) (if (hfy-opt 'merge-adjacent-tags) (hfy-merge-adjacent-spans map) map))) (defun hfy-buffer () @@ -1792,6 +1792,21 @@ FILE, if set, is the file name." (set-buffer-modified-p nil) html-buffer)) +(defun htmlfontify-string (string) + "Take a STRING and return a fontified version of it. +It is assumed that STRING has text properties that allow it to be +fontified. This is a simple convenience wrapper around +`htmlfontify-buffer'." + (let* ((hfy-optimisations-1 (copy-list hfy-optimisations)) + (hfy-optimisations (add-to-list 'hfy-optimisations-1 + 'skip-refontification))) + (with-temp-buffer + (insert string) + (htmlfontify-buffer) + (prog1 (buffer-string) + (setq buffer-modified-p nil) + (kill-buffer))))) + (defun hfy-force-fontification () "Try to force font-locking even when it is optimized away." (run-hooks 'hfy-init-kludge-hook) -- 1.7.5.1 --=-=-=--