summaryrefslogtreecommitdiffstats
path: root/emacs.d/nxhtml/nxhtml/tidy-xhtml.el
diff options
context:
space:
mode:
Diffstat (limited to 'emacs.d/nxhtml/nxhtml/tidy-xhtml.el')
-rw-r--r--emacs.d/nxhtml/nxhtml/tidy-xhtml.el2921
1 files changed, 2921 insertions, 0 deletions
diff --git a/emacs.d/nxhtml/nxhtml/tidy-xhtml.el b/emacs.d/nxhtml/nxhtml/tidy-xhtml.el
new file mode 100644
index 0000000..1c2cdd4
--- /dev/null
+++ b/emacs.d/nxhtml/nxhtml/tidy-xhtml.el
@@ -0,0 +1,2921 @@
+;;; 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 <dorge@tpg.com.au>
+;; 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
+;;
+;; <http://tidy.sourceforge.net/>
+;;
+;; 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 <BODY>...</BODY> 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 <RET>
+;;
+;; 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 <RET> tidy <RET>
+;;
+;; 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
+
+ <http://tidy.sourceforge.net/>
+
+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 <BODY>...</BODY> 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 <?xml
+... ?> 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 <PRE>, <STYLE> and <SCRIPT> when generating XML. This is needed if
+the whitespace in such elements is to be parsed appropriately without
+having access to the DTD.")
+
+ ("alt-text" "Fix Markup" "String" ""
+ "
+Type: String
+Default: -none-
+
+This option specifies the default \"alt=\" text Tidy uses for <IMG>
+attributes. This feature is dangerous as it suppresses further
+accessibility warnings. You are responsible for making your documents
+accessible to people who can not see the images!")
+
+ ("ascii-chars" "Fix Markup" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+Can be used to modify behavior of -c (--clean yes) option.
+Defaults to \"yes\" when using -c. Set to \"no\" to prevent
+converting &emdash;, &rdquo;, and other named character entities
+to their ascii equivalents.")
+
+ ("assume-xml-procins" "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 change the parsing of processing
+instructions to require ?> as the terminator rather than >. This option is
+automatically set if the input is in XML.")
+
+ ("bare" "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 strip Microsoft specific HTML from
+Word 2000 documents, and output spaces rather than non-breaking spaces
+where they exist in the input.")
+
+ ("break-before-br" "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 output a line break before each <BR>
+element.")
+
+ ("char-encoding" "Encoding" "Encoding" "ascii"
+ "
+Type: Encoding
+Default: ascii
+Example: ascii, latin1, raw, utf8, iso2022, mac, win1252
+
+This option specifies the character encoding Tidy uses for both the input
+and output. Possible values are: ascii, latin1, raw, utf8, iso2022, mac,
+win1252. For ascii, Tidy will accept Latin-1 (ISO-8859-1) character
+values, but will use entities for all characters whose value > 127. For
+raw, Tidy will output values above 127 without translating them into
+entities. For latin1, characters above 255 will be written as
+entities. For utf8, Tidy assumes that both input and output is encoded as
+UTF-8. You can use iso2022 for files encoded using the ISO-2022 family of
+encodings e.g. ISO-2022-JP. For mac and win1252, Tidy will accept vendor
+specific character values, but will use entities for all characters whose
+value > 127.")
+
+ ("clean" "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 strip out surplus presentational tags
+and attributes replacing them by style rules and structural markup as
+appropriate. It works well on the HTML saved by Microsoft Office products.")
+
+ ("doctype" "Fix Markup" "DocType" "auto"
+ "
+Type: DocType
+Default: auto
+Example: auto, omit, strict, loose, transitional, user specified fpi \(string\)
+
+This option specifies the DOCTYPE declaration generated by Tidy. If set to
+\"omit\" the output won't contain a DOCTYPE declaration. If set to \"auto\"
+\(the default\) Tidy will use an educated guess based upon the contents of
+the document. If set to \"strict\", Tidy will set the DOCTYPE to the strict
+DTD. If set to \"loose\", the DOCTYPE is set to the loose \(transitional\)
+DTD. Alternatively, you can supply a string for the formal public
+identifier \(FPI\). For example:
+
+ doctype: \"-//ACME//DTD HTML 3.14159//EN\"
+
+If you specify the FPI for an XHTML document, Tidy will set
+the system identifier to the empty string. Tidy leaves the DOCTYPE for
+generic XML documents unchanged.")
+
+ ("drop-empty-paras" "Fix Markup" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should discard empty paragraphs. If set to
+no, empty paragraphs are replaced by a pair of <BR> elements as HTML4
+precludes empty paragraphs.")
+
+ ("drop-font-tags" "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 discard <FONT> and <CENTER> tags
+rather than creating the corresponding style rules, but only if the clean
+option is also set to yes.")
+
+ ("drop-proprietary-attributes" "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 strip out proprietary attributes,
+such as MS data binding attributes.")
+
+ ("enclose-block-text" "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 insert a <P> element to enclose any
+text it finds in any element that allows mixed content for HTML
+transitional but not HTML strict.")
+
+ ("enclose-text" "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 enclose any text it finds in the body
+element within a <P> element. This is useful when you want to take
+existing HTML and use it with a style sheet.")
+
+;; ("error-file" "Omit" "String" "-none-"
+;; "
+;; Type: String
+;; Default: -none-
+
+;; This option specifies the error file Tidy uses for errors and
+;; warnings. Normally errors and warnings are output to \"stderr\".
+
+;; This is option is ignored in Emacs.")
+
+ ("escape-cdata" "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 convert <![CDATA[]]> sections to
+normal text.")
+
+ ("fix-backslash" "Fix Markup" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should replace backslash characters \"\\\" in
+URLs by forward slashes \"/\".")
+
+ ("fix-bad-comments" "Fix Markup" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should replace unexpected hyphens with \"=\"
+characters when it comes across adjacent hyphens. The default is yes. This
+option is provided for users of Cold Fusion which uses the comment syntax:
+<!--- --->")
+
+ ("fix-uri" "Fix Markup" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should check attribute values that carry
+URIsfor illegal characters and if such are found, escape them as HTML 4
+recommends.")
+
+ ("force-output" "Input/Output" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should produce output even if errors are
+encountered. Use this option with care - if Tidy reports an error,
+this means Tidy was not able to, or is not sure how to, fix the error,
+so the resulting output may not reflect your intention.")
+
+;; ("gnu-emacs" "Omit" "Boolean" "no"
+;; "
+;; Type: Boolean
+;; Default: no
+;; Example: y/n, yes/no, t/f, true/false, 1/0
+
+;; This option specifies if Tidy should change the format for reporting
+;; errors and warnings to a format that is more easily parsed by GNU
+;; Emacs.
+
+;; This option is automatically set in Emacs." )
+
+ ("hide-comments" "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 print out comments.")
+
+ ("hide-endtags" "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 omit optional end-tags when
+generating the pretty printed markup. This option is ignored if you are
+outputting to XML.")
+
+ ("indent" "Indentation" "AutoBool" "no"
+ "
+Type: AutoBool
+Default: no
+Example: auto, y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should indent block-level tags. If set to
+\"auto\", this option causes Tidy to decide whether or not to indent the
+content of tags such as TITLE, H1-H6, LI, TD, TD, or P depending on whether
+or not the content includes a block-level element. You are advised to avoid
+setting indent to yes as this can expose layout bugs in some browsers.")
+
+ ("indent-attributes" "Indentation" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should begin each attribute on a new line.")
+
+ ("indent-cdata" "Indent" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should indent <![CDATA[]]> sections.")
+
+ ("indent-spaces" "Indentation" "Integer" "2"
+ "
+Type: Integer
+Default: 2
+Example: 0, 1, 2, ...
+
+This option specifies the number of spaces Tidy uses to indent content,
+when indentation is enabled.")
+
+ ("input-encoding" "Encoding" "Encoding" "latin1"
+ "
+Type: Encoding
+Default: ascii
+Example: ascii, latin1, raw, utf8, iso2022, mac, win1252
+
+This option specifies the character encoding Tidy uses for the input. See
+char-encoding for more info.")
+
+ ("input-xml" "Input/Output" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should use the XML parser rather than the
+error correcting HTML parser.")
+
+ ("join-classes" "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 combine class names to generate a
+single new class name, if multiple class assignments are detected on an
+element.")
+
+ ("join-styles" "Fix Markup" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should combine styles to generate a single
+new style, if multiple style values are detected on an element.")
+
+ ("keep-time" "Preference" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should alter the last modified time for
+files it writes back to. The default is no, which allows you to tidy files
+without affecting which ones will be uploaded to a Web server when using a
+tool such as 'SiteCopy'. Note that this feature may not work on some
+platforms.")
+
+ ("literal-attributes" "Preference" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should ensure that whitespace characters
+within attribute values are passed through unchanged.")
+
+ ("logical-emphasis" "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 replace any occurrence of <I> by <EM>
+and any occurrence of <B> by <STRONG>. In both cases, the attributes are
+preserved unchanged. This option can be set independently of the clean and
+drop-font-tags options.")
+
+ ("lower-literals" "Preference" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should convert the value of an attribute
+that takes a list of predefined values to lower case. This is required for
+XHTML documents.")
+
+ ("markup" "Input/Output" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should generate a pretty printed version of
+the markup. Note that Tidy won't generate a pretty printed version if it
+finds significant errors (see force-output).")
+
+ ("ncr" "Preference" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should allow numeric character references.")
+
+ ("newline" "Encoding" "Encoding" "LF"
+ "
+Type: Encoding
+Default: LF
+Example: LF, CRLF, CR
+
+Line ending style. \(Only used in batch operations here.\)")
+
+ ("new-blocklevel-tags" "Tags" "Tag names" ""
+ "
+Type: Tag names
+Default: -none-
+Example: tagX, tagY, ...
+
+This option specifies new block-level tags. This option takes a space or
+comma separated list of tag names. Unless you declare new tags, Tidy will
+refuse to generate a tidied file if the input includes previously unknown
+tags. Note you can't change the content model for elements such as
+<TABLE>, <UL>, <OL> and <DL>.")
+
+ ("new-empty-tags" "Tags" "Tag names" ""
+ "
+Type: Tag names
+Default: -none-
+Example: tagX, tagY, ...
+
+This option specifies new empty inline tags. This option takes a space or
+comma separated list of tag names. Unless you declare new tags, Tidy will
+refuse to generate a tidied file if the input includes previously unknown
+tags. Remember to also declare empty tags as either inline or blocklevel.")
+
+ ("new-inline-tags" "Tags" "Tag names" ""
+ "
+Type: Tag names
+Default: -none-
+Example: tagX, tagY, ...
+
+This option specifies new non-empty inline tags. This option takes a space
+or comma separated list of tag names. Unless you declare new tags, Tidy
+will refuse to generate a tidied file if the input includes previously
+unknown tags.")
+
+ ("new-pre-tags" "Tags" "Tag names" ""
+ "
+Type: Tag names
+Default: -none-
+Example: tagX, tagY, ...
+
+This option specifies new tags that are to be processed in exactly the
+same way as HTML's <PRE> element. This option takes a space or comma
+separated list of tag names. Unless you declare new tags, Tidy will refuse
+to generate a tidied file if the input includes previously unknown
+tags. Note you can not as yet add new CDATA elements (similar to
+<SCRIPT>).")
+
+ ("numeric-entities" "Preference" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should output entities other than the
+built-in HTML entities \(&amp;, &lt;, &gt; and &quot;\) in the numeric
+rather than the named entity form.")
+
+ ("output-bom" "Encoding" "AutoBool" "auto"
+ "
+Type: AutoBool
+Default: auto
+Example: auto, y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should write a Unicode Byte Order Mark
+character (BOM; also known as Zero Width No-Break Space; has value of
+U+FEFF) to the beginning of the output; only for UTF-8 and UTF-16 output
+encodings. If set to \"auto\", this option causes Tidy to write a BOM to the
+output only if a BOM was present at the beginning of the input. A BOM is
+always written for XML/XHTML output using UTF-16 output encodings.")
+
+ ("output-encoding" "Encoding" "Encoding" "ascii"
+ "
+Type: Encoding
+Default: ascii
+Example: ascii, latin1, raw, utf8, iso2022, mac, win1252
+
+This option specifies the character encoding Tidy uses for the output. See
+char-encoding for more info. May only be different from input-encoding for
+Latin encodings (ascii, latin1, mac, win1252).")
+
+ ("output-xhtml" "Input/Output" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should generate pretty printed output,
+writing it as extensible HTML. This option causes Tidy to set the DOCTYPE
+and default namespace as appropriate to XHTML. If a DOCTYPE or namespace
+is given they will checked for consistency with the content of the
+document. In the case of an inconsistency, the corrected values will
+appear in the output. For XHTML, entities can be written as named or
+numeric entities according to the setting of the \"numeric-entities\"
+option. The original case of tags and attributes will be preserved,
+regardless of other options.")
+
+ ("output-xml" "Input/Output" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should pretty print output, writing it as
+well-formed XML. Any entities not defined in XML 1.0 will be written as
+numeric entities to allow them to be parsed by a XML parser. The original
+case of tags and attributes will be preserved, regardless of other
+options.")
+
+ ("quiet" "Input/Output" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should output the summary of the numbers of
+errors and warnings, or the welcome or informational messages.")
+
+ ("quote-ampersand" "Preference" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should output unadorned & characters as
+&amp;.")
+
+ ("quote-marks" "Preference" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should output \" characters as &quot; as is
+preferred by some editing environments. The apostrophe character \' is
+written out as &#39; since many web browsers don't yet support &apos;.")
+
+ ("quote-nbsp" "Preference" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should output non-breaking space characters
+as entities, rather than as the Unicode character value 160 (decimal).")
+
+ ("raw" "Omit" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0 char-encoding
+
+Currently not used, but this option would be the same as the
+char-encoding: raw option.")
+
+ ("repeated-attributes" "Fix Markup" ("keep-first" "keep-last") "keep-last"
+ "
+Type: -
+Default: keep-last
+Example: keep-first, keep-last
+
+This option specifies if Tidy should keep the first or last attribute, if
+an attribute is repeated, e.g. has two align attributes.")
+
+
+ ("replace-color" "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 replace numeric values in color
+attributes by HTML/XHTML color names where defined, e.g. replace
+\"#ffffff\" with \"white\"." )
+
+ ("slide-style" "Omit" "String"
+ "
+Type: Name
+Default: -none-
+split Currently not used.")
+
+;; ("show-body-only" "Omit" "Boolean" "no"
+;; "
+;; Type: Boolean
+;; Default: no
+;; Example: y/n, yes/no, t/f, true/false, 1/0
+
+;; This option specifies if Tidy should print only the contents of the body
+;; tag as an HTML fragment. Useful for incorporating existing whole pages as
+;; a portion of another page.
+
+;; Emacs overrides this option.")
+
+ ("show-errors" "Input/Output" "Integer" "6"
+ "
+Type: Integer
+Default: 6
+Example: 0, 1, 2, ...
+
+This option specifies the number Tidy uses to determine if further errors
+should be shown. If set to 0, then no errors are shown.")
+
+ ("show-warnings" "Input/Output" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should suppress warnings. This can be useful
+when a few errors are hidden in a flurry of warnings.")
+
+ ("slide-style" "Omit" "String" ""
+ "
+Type: Name
+Default: -none-
+
+Currently not used.")
+
+ ("split" "Omit" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should create a sequence of slides from
+the input, splitting the markup prior to each successive <H2>. The
+slides are written to \"slide001.html\", \"slide002.html\" etc.
+
+There is currently no Emacs support for this option.")
+
+ ("tab-size" "Indentation" "Integer" "4"
+ "
+Type: Integer
+Default: 4
+Example: 0, 1, 2, ...
+
+This option specifies the number of columns that Tidy uses between
+successive tab stops. It is used to map tabs to spaces when reading the
+input. Tidy never outputs tabs.")
+
+ ("tidy-mark" "Preference" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should add a meta element to the document
+head to indicate that the document has been tidied. Tidy won't add a meta
+element if one is already present.")
+
+ ("uppercase-attributes" "Preference" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should output attribute names in upper
+case. The default is no, which results in lower case attribute names,
+except for XML input, where the original case is preserved.")
+
+ ("uppercase-tags" "Preference" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should output tag names in upper case. The
+default is no, which results in lower case tag names, except for XML
+input, where the original case is preserved.")
+
+ ("word-2000" "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 go to great pains to strip out all
+the surplus stuff Microsoft Word 2000 inserts when you save Word documents
+as \"Web pages\". Doesn't handle embedded images or VML.")
+
+ ("wrap" "Line Wrapping" "Integer" "68"
+ "
+Type: Integer
+Default: 68
+Example: 0, 1, 2, ...
+
+This option specifies the right margin Tidy uses for line wrapping. Tidy
+tries to wrap lines so that they do not exceed this length. Set wrap to
+zero if you want to disable line wrapping.")
+
+ ("wrap-asp" "Line Wrapping" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should line wrap text contained within ASP
+pseudo elements, which look like: <% ... %>.")
+
+ ("wrap-attributes" "Line Wrapping" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should line wrap attribute values, for
+easier editing. This option can be set independently of
+wrap-script-literals.")
+
+ ("wrap-jste" "Line Wrapping" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should line wrap text contained within JSTE
+pseudo elements, which look like: <# ... #>.")
+
+ ("wrap-php" "Line Wrapping" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should line wrap text contained within PHP
+pseudo elements, which look like: <?php ... ?>.")
+
+ ("wrap-script-literals" "Line Wrapping" "Boolean" "no"
+ "
+Type: Boolean
+Default: no
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should line wrap string literals that appear
+in script attributes. Tidy wraps long script string literals by inserting
+a backslash character before the line break.")
+
+ ("wrap-sections" "Line Wrapping" "Boolean" "yes"
+ "
+Type: Boolean
+Default: yes
+Example: y/n, yes/no, t/f, true/false, 1/0
+
+This option specifies if Tidy should line wrap text contained within
+<![... ]> section tags.")
+
+;; ("write-back" "Omit" "Boolean" "no"
+;; "
+;; Type: Boolean
+;; Default: no
+;; Example: y/n, yes/no, t/f, true/false, 1/0
+
+;; This option specifies if Tidy should write back the tidied markup to
+;; the same file it read from. You are advised to keep copies of
+;; important files before tidying them, as on rare occasions the result
+;; may not be what you expect.
+
+;; This option is ignored by Emacs.")
+ ))
+ )
+
+;;;;; Create a variable for each option in `tidy-options-alist'"
+
+;; these variables are made buffer local so that different buffers can
+;; use a different set of options
+
+(let ((options-alist tidy-options-alist)
+ option name symbol docstring)
+
+ (while (setq option (car options-alist))
+ (setq name (nth 0 option)
+ docstring (nth 4 option)
+ symbol (intern (concat "tidy-" name)))
+ ;; create the variable on the fly
+ (put symbol 'variable-documentation docstring)
+ (make-variable-buffer-local symbol)
+ (set symbol nil) ;;default)
+ (setq options-alist (cdr options-alist))
+ )
+ )
+
+
+;;;;; Quick options setting
+
+(defvar tidy-xhtml-values
+ '(
+ (add-xml-decl "yes")
+ (add-xml-space "no")
+ (doctype "auto")
+ (escape-cdata "no")
+ (fix-backslash "yes")
+ (fix-bad-comments "yes")
+ (fix-uri "yes")
+ (indent "yes")
+ (indent-cdata "yes")
+ (indent-spaces "2")
+ (join-classes "yes")
+ (join-styles "yes")
+ (lower-literals "yes")
+ (newline "LF")
+ (output-xhtml "yes")
+ (output-xml "no")
+ (quote-ampersand "yes")
+ (quote-nbsp "yes")
+ (tidy-mark "no")
+ (uppercase-attributes "no")
+ (uppercase-tags "no")))
+
+(defun tidy-xhtml-options-ok ()
+ (let ((ok t))
+ (dolist (optval tidy-xhtml-values)
+ (let* ((opt (car optval))
+ (val (cadr optval))
+ (nam (symbol-name opt))
+ (ent (assoc nam tidy-options-alist))
+ (def (nth 3 ent))
+ (sym (intern (concat "tidy-" nam))))
+ (when (equal val def)
+ (setq val nil))
+ (unless (equal val (symbol-value sym))
+ (setq ok nil))))
+ ok))
+
+(defun tidy-show-xhtml-options ()
+ "List the settings set by `tidy-set-xhtml-options'."
+ (interactive)
+ (with-output-to-temp-buffer (help-buffer)
+ (with-current-buffer (help-buffer)
+ (help-setup-xref (list #'tidy-show-xhtml-settings) (interactive-p))
+ (let ((inhibit-read-only t)
+ (point (point))
+ s)
+ (insert "Values that will be set by `tidy-set-xhtml-options'. ")
+ (setq s "Green")
+ (put-text-property 0 (length s)
+ 'face '(:foreground "green")
+ s)
+ (insert s " indicates that the local value in the current buffer")
+ (insert " is the value that would be set, ")
+ (setq s "red")
+ (put-text-property 0 (length s)
+ 'face '(:foreground "red")
+ s)
+ (insert s " indicates it is not.\n\n")
+ (fill-region point (point))
+ (dolist (optval tidy-xhtml-values)
+ (let* ((opt (car optval))
+ (val (cadr optval))
+ (nam (symbol-name opt))
+ (ent (assoc nam tidy-options-alist))
+ (def (nth 3 ent))
+ (cur (symbol-value (intern (concat "tidy-" nam))))
+ (show (copy-seq val))
+ )
+ (unless cur (setq cur def))
+ (put-text-property 0 (length show)
+ 'face
+ (if (equal val cur)
+ '(:foreground "green")
+ 'face '(:foreground "red"))
+ show)
+ (insert (format "%25s => %s\n" opt show))))))
+ (with-no-warnings (print-help-return-message))))
+
+(defun tidy-set-xhtml-options (&optional only-current-buffer)
+ "Set option necessary to convert to XHTML.
+To get a list of this settings use `tidy-show-xhtml-options'.
+
+Note that the option variables are buffer local. The default
+variable values are always set. If ONLY-CURRENT-BUFFER is nil set
+the buffer local variables in all buffers."
+ (interactive (list
+ (not (y-or-n-p "Set XHTML options in all buffers? "))))
+ (let ((buffers (if (not only-current-buffer)
+ (buffer-list)
+ (list (current-buffer)))))
+ (dolist (buffer buffers)
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (dolist (optval tidy-xhtml-values)
+ (let* ((opt (car optval))
+ (val (cadr optval))
+ (nam (symbol-name opt))
+ (ent (assoc nam tidy-options-alist))
+ (def (nth 3 ent))
+ (symbol (intern (concat "tidy-" nam))))
+ (when (equal val def)
+ (setq val nil))
+ (set-default symbol val) ;; The least overhead I think
+ (unless (equal val (symbol-value symbol))
+ (set symbol val)))))))))
+
+
+;;;;; Menu Lock (adapted from printing.el)
+
+;; quite compiler
+(eval-when-compile
+ (progn
+ (or (boundp 'current-menubar)
+ (defvar current-menubar nil))
+ (or (fboundp 'tidy-menu-position)
+ (defun tidy-menu-position () ""))
+ (or (fboundp 'tidy-menu-lock)
+ (defun tidy-menu-lock (entry state path) ""))
+ (or (fboundp 'tidy-menu-lookup)
+ (defun tidy-menu-lookup (path) ""))
+ ))
+
+;; always define these
+(defvar tidy-menu nil "Menu used by tidy.")
+(defvar tidy-menu-position nil)
+(defvar tidy-menu-state nil)
+
+(cond
+ ((tidy-xemacs-p)
+ ;; XEmacs
+ (defun tidy-menu-position ()
+ (tidy-x-make-event
+ 'button-release
+ (list 'button 1
+ 'x tidy-menu-x-position
+ 'y -5
+ )))
+
+ ;; XEmacs
+ (defun tidy-menu-lock (entry state path)
+ (when (and (not (interactive-p)) tidy-menu-lock)
+ (or (and tidy-menu-position (eq state tidy-menu-state))
+ (setq tidy-menu-position (tidy-menu-position)
+ tidy-menu-state state))
+ (let* ((menu (tidy-menu-lookup path))
+ (result (tidy-x-get-popup-menu-response menu tidy-menu-position)))
+ (and (tidy-x-misc-user-event-p result)
+ (funcall (tidy-x-event-function result)
+ (tidy-x-event-object result))))
+ (setq tidy-menu-position nil)))
+
+ ;; XEmacs
+ (defun tidy-menu-lookup (path)
+ (car (tidy-x-find-menu-item current-menubar (cons "Tidy" path)))))
+
+ (t
+ ;; GNU Emacs
+ (defun tidy-menu-position ()
+ (let ()
+ (list (list tidy-menu-x-position '-5)
+ (selected-frame)))) ; frame
+
+ ;; GNU Emacs
+;; (defun tidy-menu-lock-old (entry state path)
+;; (when (and (not (interactive-p)) tidy-menu-lock)
+;; (or (and tidy-menu-position (eq state tidy-menu-state))
+;; (setq tidy-menu-position (tidy-menu-position )
+;; tidy-menu-state state))
+;; (let* ((menu (tidy-menu-lookup path))
+;; (result (x-popup-menu tidy-menu-position menu)))
+;; (and result
+;; (let ((command (lookup-key menu (vconcat result))))
+;; (if (fboundp command)
+;; (funcall command)
+;; (eval command)))))
+;; (setq tidy-menu-position nil)))
+ (defun tidy-menu-lock (entry state path)
+ (when (and (not (interactive-p)) tidy-menu-lock)
+ (or (and tidy-menu-position (eq state tidy-menu-state))
+ (setq tidy-menu-position (tidy-menu-position )
+ tidy-menu-state state))
+ ;;(popup-menu tidy-menu tidy-menu-position)))
+ (run-with-idle-timer 1 nil 'popup-menu tidy-menu tidy-menu-position)))
+
+ ;; GNU Emacs
+ (defun tidy-menu-lookup (dummy)
+ (lookup-key (current-local-map) [menu-bar Tidy])))
+ )
+
+;;;;; Define classes of menu items
+
+(defun tidy-set (var-sym value mess entry state &optional path)
+ "Set the value of the symbol VAR-SYM to VALUE giving a message
+derived from VALUE and MESS. Pass on menu data to `tidy-menu-lock'."
+ (set var-sym value)
+ (message "%s is %s" mess value)
+ (tidy-menu-lock entry state path))
+
+(defun tidy-boolean-entry (symbol name type default menu)
+ "Returns a menu entry that allows us to toggle the value of SYMBOL.
+SYMBOL refers to the option called NAME which has default value
+DEFAULT. TYPE should always have the value \"Boolean\". MENU refers
+to the sub-menu that this item belongs to and POSITION its position in
+that list."
+ (cond ((equal default "no")
+ (list (vector name
+ (list 'tidy-set (list 'quote symbol)
+ (list 'if symbol 'nil "yes")
+ name
+ (list 'quote menu)
+ '(quote toggle)
+ )
+ :style 'toggle
+ :selected (list 'if symbol 't 'nil))))
+
+ ((equal default "yes")
+ (list (vector name (list 'tidy-set (list 'quote symbol)
+ (list 'if symbol 'nil "no")
+ name
+ (list 'quote menu)
+ '(quote toggle)
+ )
+ :style 'toggle
+ :selected (list 'if symbol 'nil 't))))))
+
+(defun tidy-list-entry (symbol name type default menu)
+"Returns a menu entry that allows us to set via a radio button the
+value of SYMBOL. SYMBOL refers to the option called NAME which has
+default value DEFAULT. TYPE should be a list of the possible
+values. MENU refers to the sub-menu that this item belongs to and
+POSITION its position in that list."
+ (let (value element)
+ (while (setq value (car type))
+ (if (equal value default)
+ (setq element
+ (append element
+ (list
+ (vector
+ (concat name " is \"" value "\"")
+ (list 'tidy-set (list 'quote symbol)
+ (list 'if symbol 'nil value)
+ name
+ (list 'quote menu)
+ '(quote toggle)
+ )
+ :style 'radio
+ :selected (list 'if symbol 'nil 't)
+ ))))
+ (setq element
+ (append element
+ (list
+ (vector
+ (concat name " is \"" value "\"")
+
+ (list 'tidy-set (list 'quote symbol)
+ (list 'if symbol 'nil value)
+ name
+ (list 'quote menu)
+ '(quote toggle)
+ )
+
+ :style 'radio
+ :selected (list
+ 'if (list 'string-equal symbol value)
+ 't 'nil)
+ )))))
+ (setq type (cdr type)))
+ element))
+
+(defun tidy-set-string (symbol name default)
+ "Set the value of SYMBOL identified by name to VALUE,
+unless VALUE equals DEFAULT, in which case we set it to nil."
+ (interactive)
+ (let* ((last-value (symbol-value symbol))
+ (new-value
+ (if (tidy-xemacs-p)
+ (read-string (format "Set %s to: " name)
+ (or last-value default) nil) ;; no default arg
+ (read-string (format "Set %s to: " name)
+ (or last-value default) nil default))))
+ (set symbol (if (equal new-value default) nil new-value))))
+
+(defun tidy-set-integer (symbol name default)
+ "Set the value of SYMBOL identified by name to VALUE,
+unless VALUE = DEFAULT, in which case we set it to nil."
+ (interactive)
+ (let* ((last-value (symbol-value symbol))
+ ;; careful to interpret the string as a number
+ (new-value
+ (string-to-number
+ (if (tidy-xemacs-p)
+ (read-string (format "Set %s to: " name)
+ (or last-value default) nil)
+ (read-string (format "Set %s to: " name)
+ (or last-value default) nil default)
+ ))))
+ (set symbol (if (= new-value (string-to-number default)) nil
+ (number-to-string new-value)))))
+
+
+(defun tidy-string-entry (symbol name type default menu)
+ "Returns a menu entry that allows us to set the value of SYMBOL.
+SYMBOL refers to the option called NAME which has default value
+DEFAULT. TYPE should always be one of \"String\" \"Tags\", or
+\"DocType\". MENU and POSITION are not used in this case."
+
+ (list (vector (concat "set " name)
+ (list 'tidy-set-string
+ (list 'quote symbol)
+ name default))))
+
+(defun tidy-integer-entry (symbol name type default menu)
+"Returns a menu entry that allows us to set the value of SYMBOL.
+SYMBOL refers to the option called NAME which has default value
+DEFAULT. TYPE should always have the value \"Integer\". MENU and
+POSITION are not used in this case. "
+ (list (vector (concat "set " name)
+ (list 'tidy-set-integer
+ (list 'quote symbol)
+ name default))))
+
+(defun tidy-exe-found ()
+ (when tidy-shell-program
+ ;;(file-executable-p (car (split-string tidy-shell-program)))))
+ (or (file-executable-p tidy-shell-program)
+ (executable-find tidy-shell-program))))
+
+
+(defvar tidy-top-menu nil
+ "The first part of the menu.")
+(when (or (null tidy-top-menu) tidy-debug)
+ (setq tidy-top-menu
+ '("Tidy"
+ ["Tidy Buffer" tidy-buffer
+ :active (tidy-exe-found)]
+
+;; ["Tidy Region" tidy-region
+;; :active (and (mark)
+;; (tidy-exe-found))
+;; :keys "C-u \\[tidy-buffer]"]
+
+ ["Tidy Directory Tree" tidy-tree
+ :active (tidy-exe-found)]
+
+ ["Tidy Site" tidy-tree
+ :active (and (featurep 'html-site)
+ (tidy-exe-found))]
+
+ "----------------------------------------------"
+
+ ["Customize Tidy" (customize-group-other-window 'tidy)]
+
+;; ["Use Ediff" (lambda () (interactive)
+;; (setq tidy-use-ediff (not tidy-use-ediff)))
+;; :style toggle
+;; :selected tidy-use-ediff
+;; ]
+
+;; ["Load Settings" tidy-parse-config-file
+;; :active (and tidy-config-file (file-exists-p tidy-config-file))]
+
+;; ["Load Settings All Buffers" (lambda () (interactive)
+;; (tidy-parse-config-file t))
+;; :active (and tidy-config-file (file-readable-p tidy-config-file))]
+
+ ["Save Settings" tidy-save-settings
+ :active (and tidy-config-file (file-readable-p tidy-config-file))]
+
+ "----------------------------------------------"
+
+ )))
+
+(defvar tidy-newline-menu
+ '("Set newline"
+ ["LF" (tidy-set 'tidy-newline
+ nil
+ "newline"
+ 'newline
+ 'toggle)
+ :style radio
+ :selected (if (null tidy-newline) t nil)]
+
+ ["CRLF" (tidy-set 'tidy-newline
+ "CRLF"
+ "newline"
+ 'newline
+ 'toggle)
+ :style radio
+ :selected (if (equal tidy-newline "CRLF") t nil)]
+
+ ["CR" (tidy-set 'tidy-newline
+ "CR"
+ "newline"
+ 'newline
+ 'toggle)
+ :style radio
+ :selected (if (equal tidy-newline "CRLF") t nil)]
+ ))
+
+(defvar tidy-doctype-menu nil "The second to last sub-menu.")
+(when (or (null tidy-doctype-menu) tidy-debug)
+ (setq tidy-doctype-menu
+ '("Set doctype" ;; ==>
+
+ ["auto" (tidy-set 'tidy-doctype
+ nil
+ "doctype"
+ 'doctype
+ 'toggle)
+ :style radio
+ :selected (if (null tidy-doctype) t nil)]
+
+ ["omit" (tidy-set 'tidy-doctype
+ "omit"
+ "doctype"
+ 'doctype
+ 'toggle)
+ :style radio
+ :selected (if (equal tidy-doctype "omit") t nil)]
+
+ ["strict" (tidy-set 'tidy-doctype
+ "strict"
+ "doctype"
+ 'doctype
+ 'toggle)
+ :style radio
+ :selected (if (equal tidy-doctype "strict") t nil)]
+
+ ["loose" (tidy-set 'tidy-doctype
+ "loose"
+ "doctype"
+ 'doctype
+ 'toggle)
+ :style radio
+ :selected (if (equal tidy-doctype "loose") t nil)]
+
+ ["transitional" (tidy-set 'tidy-doctype
+ "transitional"
+ "doctype"
+ 'doctype
+ 'toggle)
+ :style radio
+ :selected (if (equal tidy-doctype "transitional") t nil)]
+
+ ["fpi" (null nil) ;; stub function
+ :style radio
+ :selected (if (or (null tidy-doctype)
+ (equal tidy-doctype "omit")
+ (equal tidy-doctype "strict")
+ (equal tidy-doctype "loose"))
+ nil t) ]
+
+ ["reset fpi" (tidy-set-string 'tidy-doctype "doctype" "" "")]
+ )))
+
+(defconst tidy-emacs-encoding-lbl "Use Emacs' encoding")
+
+(defun tidy-create-encoding-menu (label encoding-what msg-what)
+ (list label ;; ==>
+ (vector tidy-emacs-encoding-lbl (list 'tidy-set (list 'quote encoding-what)
+ tidy-emacs-encoding-lbl ;(list 'tidy-get-buffer-encoding)
+ msg-what
+ ''encoding
+ ''toggle)
+ :style 'radio
+ :selected (list 'if (list 'equal encoding-what tidy-emacs-encoding-lbl) t nil)
+ )
+
+ "----------------------------------------------"
+
+ (vector "ascii" (list 'tidy-set (list 'quote encoding-what)
+ nil
+ msg-what
+ ''encoding
+ ''toggle)
+ :style 'radio
+ :selected (list 'if (list 'null encoding-what) t nil) ;; default
+ )
+
+ (vector "raw" (list 'tidy-set (list 'quote encoding-what)
+ "raw"
+ msg-what
+ ''encoding
+ ''toggle)
+ :style 'radio
+ :selected (list 'if (list 'equal encoding-what "raw") t nil))
+
+ (vector "latin1" (list 'tidy-set (list 'quote encoding-what)
+ "latin1"
+ msg-what
+ ''encoding
+ ''toggle)
+ :style 'radio
+ :selected (list 'if (list 'equal encoding-what "latin1") t nil))
+
+ (vector "utf8" (list 'tidy-set (list 'quote encoding-what)
+ "utf8"
+ msg-what
+ ''encoding
+ ''toggle)
+ :style 'radio
+ :selected (list 'if (list 'equal encoding-what "utf8") t nil))
+
+ (vector "iso2022" (list 'tidy-set (list 'quote encoding-what)
+ "iso2022"
+ msg-what
+ ''encoding
+ ''toggle)
+ :style 'radio
+ :selected (list 'if (list 'equal encoding-what "iso2022") t nil))
+
+ (vector "mac" (list 'tidy-set (list 'quote encoding-what)
+ "mac"
+ msg-what
+ ''encoding
+ ''toggle)
+ :style 'radio
+ :selected (list 'if (list 'equal encoding-what "mac") t nil))
+
+ (vector "win1252" (list 'tidy-set (list 'quote encoding-what)
+ "win1252"
+ msg-what
+ ''encoding
+ ''toggle)
+ :style 'radio
+ :selected (list 'if (list 'equal encoding-what "win1252") t nil))
+
+ ))
+;; (defvar tidy-char-encoding-menu nil "The last sub-menu.")
+;; (when (or (null tidy-char-encoding-menu) tidy-debug)
+;; (setq tidy-char-encoding-menu
+;; (tidy-create-encoding-menu
+;; "Set char-encoding" 'tidy-char-encoding "char-encoding")))
+;; (defvar tidy-input-encoding-menu nil "The last sub-menu.")
+;; (when (or (null tidy-input-encoding-menu) tidy-debug)
+;; (setq tidy-input-encoding-menu
+;; (tidy-create-encoding-menu
+;; "Set input-encoding" 'tidy-input-encoding "input-encoding")))
+(defvar tidy-output-encoding-menu nil "The last sub-menu.")
+(when (or (null tidy-output-encoding-menu) tidy-debug)
+ (setq tidy-output-encoding-menu
+ (tidy-create-encoding-menu
+ "Set output-encoding" 'tidy-output-encoding "output-encoding")))
+
+;;;;; Create a menu item for each option that has a valid sub-menu
+;; field
+
+(when (or (null tidy-menu) tidy-debug)
+ (let ((options-alist tidy-options-alist)
+
+ ;; sub menus are divided into two parts with list type options
+ ;; coming first, followed by the rest
+
+ markup-menu-bool markup-menu-set
+ line-wrap-menu-bool line-wrap-menu-set
+ preference-menu-bool preference-menu-set
+ indent-menu-bool indent-menu-set
+ io-menu-bool io-menu-set
+ tags-menu-bool tags-menu-set
+
+ name sub-menu type default symbol entry entry-function option)
+
+ (while (setq option (car options-alist))
+ (setq name (nth 0 option)
+ sub-menu (nth 1 option)
+ type (nth 2 option)
+ default (nth 3 option)
+ symbol (intern (concat "tidy-" name))
+ entry nil)
+
+ (cond ((equal type "Boolean")
+ (setq entry-function 'tidy-boolean-entry))
+
+ ((equal type "AutoBool")
+ (setq entry-function 'tidy-list-entry)
+ (setq type '("auto" "yes" "no")))
+
+ ((equal type "DocType")
+ (setq entry '())) ;; handled below
+
+ ((equal type "Tag names")
+ (setq entry-function 'tidy-string-entry))
+
+ ((equal type "String")
+ (setq entry-function 'tidy-string-entry))
+
+ ((equal type "Integer")
+ (setq entry-function 'tidy-integer-entry))
+
+ ((equal type "Encoding")
+ (setq entry '()));; handled below
+
+ ((listp type)
+ (setq entry-function 'tidy-list-entry))
+ (t
+ (error (concat "Tidy: unhandled value type " type " for " name))))
+
+ (cond ((equal sub-menu "Fix Markup")
+ (setq entry (funcall
+ entry-function
+ symbol
+ name
+ type
+ default
+ 'markup))
+
+ (if (or (equal type "Boolean") (equal type "AutoBool") (listp type))
+ (setq markup-menu-bool (append markup-menu-bool entry))
+ (setq markup-menu-set (append markup-menu-set entry))))
+
+ ((equal sub-menu "Indentation")
+ (setq entry (funcall
+ entry-function
+ symbol
+ name
+ type
+ default
+ 'indent))
+
+ (if (or (equal type "Boolean") (equal type "AutoBool") (listp type))
+ (setq indent-menu-bool (append indent-menu-bool entry))
+ (setq indent-menu-set (append indent-menu-set entry))))
+
+ ((equal sub-menu "Line Wrapping")
+ (setq entry (funcall
+ entry-function
+ symbol
+ name
+ type
+ default
+ 'line-wrap))
+
+ (if (or (equal type "Boolean") (equal type "AutoBool") (listp type))
+ (setq line-wrap-menu-bool (append line-wrap-menu-bool entry))
+ (setq line-wrap-menu-set (append line-wrap-menu-set entry))))
+
+ ((equal sub-menu "Input/Output")
+ (setq entry (funcall
+ entry-function
+ symbol
+ name
+ type
+ default
+ 'io))
+
+ (if (or (equal type "Boolean") (equal type "AutoBool") (listp type))
+ (setq io-menu-bool (append io-menu-bool entry))
+ (setq io-menu-set (append io-menu-set entry))))
+
+ ((equal sub-menu "Preference")
+ (setq entry (funcall
+ entry-function
+ symbol
+ name
+ type
+ default
+ 'preference))
+
+ (if (or (equal type "Boolean") (equal type "AutoBool") (listp type))
+ (setq preference-menu-bool (append preference-menu-bool entry))
+ (setq preference-menu-set (append preference-menu-set entry))))
+
+ ((equal sub-menu "Tags")
+ (setq entry (funcall
+ entry-function
+ symbol
+ name
+ type
+ default
+ 'tags))
+
+ (if (or (equal type "Boolean") (equal type "AutoBool"))
+ (setq tags-menu-bool (append tags-menu-bool entry))
+ (setq tags-menu-set (append tags-menu-set entry))))
+ (t)) ;; we simple omit all other menus
+
+ (setq options-alist (cdr options-alist)))
+
+ (setq tidy-menu (append
+ tidy-top-menu
+ (list
+ (list "Quick Options Settings"
+ (vector "Set Options for XHTML"
+ 'tidy-set-xhtml-options
+ :style 'toggle
+ :selected '(tidy-xhtml-options-ok)
+ )
+ (vector "Show Options for XHTML"
+ 'tidy-show-xhtml-options
+ )
+ ))
+ (list (append (list "Advanced")
+
+
+;; "----------------------------------------------"
+
+;; ["Menu Lock" (tidy-set 'tidy-menu-lock
+;; (if tidy-menu-lock nil t)
+;; "Menu Lock"
+;; 'top
+;; 'toggle)
+;; :style toggle
+;; :selected (if tidy-menu-lock t nil)
+;; ]
+;; (vector "Menu Lock"
+;; 'tidy-menu-lock
+;; :style 'toggle
+;; :selected '(if tidy-menu-lock t nil)
+;; )
+ (list (vector "Menu Lock"
+ '(tidy-set 'tidy-menu-lock
+ (if tidy-menu-lock nil t)
+ "Menu Lock"
+ 'top
+ 'toggle
+ )
+ :style 'toggle
+ :selected '(if tidy-menu-lock t nil)
+ ))
+ (list (list "-------"))
+
+ (list (append (list "Fix Markup")
+ markup-menu-bool
+ markup-menu-set))
+ (list (append (list "Line Wrapping")
+ line-wrap-menu-bool
+ line-wrap-menu-set))
+ (list (append (list "Preference")
+ preference-menu-bool
+ preference-menu-set))
+ (list (append (list "Indentation")
+ indent-menu-bool
+ indent-menu-set))
+ (list (append (list "Input/Output")
+ io-menu-bool
+ io-menu-set))
+ (list (append (list "Tags")
+ tags-menu-bool
+ tags-menu-set))
+ (list tidy-doctype-menu)
+ (list tidy-output-encoding-menu)
+ (list tidy-newline-menu)
+ ))
+ '(["Describe Options" tidy-describe-options t])
+ (list (list "-------"))
+ '(["Tidy Home Page"
+ (lambda ()
+ "Open Tidy home page in your web browser."
+ (interactive)
+ (browse-url "http://tidy.sourceforge.net/"))
+ t])
+ ))
+ )
+)
+
+(defvar tidy-menu-symbol nil)
+;;(tidy-build-menu (&optional map)
+;;;###autoload
+(defun tidy-build-menu (&optional map)
+ "Set up the tidy menu in MAP.
+Used to set up a Tidy menu in your favourite mode."
+ (interactive) ;; for debugging
+ (unless tidy-menu-symbol
+ (unless tidy-config-file-parsed
+ (tidy-parse-config-file)
+ (setq tidy-config-file-parsed t))
+ ;;(or map (setq map (current-local-map)))
+ (easy-menu-remove tidy-menu)
+ (easy-menu-define tidy-menu-symbol map "Menu for Tidy" tidy-menu)
+ (setq tidy-menu-symbol (delete "Tidy" tidy-menu-symbol))
+ (easy-menu-add tidy-menu map))
+ t)
+
+;;;;; Option description support
+
+;; quiet FSF Emacs and XEmacs compilers
+(eval-when-compile
+ (progn (or (fboundp 'event-point) (defun event-point (dummy) ""))
+ (or (fboundp 'posn-point) (defun posn-point (dummy) ""))
+ (or (fboundp 'event-start) (defun event-start (dummy) ""))))
+
+(defun tidy-describe-this-option-mouse (click)
+ (interactive "e")
+ (let ((p (if (tidy-xemacs-p)
+ (event-point click)
+ (posn-point (event-start click)))))
+ (tidy-describe-this-option p)))
+
+(defun tidy-describe-this-option (&optional point)
+ "Describe variable associated with the text at point."
+ (interactive (list (point)))
+
+ (let* ((variable (get-text-property
+ point
+ 'tidy-variable))
+ value
+ buffer) ;; reuse the help buffer
+ (when variable
+ (with-output-to-temp-buffer (help-buffer)
+ (help-setup-xref (list #'tidy-describe-this-option point) (interactive-p))
+ (with-current-buffer (help-buffer)
+ (setq value (symbol-value variable))
+ (insert (substring (symbol-name variable) 5) ;; clip the `tidy-' prefix
+ " is set to ")
+ (if value (insert value) (insert "set to the default value"))
+ (insert "\n\n" (documentation-property variable 'variable-documentation))
+ (local-set-key [(q)] 'tidy-quit-describe-options)
+ (with-no-warnings (print-help-return-message)))))))
+
+(defun tidy-quit-describe-options ()
+ "Rid thyself of any display associated with Tidy's options."
+ (interactive)
+ (bury-buffer (get-buffer "*tidy-options*"))
+ (delete-windows-on (get-buffer "*tidy-options*"))
+ (bury-buffer (get-buffer "*Help*"))
+ (delete-windows-on (get-buffer "*Help*")))
+
+;; nicked this from cal-desk-calendar.el:-)
+(defun tidy-current-line ()
+ "Get the current line number (in the buffer) of point."
+ ;;(interactive)
+ (save-restriction
+ (widen)
+ (save-excursion
+ (beginning-of-line)
+ (1+ (count-lines 1 (point))))))
+
+(defun tidy-goto-line (line)
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (forward-line (1- line))))
+
+(defun tidy-describe-options ()
+ "Interactively access documentation strings for `tidy-' variables."
+ (interactive)
+ (let ((buffer (get-buffer "*tidy-options*")))
+ (if buffer (pop-to-buffer buffer)
+ ;; else build it from scratch
+ (setq buffer (get-buffer-create "*tidy-options*"))
+ (let* ((start 0)
+ (end 0)
+ name
+ (count 0)
+ (option-alist tidy-options-alist)
+ (column2a (+ (length "drop-proprietary-attributes") 3))
+ (column2b (/ (window-width) 3))
+ (column2 (if (> column2a column2b) column2a column2b))
+ (column3 (* 2 column2))
+ (start-line 0)
+ (third-length 0)
+ (two-third-length 0))
+
+ (set-buffer buffer)
+
+ (setq buffer-read-only nil)
+ (delete-region (point-min) (point-max)) ;; empty the buffer
+
+ ;; set up local bindings
+ (if (tidy-xemacs-p)
+ (local-set-key [(button2)] 'tidy-describe-this-option-mouse)
+ (local-set-key [(mouse-2)] 'tidy-describe-this-option-mouse))
+
+ (local-set-key "\r" 'tidy-describe-this-option)
+ (local-set-key [(q)] 'tidy-quit-describe-options)
+
+ (insert "Press RET over option to see its description. "
+ "Type \"q\" to quit." "\n\n")
+
+ (setq start-line (tidy-current-line))
+ (setq third-length (1+ (/ (length option-alist) 3) ))
+ (setq two-third-length (1- (* 2 third-length)))
+
+ (while (setq name (car (car-safe option-alist)))
+ (setq option-alist (cdr option-alist))
+ (setq count (+ count 1))
+
+ (cond
+ ((< count third-length) ;; 0 <= count < third-length
+ (setq start (point))
+ (insert name)
+ (setq end (point))
+ (insert "\n"))
+ ((< count two-third-length) ;; third-length <= count < two-third-length
+ (if (= count third-length)
+ (tidy-goto-line start-line)
+ (forward-line 1))
+ (end-of-line)
+ (setq start (point))
+ (indent-to-column column2)
+ (setq end (point))
+ (put-text-property start end 'mouse-face 'default)
+ (setq start (point))
+ (insert name)
+ (setq end (point)))
+ (t ;; two-third-length <= count < length
+ (if (= count two-third-length)
+ (tidy-goto-line start-line)
+ (forward-line 1))
+ (end-of-line)
+ (setq start (point))
+ (indent-to-column column3)
+ (setq end (point))
+ (put-text-property start end 'mouse-face 'default)
+ (setq start (point))
+ (insert name)
+ (setq end (point))))
+
+ ;; make the strings funky
+ (put-text-property start end 'mouse-face 'highlight)
+ (put-text-property start end 'tidy-variable (intern (concat "tidy-" name)))
+ )
+ (setq buffer-read-only t)
+ ;;(beginning-of-buffer)
+ (goto-char (point-min))
+ (pop-to-buffer buffer)
+ ))))
+
+;;;;; Configuration file support
+
+(defun tidy-parse-config-file (&optional all-buffers)
+ "Parse `tidy-config-file' and set variables accordingly.
+If `tidy-config-file' is nil or \"\" do nothing. If the file does
+not exist just give a message.
+
+Note that the option variables are buffer local. The default
+variable values are always set. If ALL-BUFFERS is non-nil set the
+buffer local variables in all buffers."
+ (interactive (list
+ (y-or-n-p "Set Tidy config file values in all buffers? ")))
+ (tidy-set-xhtml-options all-buffers)
+ (when (and tidy-config-file
+ (not (string= "" tidy-config-file)))
+ (if (not (file-exists-p tidy-config-file))
+ (unless (string= tidy-config-file tidy-default-config-file)
+ (message "Could not find Tidy config file \"%s\"." tidy-config-file))
+ (message "Parsing config file...")
+ (let ((html-buffer (current-buffer))
+ (config-buffer (find-file-noselect tidy-config-file t))
+ config-variables)
+ (with-current-buffer config-buffer
+ (goto-char (point-min)) ;; unnecessary but pedantic
+
+ ;; delete all comments
+ (while (re-search-forward "//.*\n" nil t)
+ (replace-match "" nil nil))
+
+ (goto-char (point-min))
+ (while (re-search-forward "\\([a-z,-]+\\):\\s-*\\(.*\\)\\s-*" nil t)
+ ;; set the variable
+ ;; Thanks to Thomas Baumann for this bugfix
+ (let ((variable (concat "tidy-" (match-string 1)))
+ (value (match-string 2)))
+ ;;(set-default (intern variable value))
+ (set-default (intern variable) value)
+ (setq config-variables
+ (cons (cons variable value) config-variables))
+ (with-current-buffer html-buffer
+ (set (intern variable) value))
+ ))
+
+ (set-buffer-modified-p nil) ;; don't save changes
+ (kill-buffer config-buffer))
+ (when all-buffers
+ (dolist (buffer (buffer-list))
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (dolist (optval config-variables)
+ (let* ((opt (car optval))
+ (val (cdr optval))
+ (sym (intern opt)))
+ (set sym val))))))))
+ (message "Parsing config file...done")
+ )))
+
+(defun tidy-save-settings (&optional config-file)
+ "Query saving the current settings to your `tidy-config-file'.
+The local values in the current buffer will be saved."
+ (interactive)
+ (or config-file (setq config-file tidy-config-file))
+ (when config-file
+
+ ;; should check for locks!
+ (if (or (not (interactive-p))
+ (y-or-n-p "Save settings to your tidy configuration file? "))
+
+ (let ((buffer (find-file-noselect config-file t))
+ (option-alist tidy-options-alist)
+ (outer-buffer (current-buffer))
+ option name symbol value)
+ (with-current-buffer buffer
+ (delete-region (point-min) (point-max)) ;; clear the buffer
+
+ ;; need this line so that config file is always non empty
+ (insert "// HTML Tidy configuration file \n")
+ (while (setq option (car option-alist))
+ (setq option-alist (cdr option-alist))
+ (setq name (nth 0 option)
+ symbol (intern (concat "tidy-" name)))
+ (with-current-buffer outer-buffer
+ (setq value (symbol-value symbol)))
+ (when (string= value tidy-emacs-encoding-lbl)
+ (setq value (tidy-get-buffer-encoding)))
+ (when value ;; nil iff default
+ (insert (car option) ": " value "\n")))
+
+ (save-buffer)
+ ;;(basic-save-buffer)
+ (kill-buffer buffer)
+ )))))
+
+
+;;;;; Main user function
+
+(eval-when-compile (defvar tidy-markup nil ""))
+
+(defun tidy-set-buffer-unmodified (dummy1 dummy2 dumm3)
+ "Used to prevent error buffer form being marked as modified."
+ (set-buffer-modified-p nil))
+
+;; See http://www.mhonarc.org/MHonArc/doc/resources/charsetaliases.html
+(defconst tidy-encodings-mime-charset-list
+ '(
+ ;; ("raw") ;; Same as ascii??
+ ("ascii" . "us-ascii")
+ ("latin0" . "iso-8859-15")
+ ("latin1" . "iso-8859-1")
+ ("iso2022" . "iso-2022-jp") ;; Correct? There are several iso-2022-..
+ ("utf8" . "utf-8")
+ ("mac" . "macintosh")
+ ("win1252" . "windows-1252")
+ ("ibm858" . "cp850")
+ ("utf16le" . "utf-16-le")
+ ("utf16be" . "utf-16-be")
+ ("utf16" . "utf-16")
+ ("big5" . "big5")
+ ("shiftjis" . "shift_jis")
+ )
+ "Encoding names used by Tidy and Emacs.
+First column is Tidy's name, second Emacs' name."
+ )
+
+(defun tidy-get-buffer-encoding ()
+ "Get Tidy's name for value of `buffer-file-coding-system'."
+ (tidy-get-tidy-encoding buffer-file-coding-system))
+
+(defun tidy-get-tidy-encoding (emacs-coding-system)
+ (let ((encoding (rassoc
+ (symbol-name
+ (coding-system-get emacs-coding-system 'mime-charset))
+ tidy-encodings-mime-charset-list)))
+ (if encoding
+ (setq encoding (car encoding))
+ (setq encoding "raw"))
+ encoding))
+
+(defun tidy-temp-config-file ()
+ (expand-file-name "temp-tidy-config"
+ tidy-temp-directory))
+
+(defconst tidy-output-buf-name "Tidy (X)HTML Output")
+
+(defvar tidy-tidied-buffer nil)
+(make-variable-buffer-local 'tidy-tidied-buffer)
+(put 'tidy-tidied-buffer 'permanent-local t)
+
+(defun tidy-check-is-tidied (orig-buf tidy-buf)
+ (with-current-buffer tidy-buf
+ (unless tidy-tidied-buffer
+ (error "%s is not a tidy output buffer" tidy-buf))
+ (unless (eq orig-buf tidy-tidied-buffer)
+ (error "Buffer does not contain tidied %s" orig-buf))))
+
+(defconst tidy-control-buffer-name "Tidy Control Buffer")
+
+(defvar tidy-output-encoding) ;; dyn var
+
+(defun tidy-buffer ()
+ "Run the HTML Tidy program on the current buffer.
+Show the errors in a buffer with buttons to:
+
+- show the original buffer
+- show the tidied output
+- copy tidied to original
+- run ediff
+
+This buffer also contains any error and warning messages and they
+link to the original source code.
+
+If the buffer to tidy contains a fictive XHTML validation header
+\(see `nxhtml-validation-header-mode') then the corresponding
+header is added before running tidy. This header is removed again
+after tidying, together with additions tidy might have done at
+the end of the buffer.
+
+You may tidy part of the buffer, either by narrowing the buffer
+or by selecting a region and having it visibly marked (`cua-mode'
+etc). A fictive XHTML validation header will apply as
+above. However if there is no such header then when you tidy part
+of the buffer still a hopefully suitable header is added before
+calling tidy."
+;; Fix-me: copy back parts outside visible region
+ (interactive)
+ (message "starting tidy-buffer")
+ (let* ((is-narrowed (buffer-narrowed-p))
+ (validation-header (when (boundp 'rngalt-validation-header)
+ (let ((header (nth 2 rngalt-validation-header)))
+ (when header (concat header "\n")))))
+ (region-restricted (and mark-active
+ transient-mark-mode
+ (or (< (point-min) (region-beginning))
+ (< (region-end) (point-max)))))
+ (partial (or validation-header
+ is-narrowed
+ region-restricted))
+ (start (if region-restricted (region-beginning) (point-min)))
+ (end (if region-restricted (region-end) (point-max)))
+ (region-header (when region-restricted
+ (when (< (point-min) (region-beginning))
+ (buffer-substring-no-properties
+ (point-min) (region-beginning)))))
+ (region-footer (when region-restricted
+ (when (< (region-end) (point-max))
+ (buffer-substring-no-properties
+ (region-end) (point-max)))))
+ (tidy-beg-mark "<!-- TIDY BEGIN MARK 142505535 -->\n")
+ (tidy-end-mark "<!-- TIDY END MARK 143345187 -->")
+ ;;(whole-file t) ;(and (= start 1) (= end (1+ (buffer-size)))))
+ (filename buffer-file-name)
+ ;;(orig-dir (file-name-directory filename))
+ (orig-buffer (current-buffer))
+ (work-buffer (get-buffer-create "* Tidy Temporary Work Buffer *"))
+ (line-header-offset nil)
+
+ ;; Gasp! We have to use temp files here because the command
+ ;; line would likely get too long!
+
+ (error-buf-name tidy-control-buffer-name)
+
+ (error-file (expand-file-name error-buf-name
+ tidy-temp-directory))
+
+ (error-buffer (get-buffer-create error-buf-name))
+
+ (output-buffer (get-buffer-create tidy-output-buf-name))
+
+ (config-file (tidy-temp-config-file))
+
+ ;;(eol (coding-system-eol-type buffer-file-coding-system))
+ ;;(encoding (coding-system-get buffer-file-coding-system 'mime-charset))
+ ;;(errors 0)
+ ;;(warnings 0)
+ (tidy-message "")
+ (seg-error nil)
+ ;;(use-ediff tidy-use-ediff)
+
+ (want-mumamo nil)
+ )
+
+;; (when (and use-ediff
+;; (not tidy-show-warnings)) ;; default "yes" hence inverted logic
+;; (setq use-ediff (y-or-n-p "Warning can not be shown when using ediff. Still use ediff? ")))
+ (unless buffer-file-name
+ (error "Can't tidy buffer with no file name"))
+
+ (when (buffer-modified-p orig-buffer)
+ (error "Can't tidy buffer because it is modified"))
+
+ (with-current-buffer error-buffer
+ (setq buffer-read-only nil)
+ (erase-buffer)
+ (setq tidy-tidied-buffer orig-buffer))
+
+ ;; OK do the tidy
+;; (message "coding-system: %s, %s, %s"
+;; (find-operation-coding-system
+;; 'call-process-region start end command)
+;; coding-system-for-write
+;; buffer-file-coding-system)
+ (let* ((coding-system-for-write buffer-file-coding-system)
+ (tidy-input-encoding (tidy-get-tidy-encoding coding-system-for-write)))
+
+ (let ((output-mode (if (not (featurep 'mumamo))
+ major-mode
+ (if (and (boundp 'mumamo-multi-major-mode)
+ mumamo-multi-major-mode)
+ mumamo-multi-major-mode
+ major-mode))))
+ (with-current-buffer output-buffer
+ (erase-buffer)
+ ;;(when (and (fboundp 'mumamo-mode) mumamo-mode) (setq want-mumamo t) (mumamo-mode 0))
+ (funcall output-mode)
+ (set (make-local-variable 'coding-system-for-read) coding-system-for-write)))
+
+ (let ((tidy-output-encoding tidy-output-encoding))
+ (unless tidy-output-encoding
+ (setq tidy-output-encoding tidy-input-encoding))
+ ;;(message "tidy-input-enc=%s, tidy-output-enc=%s" tidy-input-encoding tidy-output-encoding)
+ (tidy-save-settings config-file)
+ )
+
+ ;; Tidy does not replace the xml declaration so it must be removed:
+ ;(setq tidy-add-xml-decl "no")
+ (let (;(orig-min (point-min)) (orig-max (point-max))
+ )
+;; (when region-restricted
+;; ;; We have a visible region
+;; (setq orig-min (region-beginning))
+;; (setq orig-max (region-end)))
+ (with-current-buffer work-buffer
+ (erase-buffer)
+ (when validation-header
+ (insert validation-header))
+ (when partial
+ ;; Have to insert things to make tidy insert at correctt
+ ;; position. A bit of guessing here to keep it simple.
+ (let ((p "\n<p>TIDY</p>\n")
+ (b "\n<body>\n")
+ (he "\n<head><title></title></head>\n")
+ (ht (concat
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"\n"
+ "\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n")))
+ (goto-char (point-min))
+ (if (re-search-forward "<body[^>]*>" nil t)
+ (insert p)
+ (if (search-forward "</head>" nil t)
+ (insert b p)
+ (if (re-search-forward "<html[^>]*>" nil t)
+ (insert he b p)
+ (insert ht he b p))))
+ (goto-char (point-max))
+ (insert "\n" tidy-beg-mark)))
+ (setq line-header-offset (line-number-at-pos))
+ (insert-buffer-substring orig-buffer start end) ;orig-min orig-max)
+ (when partial (insert "\n" tidy-end-mark "\n"))
+ (let ((args
+ (list
+ ;;start end
+ (point-min) (point-max)
+ tidy-shell-program
+ nil
+ output-buffer
+ t
+ "-config" config-file
+ "--error-file" error-file
+ "--write-back" "no"
+ ;;(if (not whole-file) "--show-body-only" "--show-body-only")
+ ;;(if (not whole-file) "yes" "no")
+ "--show-body-only" "no"
+ "--gnu-emacs" "yes"
+ "--gnu-emacs-file" (file-name-nondirectory filename)
+ ))
+ (default-directory (file-name-directory filename))
+ )
+ (apply 'call-process-region args)))
+ ))
+
+
+ ;; Since XEmacs can't grab the std error stream we use an error file
+ ;;(setq error-buffer (find-file-noselect error-file t))
+ (with-current-buffer error-buffer
+ (setq tidy-tidied-buffer orig-buffer)
+ (insert-file-contents error-file)
+ ;; Change the line numbers if a header was inserted
+ (when line-header-offset
+ (goto-char (point-min))
+ (while (re-search-forward ":\\([0-9]+\\):[0-9]+" nil t)
+ (let ((line (1+ (- (string-to-number (match-string-no-properties 1))
+ line-header-offset))))
+ (replace-match (number-to-string line) nil nil nil 1))))
+ )
+
+ ;; avoid leaving these guys lying around
+ (if (file-exists-p error-file) (delete-file error-file))
+ ;;(if (file-exists-p config-file) (delete-file config-file))
+
+ ;; scan the buffer for error strings
+ (with-current-buffer error-buffer
+ ;;(local-set-key [tab] 'tidy-errbuf-forward)
+ (goto-char (point-min))
+ (insert "\n")
+ (make-local-variable 'widget-button-face)
+ (setq widget-button-face custom-button)
+ (set (make-local-variable 'widget-push-button-prefix) "")
+ (set (make-local-variable 'widget-push-button-suffix) "")
+ (set (make-local-variable 'widget-link-prefix) "")
+ (set (make-local-variable 'widget-link-suffix) "")
+ (widget-create 'push-button
+ :tag " Show Source "
+ :keymap (make-sparse-keymap)
+ :arg-orig orig-buffer
+ :action (lambda (widget &optional event)
+ (let ((orig-buf (widget-get widget :arg-orig))
+ (curr-win (selected-window)))
+ (switch-to-buffer-other-window orig-buf)
+ (select-window curr-win))))
+ (insert " ")
+ (widget-create 'push-button
+ :tag " Show Tidied "
+ :keymap (make-sparse-keymap)
+ :arg-tidy output-buffer
+ :arg-orig orig-buffer
+ :action (lambda (widget &optional event)
+ (let ((tidy-buf (widget-get widget :arg-tidy))
+ (orig-buf (widget-get widget :arg-orig))
+ (curr-win (selected-window)))
+ (tidy-check-is-tidied orig-buf tidy-buf)
+ (switch-to-buffer-other-window tidy-buf)
+ (select-window curr-win))))
+
+
+ (insert " ")
+ (widget-create 'push-button
+ :tag " Use Tidied "
+ :keymap (make-sparse-keymap)
+ :arg-tidy output-buffer
+ :arg-orig orig-buffer
+ :action (lambda (widget &optional event)
+ (message "Copying ...")
+ (let* ((orig-buf (widget-get widget :arg-orig))
+ (tidy-buf (widget-get widget :arg-tidy))
+ (orig-buf-str
+ (save-restriction
+ (with-current-buffer orig-buf
+ (widen)
+ (buffer-substring-no-properties (point-min) (point-max)))))
+ (tidy-buf-str
+ (save-restriction
+ (with-current-buffer tidy-buf
+ (widen)
+ (buffer-substring-no-properties (point-min) (point-max)))))
+ )
+ (tidy-check-is-tidied orig-buf tidy-buf)
+ (kill-buffer (current-buffer))
+ (kill-buffer tidy-buf)
+ (if (string= orig-buf-str tidy-buf-str)
+ (message "Original buffer's and tidied buffer's contents are equal")
+ (with-current-buffer orig-buf
+ (erase-buffer)
+ (insert tidy-buf-str)
+ (goto-char (point-min))
+ (delete-window (selected-window))
+ (switch-to-buffer orig-buf)
+ (message "Copied to %s" orig-buf))))))
+ (insert " ")
+ (widget-create 'push-button
+ :tag " Ediff "
+ :keymap (make-sparse-keymap)
+ :arg-tidy output-buffer
+ :arg-orig orig-buffer
+ :action (lambda (widget &optional event)
+ (require 'ediff)
+ (let ((orig-buf (widget-get widget :arg-orig))
+ (tidy-buf (widget-get widget :arg-tidy))
+ ;; Fix-me: How should ediff-actual-options be set?
+ (old-ediff-actual-diff-options (default-value 'ediff-actual-diff-options))
+ (new-ediff-actual-diff-options " -a -b -w "))
+ (with-current-buffer orig-buf (setq ediff-actual-diff-options " -a -b -w "))
+ (with-current-buffer tidy-buf (setq ediff-actual-diff-options " -a -b -w "))
+ (tidy-check-is-tidied orig-buf tidy-buf)
+ (set-default 'ediff-actual-diff-options new-ediff-actual-diff-options)
+ (tidy-ediff-buffers orig-buf tidy-buf)
+ (set-default 'ediff-actual-diff-options old-ediff-actual-diff-options)
+ )))
+ ;;(widget-setup)
+
+ (insert "\n\n")
+ (when (re-search-forward (concat
+ "\\([0-9]+\\) warnings?, "
+ "\\([0-9]+\\) errors? were found!")
+ nil t)
+ (setq tidy-warnings (string-to-number (match-string 1)))
+ (setq tidy-errors (string-to-number (match-string 2)))
+ (setq tidy-message (match-string 0)))
+
+ (goto-char (point-min))
+ ;;(while (re-search-forward "stdin:" nil t) (replace-match (concat filename ":")))
+ (wab-compilation-mode)
+ (set-buffer-modified-p nil)
+ (goto-char (point-min))
+ ;; Fix-me: How should this be run? Some hook for compilation I
+ ;; guess, but what is the name of it?
+ ;; (wab-forward)
+ )
+
+
+ (when (buffer-live-p output-buffer)
+ ;; Catch segmentation violations
+ ;; Sometimes get this when editing files from Macs
+ ;; See the function at the bottom of the file
+ (with-current-buffer output-buffer
+ (goto-char (point-min))
+ (let ((case-fold-search t))
+ (if (looking-at "Segmentation") ;; might work with XEmacs
+ (setq seg-error t))))
+ ;; Fix-me: add parts outside region
+ (when partial
+ (with-current-buffer output-buffer
+ (goto-char (point-min))
+ (when (search-forward tidy-beg-mark nil t)
+ (delete-region (point-min) (point)))
+ (when region-header (insert region-header))
+ (when (search-forward tidy-end-mark nil t)
+ (backward-char (length tidy-end-mark))
+ (delete-region (point) (point-max)))
+ (when region-footer (insert region-footer))))
+ )
+
+ (unless (or (> tidy-errors 0) seg-error)
+ ;; Do not know if the window stuff is needed?
+ (let* ((window (get-buffer-window (current-buffer)))
+ (top (window-start window)))
+
+ (unless tidy-markup ;; default is "yes" hence inverted logic
+ (when (eq system-type 'windows-nt)
+ (tidy-remove-ctrl-m output-buffer))
+ (with-current-buffer output-buffer
+ (setq tidy-tidied-buffer orig-buffer)
+ (delete-trailing-whitespace)
+ (indent-region (point-min) (point-max))
+ (goto-char (point-min))))
+
+ ;; Try not to move the window too much when we tidy the whole buffer
+ (set-window-start window top)))
+
+ (switch-to-buffer-other-window error-buffer)
+
+ (if seg-error
+ (message (concat "Tidy: Segmentation violation!!!"
+ " Check your character encoding."))
+ (message "%s" tidy-message))))
+
+(defun tidy-after-ediff ()
+ (run-with-idle-timer 0 nil 'remove-hook 'ediff-quit-hook 'tidy-after-ediff)
+ ;;(lwarn 't :warning "cb=%s, %s, %s" (current-buffer) ediff-buffer-A ediff-buffer-B)
+ (let ((sw (selected-window))
+ nw)
+ (select-window ediff-window-B)
+ (setq nw (split-window))
+ (set-window-buffer nw (get-buffer-create tidy-control-buffer-name))
+ (select-window sw))
+ nil)
+
+(defun tidy-ediff-buffers (buffer-a buffer-b &optional startup-hooks job-name)
+ (add-hook 'ediff-quit-hook 'tidy-after-ediff)
+ (ediff-buffers buffer-a buffer-b startup-hooks job-name))
+
+;; http://sf.net/tracker/index.php?func=detail&aid=1425219&group_id=27659&atid=390963
+(defun tidy-remove-ctrl-m (buffer)
+ (with-current-buffer buffer
+ (goto-char (point-min))
+ (let ((control-m (char-to-string ?\r)))
+ (while (search-forward control-m nil t)
+ (replace-match "" nil t)))))
+
+(defvar tidy-html-files-re "\.x?html?$")
+(defun tidy-is-html-file (filename)
+ (string-match tidy-html-files-re filename))
+
+(defun tidy-contains (dir file)
+ (let ((d (file-name-as-directory dir)))
+ (when (< (length d) (length file))
+ (string= d (substring file 0 (length d))))))
+
+
+
+(defvar tidy-tree-files nil)
+(defun tidy-tree-next ()
+ (let ((next-file (car tidy-tree-files))
+ file-buffer
+ ;;(tidy-use-ediff nil)
+ )
+ (if (not next-file)
+ ;;(setq tidy-batch-buffer nil)
+ nil
+ (setq tidy-tree-files (cdr tidy-tree-files))
+ (if (file-directory-p next-file)
+ (error "Uh?")
+ (tidy-batch next-file)))))
+
+(defun tidy-tree (root)
+ "Run Tidy on all files in the directory ROOT.
+The files are first opened in Emacs and then `tidy-buffer' is
+called."
+ (interactive "DDirectory tree: ")
+ (unless (file-directory-p root)
+ (error "tidy-tree called with non-directory arg: %s" root))
+ (setq tidy-tree-files (html-site-get-sub-files root html-site-files-re))
+ (dolist (f tidy-tree-files)
+ (let ((b (get-file-buffer f)))
+ (when (and b
+ (buffer-modified-p b))
+ (unless
+ (y-or-n-p (format "Modified buffer %s must be saved. Save it and continue? "
+ (buffer-name b)))
+ (error "Modified buffers prevent run with Tidy"))
+ (with-current-buffer b
+ (basic-save-buffer)))))
+ (setq tidy-batch-last-file nil)
+ (tidy-tree-next))
+
+(defun tidy-html-site ()
+ "Tidy the whole tree in the current site."
+ ;; Fix-me: document html-site better.
+ (interactive)
+ (unless (featurep 'html-site)
+ (error "html-site is not loaded"))
+ (html-site-current-ensure-site-defined)
+ (tidy-tree (html-site-current-site-dir)))
+
+(defun tidy-batch-sentinel (process event)
+ (with-current-buffer (process-buffer process)
+ (let ((inhibit-read-only t))
+ (insert "PROCESS-EVENT: " event "\n")))
+ (when (eq (process-status process) 'exit)
+ (when tidy-batch-last-file
+ (let ((b (get-file-buffer tidy-batch-last-file)))
+ (when b
+ (with-current-buffer b
+ (save-excursion
+ (widen)
+ (let ((old (buffer-substring-no-properties (point-min) (point-max)))
+ (new (with-temp-buffer
+ ;;(insert-file tidy-batch-last-file)
+ (insert-file-contents tidy-batch-last-file)
+ (buffer-substring-no-properties (point-min) (point-max))))
+ )
+ (unless (string= old new)
+ (erase-buffer)
+ (insert new))))))))
+ (tidy-tree-next)))
+
+(defun tidy-batch-output-filter (proc string)
+ (display-buffer (process-buffer proc))
+ (with-current-buffer (process-buffer proc)
+ (let ((moving (= (point) (process-mark proc))))
+ (save-excursion
+ ;; Insert the text, advancing the process marker.
+ (goto-char (process-mark proc))
+ (let ((inhibit-read-only t))
+ ;; http://sf.net/tracker/index.php?func=detail&aid=1425219&group_id=27659&atid=390963
+ (setq string (replace-regexp-in-string "\r$" "" string))
+ (insert string))
+ (set-marker (process-mark proc) (point)))
+ (if moving (goto-char (process-mark proc))))))
+
+(defun tidy-batch (filename)
+ (interactive (list buffer-file-name)) ;; For testing
+ (setq tidy-batch-last-file filename)
+ (let* (;;(filename buffer-file-name)
+ (config-file (tidy-temp-config-file))
+ (command (list tidy-shell-program
+ ;; load configuration file first so that
+ ;; options are overridden by command line
+
+ "-config" config-file
+ ;;"--error-file" error-file
+ "--write-back" "yes"
+ ;;"--show-body-only" "no"
+ "--gnu-emacs" "yes"
+ "--gnu-emacs-file" filename
+ filename
+ ))
+ (procbuf (noshell-procbuf-setup "subprocess for Tidy"))
+ (start (with-current-buffer procbuf (point)))
+ proc
+ ;; This does not work at the moment (2006-05-16):
+ (coding-system-for-read 'undecided-dos)
+ (coding-system-for-write 'undecided-dos)
+ )
+ ;;(setq tidy-batch-buffer procbuf)
+ (tidy-save-settings config-file)
+ (unwind-protect
+ (setq proc (apply 'noshell-procbuf-run procbuf command))
+ (with-current-buffer procbuf
+ (set-process-sentinel proc 'tidy-batch-sentinel)
+ ;;(set-process-coding-system 'dos)
+ (set-process-filter proc 'tidy-batch-output-filter)
+ (let ((win (get-buffer-window procbuf)))
+ (when win
+ (set-window-point win (point-max))
+ ))
+ ))))
+
+;;;}}} +
+
+;;;}}}
+
+;; (with-temp-buffer
+;; (tidy-parse-config-file))
+
+(defun wab-compilation-button-at (pos)
+ (let ((old (point))
+ ret)
+ (goto-char pos)
+ (setq ret (eq 'compilation-button-map
+ (get-char-property pos 'keymap)))
+ (goto-char old)
+ ret))
+
+(defun wab-click (&optional event)
+ "Do the action that is tighed to the button."
+ (interactive (list last-input-event))
+ (if event (posn-set-point (event-end event)))
+ (let ((button (get-char-property (point) 'button))
+ done)
+ (condition-case nil
+ (progn
+ (compile-goto-error)
+ (setq done t))
+ (error nil))
+ (unless done
+ (when button
+ (if (widget-at)
+ ;;(widget-apply-action button event)
+ (widget-apply-action button)
+ (push-button))))))
+
+(defvar wab-errors-supress
+ '("No more buttons"
+ "Moved past last error"
+ "No buttons or fields found"
+ "Moved back before first error"
+ ))
+
+(defun wab-fb-errmsg (err)
+ (let ((s (error-message-string err)))
+ (unless (member s wab-errors-supress)
+ (message "%s" err)
+ (signal (car err) (cdr err)))))
+
+(defun wab-fb-helper (forward function check-at args)
+ (let (ret
+ (len (1+ (- (point-max) (point-min))))
+ (old (point)))
+ (condition-case err
+ (progn
+ (apply function args)
+ (when (funcall check-at (point))
+ (setq ret (point))))
+ (error (wab-fb-errmsg err)))
+ (unless ret
+ (if forward
+ (goto-char (point-min))
+ (goto-char (point-max)))
+ (condition-case err
+ (progn
+ (apply function args)
+ (when (funcall check-at (point))
+ (setq ret (point))))
+ (error (message "%s" (error-message-string err)))))
+ (goto-char old)
+ (when (and ret (= ret old))
+ (if forward
+ (setq ret (+ ret len))
+ (setq ret (- ret len))))
+ ;;(message "function=%s, ret=%s" function ret)
+ ret))
+(defvar wab-button-list
+ '(
+ (compilation-previous-error (1) compilation-next-error (1) wab-compilation-button-at)
+ (backward-button (1) forward-button (1) button-at)
+ (widget-backward (1) widget-forward (1) widget-at)
+ ))
+(defun wab-fb (forward)
+ ;;(message "==================")
+ (let* ((pos-list (mapcar (lambda (p)
+ (let ((prev-fun (nth 0 p))
+ (prev-arg (nth 1 p))
+ (next-fun (nth 2 p))
+ (next-arg (nth 3 p))
+ (test-fun (nth 4 p)))
+ (if forward
+ (wab-fb-helper t next-fun test-fun next-arg)
+ (wab-fb-helper nil prev-fun test-fun prev-arg))))
+ wab-button-list))
+ (len (1+ (- (point-max) (point-min))))
+ (defpos (if forward (* 2 len) (- len)))
+ (newpos defpos)
+ (here (point)))
+ ;;(message "pos-list=%s" pos-list)
+ (mapc (lambda (p) (when (and p
+ (if forward
+ (progn
+ (when (< p here)
+ (setq p (+ p len)))
+ (< p newpos))
+ (when (> p here)
+ (setq p (- p len)))
+ (> p newpos)))
+ (setq newpos p)))
+ pos-list)
+ (if (= newpos defpos)
+ (setq newpos here)
+ (setq newpos (mod newpos len)))
+ (goto-char newpos)))
+
+(defun wab-backward ()
+ "Go to next button or error link."
+ (interactive)
+ (wab-fb nil))
+
+(defun wab-forward ()
+ "Go to previous button or error link."
+ (interactive)
+ (wab-fb t))
+
+(define-compilation-mode wab-compilation-mode "WAB Compilation"
+ "Mode for tidy control buffer."
+ )
+(define-key wab-compilation-mode-map [tab] 'wab-forward)
+(define-key wab-compilation-mode-map [(shift tab)] 'wab-backward)
+(define-key wab-compilation-mode-map [backtab] 'wab-backward)
+(define-key wab-compilation-mode-map "\r" 'wab-click)
+(define-key wab-compilation-mode-map [mouse-1] 'wab-click)
+(define-key wab-compilation-mode-map [mouse-2] 'wab-click)
+
+(defvar tidy-menu-mode-map
+ (let ((map (make-sparse-keymap)))
+ ;; This did not work:
+ ;;(define-key map [menu-bar tidy-menu] (list 'menu-item "Tidy" '(lambda () (interactive) tidy-menu-symbol)))
+ map))
+
+(define-minor-mode tidy-menu-mode
+ "This mode just adds Tidy to the menu bar."
+ nil
+ nil
+ nil
+ (when tidy-menu-mode
+ (define-key tidy-menu-mode-map [menu-bar tidy-menu]
+ (list 'menu-item "Tidy" tidy-menu-symbol))))
+
+(provide 'tidy-xhtml)
+
+;;; tidy-xhtml.el ends here