;;; tidy-xhtml.el --- Interface to the HTML Tidy program ;; Copyright (C) 2001, 2002, 2003, 2006, 2007 by Free Software ;; Foundation, Inc. ;; Emacs Lisp Archive Entry ;; Ancestors filename: tidy.el ;; Author: Kahlil (Kal) HODGSON ;; Author: Lennart Borgman (lennart O borgman A gmail O com) ;; Original X-URL: http://www.emacswiki.org/elisp/tidy.el ;; Last-Updated: 2008-03-09T13:10:06+0100 Sun (defconst tidy-xhtml:version "2.25") ;; Keywords: languages ;; This file is NOT part of GNU Emacs. ;; This file 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 2, or (at your option) ;; any later version. ;; This file 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; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;;; Commentary: ;; Provides a simple interface to the HTML Tidy program -- a free ;; utility that can fix common errors in your mark-up and clean up ;; sloppy editing automatically. See ;; ;; ;; ;; for more details. This package provides the following functions: ;; ;; `tidy-buffer', ;; `tidy-region', ;; `tidy-tree', ;; `tidy-html-site', ;; `tidy-parse-config-file', ;; `tidy-save-settings', ;; `tidy-describe-options', ;; `tidy-show-xhtml-options', ;; `tidy-set-xhtml-options', ;; ;; These can be invoked interactively (using M-x) or via the menu-bar. ;; The function `tidy-buffer' sends the current buffer to HTML Tidy, ;; replacing the existing contents with a "tidied" version. If ;; `tidy-buffer' is given a prefix argument, tidy operates on the ;; current region, ignoring mark-up outside ... tags ;; (useful for writhing cgi scripts in Pearl). Warnings and errors ;; are presented in a compilation buffer to facilitate tracking down ;; necessary changes (e.g. C-x ` is bound to `next-error'). ;; ;; This package also provides menu-bar support for setting Tidy's many ;; options, and includes support for Tidy configuration files. The ;; function `tidy-parse-config-file' will synchronise options ;; displayed in the menu-bar with the settings in `tidy-config-file'. ;; This is normally called by the load-hook for your HTML editing mode ;; (see installation instructions below). The function ;; `tidy-save-settings' will save the current option settings to your ;; `tidy-config-file'. Finally `tidy-describe-options' allows you to ;; browse the documentation strings associated with each option. ;;; ;;;; Installation: ;; This package assumes you have and up-to-date HTML Tidy program ;; installed on your system. See the URL above for instructions on ;; how to do this. To set up this support package, first place the ;; "tidy.el" file somewhere in your `load-path' and open it in Emacs. ;; Byte-compile and load this package using the command ;; ;; M-x emacs-lisp-byte-compile-and-load ;; ;; Next customise the variables `tidy-config-file', `tidy-temp-dir' ;; `tidy-shell-program', `tidy-menu-lock' and `tidy-menu-x-position' ;; ;; M-x customize-group tidy ;; ;; Now add the following autoloads to your ".emacs.el" file: ;; ;; (autoload 'tidy-buffer "tidy" "Run Tidy HTML parser on current buffer" t) ;; (autoload 'tidy-parse-config-file "tidy" "Parse the `tidy-config-file'" t) ;; (autoload 'tidy-save-settings "tidy" "Save settings to `tidy-config-file'" t) ;; (autoload 'tidy-build-menu "tidy" "Install an options menu for HTML Tidy." t) ;; ;; If you use html-mode to edit HTML files then add something like ;; this as well ;; (defun my-html-mode-hook () "Customize my html-mode." ;; (tidy-build-menu html-mode-map) ;; (local-set-key [(control c) (control c)] 'tidy-buffer) ;; (setq sgml-validate-command "tidy")) ;; ;; (add-hook 'html-mode-hook 'my-html-mode-hook) ;; This will set up a "tidy" menu in the menu bar and bind the key ;; sequence "C-c C-c" to `tidy-buffer' in html-mode (normally bound to ;; `validate-buffer'). ;; ;; For other modes (like html-helper-mode) simple change the variables ;; `html-mode-hook' and `html-mode-map' to whatever is appropriate e.g. ;; (defun my-html-mode-hook () "Customize my html-helper-mode." ;; (tidy-build-menu html-helper-mode-map) ;; (local-set-key [(control c) (control c)] 'tidy-buffer) ;; (setq sgml-validate-command "tidy")) ;; ;; (add-hook 'html-helper-mode-hook 'my-html-mode-hook) ;; Finally, restart Emacs and open an HTML file to test-drive the tidy ;; package. For people new to HTML tidy check that the option "markup" ;; under the "Input/Output" sub menu is set. You can read the ;; documentation on this option via the menu item "Describe Options". ;; ;; Enjoy! ;;;; New Features: ;; ;; 0. Now compatible with CVS version of Tidy as at 22 May 2003 ;; 1. Improved menu support to facillitate incorporting new options ;; 2. Menu lock option makes menu stick when toggling options. ;; 3. Now runs on XEmacs!! ;; 4. Uses error file rather than std-error to retrieve errors (this ;; fixes some odd pop up behaviour) ;; 5. minor bug fix (empty config files) ;; 6. handle buffer modified query in error buffer better ;; 7. make it impossible to mark the error buffer as modified ;; 8. Added the variable `tidy-temp-directory'. ;; 9. Bugfix in tidy-buffer: call find-file-noselect with NOWARN ;; 10. Removes ^M on w32. ;; 11. Changed defcustom types to 'file and 'directory. ;; 12. Added `tidy-set-xhtml-options'. ;; 13. Tried to handle encodings. ;; 14. Added the function `tidy-region'. ;; 15. Added ediff support. ;; 16. Added `tidy-tree'. ;; 17. Added `tidy-html-site'. ;;;; ToDo: ;; ;; 1. Automatically set "char-encoding" according to the buffer encoding ;; 2. Should check value of HTML_TIDY environment variable. ;;;; Bugs: ;; Requires a version of HTML Tidy that understands the "-f" ;; "-config" "--show-body-only" command line options e.g. source-forge ;; pre-release. ;; ;; There may be a bug with setting doctypes. I don't use this feature ;; yet and, well, don't really know how its supposed to work:-) ;; ;; Care with character encodings!! ;;; History: ;; 2006-05-09: New features 10-17 above. ;; - Lennart Borgman ;; 2006-05-24: Fixed some errors spotted by Andreas Roethler. ;;;; Credits ;; This code was inspired by an Emacs "tip" suggested by Pete Gelbman. ;; ;; Thanks to Hans-Michael Stahl for comments regarding XEmacs ;; compatibility. ;; ;; Thanks to Thomas Baumann for bugfix's in `tidy-parse-config-file' ;; and `tidy-buffer'. ;; ;; Thanks to Chris Lott for comments regarding installation and menu ;; display ;; ;; Thanks to Jeroen Baekelandt for noting a problem with ange-ftp and ;; inspiring `tidy-temp-directory'. ;;;; Code: ;;;;; Forward references (stuff which must come first) (eval-when-compile (require 'cl)) (eval-when-compile (require 'ediff)) (eval-when-compile (require 'mumamo nil t)) (eval-when-compile (require 'ourcomments-util nil t)) (eval-when-compile (add-to-list 'load-path default-directory)) (eval-when-compile (require 'html-site nil t)) (require 'easymenu) ;; This makes menus so much easier! (require 'compile) ;; To make the error buffer more sexy (require 'cus-edit) ;; Just for face custom-button (require 'help-mode) ;; The following two are functions so that the same compiled code will ;; work in both situations (time cost is negligible) (defsubst tidy-xemacs-p () "Return t iff we are running XEmacs this session." (not (null (string-match "^XEmacs.*" (emacs-version))))) (defsubst tidy-windows-p () "Return t iff we are running on a Windows system." (memq system-type '(emx win32 w32 mswindows ms-dos windows-nt))) ;; function definitions ;; XEmacs (defalias 'tidy-x-event-function 'event-function) (defalias 'tidy-x-event-object 'event-object) (defalias 'tidy-x-find-menu-item 'find-menu-item) (defalias 'tidy-x-get-popup-menu-response 'get-popup-menu-response) (defalias 'tidy-x-make-event 'make-event) (defalias 'tidy-x-misc-user-event-p 'misc-user-event-p) ;;;;; User Variables ;;;###autoload (defgroup tidy nil "Provides a simple interface to the HTML Tidy program -- a free utility that can fix common errors in your mark-up and clean up sloppy editing automatically. See for more details. This package provides the following functions: `tidy-buffer', `tidy-parse-config-file', `tidy-save-settings', and `tidy-describe-options', These can be invoked interactively (using M-x) or via the menu-bar. The function `tidy-buffer' sends the current buffer to HTML Tidy, replacing the existing contents with a \"tidied\" version. If `tidy-buffer' is given a prefix argument, tidy operates on the current region, ignoring mark-up outside ... tags \(useful for writhing cgi scripts in Pearl). Warnings and errors are presented in a compilation buffer to facilitate tracking down necessary changes (e.g. C-x ` is bound to `next-error'). This package also provides menu-bar support for setting Tidy's many options, and includes support for Tidy configuration files. The function `tidy-parse-config-file' will synchronise options displayed in the menu-bar with the settings in `tidy-config-file'. This is normally called by the load-hook for your HTML editing mode \(see installation instructions below). The function `tidy-save-settings' will save the current option settings to your `tidy-config-file'. Finally `tidy-describe-options' allows you to browse the documentation strings associated with each option. " :group 'nxhtml :group 'hypermedia) ;; (defcustom tidy-use-ediff nil ;; "If non-nil call ediff in `tidy-buffer' instead of replacing." ;; :group 'tidy ;; :type 'boolean) (defvar tidy-warnings 0) (defvar tidy-errors 0) (defvar tidy-message nil) ;;(defvar tidy-batch-buffer nil) (defvar tidy-batch-last-file nil) (defvar tidy-default-config-file "~/.tidyrc") (defvar tidy-config-file-parsed nil) (defcustom tidy-config-file tidy-default-config-file "Path to your default tidy configuration file. This is used by `tidy-parse-config-file' to synchronise Tidy's behaviour inside Emacs with its behaviour outside, and by `tidy-save-settings' to set your configuration file from within Emacs. If you never want this to happen, set `tidy-config-file' to \"\"." :group 'tidy :type 'file :set (lambda (symbol value) (set-default symbol value) (if (file-readable-p value) ;; Just set the default values here: ;;(tidy-parse-config-file) ;; Just tell we need to parse: (setq tidy-config-file-parsed nil) (if (file-exists-p value) (lwarn '(tidy-config-file) :warning "Tidy config file not readable: %s" value) (unless (string= value tidy-default-config-file) (lwarn '(tidy-config-file) :warning "Tidy config file not found: %s" value)))))) (defcustom tidy-shell-program "tidy" "The HTML program." :group 'tidy :type '(choice (file :must-match t) (string :tag "File name (searched for in path): ")) :set (lambda (symbol value) (set-default symbol value) (unless (string= value "tidy") (or (file-executable-p value) (executable-find value) (lwarn '(tidy-shell-program) :error "Tidy program not found: %s" value))))) (defcustom tidy-temp-directory temporary-file-directory "Directory where tidy places its temp files. The default is the current directory which works fine unless you are operating on remote files via `ange-ftp' and its ilk, in which case it will try to place the temp files on the remote server (and will probably fail). If this is the case try setting this variable to something like \"/tmp/\" or \"/var/tmp/\"." :group 'tidy :type 'directory :set-after '(temporary-file-directory)) (defcustom tidy-menu-lock t " *Non-nil means menu is locked (i.e. doesn't pop down) when selecting toggle and radio options. See also `tidy-menu-x-position'." :type 'boolean :group 'tidy) (defcustom tidy-menu-x-position 211 "Specify menu position height in pixels. This variable is used to set the horizontal position of the locked menu, so don't forget to adjust it if menu position is not ok. See also `tidy-menu-lock'." :type 'integer :group 'tidy) ;;;;; Local Variables (defvar tidy-debug nil "If t then we rebuild everything on reload. Useful for debugging.") ;;(eval-when-compile (setq tidy-debug t)) (defun tidy-toggle-debug () "Toggle value of tidy-debug." (interactive) (message "tidy-debug is %s" (setq tidy-debug (not tidy-debug)))) ;; (defun tidy-boolean-option-value (symbol) ;; "Return t when the symbol's value is \"yes\"." ;; (let ((name (symbol-name symbol))) ;; (assert (string= "tidy-" (substring name 0 5))) ;; (setq name (substring name 5)) ;; (let ((entry (assoc name tidy-options-alist))) ;; (assert (string= "Boolean" (nth 2 entry))))) ;; (when (symbol-value symbol) ;; (string= (symbol-value symbol)))) (defvar tidy-options-alist nil "An alist containing all valid tidy options. Each element is a list of the form (NAME, SUB-MENU, VALUE-TYPE, DEFAULT-VALUE, DOC-STRING). This is used to automatically construct variables and a menu bar. To add new or modify exiting options simply modify this list.") ;; Fix-me: built the options list dynamically, point to ;; http://tidy.sourceforge.net/docs/quickref.html for help (defun tidy-build-options-alist () (when (and tidy-shell-program (executable-find tidy-shell-program)) (let ((outbuf (get-buffer-create "* Tidy options *"))) (call-process tidy-shell-program nil ;; No input outbuf ;; Output here nil ;; Do not display "-help-config") (switch-to-buffer outbuf)))) (when (or (null tidy-options-alist) tidy-debug) (setq tidy-options-alist '( ("add-xml-decl" "Fix Markup" "Boolean" "no" " Type: Boolean Default: no Example: y/n, yes/no, t/f, true/false, 1/0 This option specifies if Tidy should add the XML declaration when outputting XML or XHTML. Note that if the input already includes an declaration then this option will be ignored.") ;; ("add-xml-pi" "Fix Markup" "Boolean" "no" ;; " ;; Type: Boolean ;; Default: no ;; Example: y/n, yes/no, t/f, true/false, 1/0 ;; This option is the same as the add-xml-decl option.") ("add-xml-space" "Fix Markup" "Boolean" "no" " Type: Boolean Default: no Example: y/n, yes/no, t/f, true/false, 1/0 This option specifies if Tidy should add xml:space=\"preserve\" to elements such as
,