From: Stefan Bund Date: Mon, 6 Aug 2012 08:20:51 +0000 (+0200) Subject: multiple updates: X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=4ef831f9faaf8ca7ee36ca656c0d511be00ae1bc;p=emacs-init.git multiple updates: * update python integration * add global binding for toggle-truncate-lines * dired-x and dired-omit git files * move history navigation in eshell to C- / C- * add gnuplot mode * better eshell / git integration (set some GIT_* env vars) * more flexible my-setup-windows --- diff --git a/gnuplot/autoload.el b/gnuplot/autoload.el new file mode 100644 index 0000000..1d2a99b --- /dev/null +++ b/gnuplot/autoload.el @@ -0,0 +1,21 @@ +;;-------------------------------------------------------------------- +;; Lines enabling gnuplot-mode + +;; move the files gnuplot.el to someplace in your lisp load-path or +;; use a line like +;; (setq load-path (append (list "/path/to/gnuplot") load-path)) + +;; these lines enable the use of gnuplot mode + (autoload 'gnuplot-mode "gnuplot" "gnuplot major mode" t) + (autoload 'gnuplot-make-buffer "gnuplot" "open a buffer in gnuplot mode" t) + +;; this line automatically causes all files with the .gp extension to +;; be loaded into gnuplot mode + (setq auto-mode-alist (append '(("\\.gp$" . gnuplot-mode)) auto-mode-alist)) + +;; This line binds the function-9 key so that it opens a buffer into +;; gnuplot mode +; (global-set-key [(f9)] 'gnuplot-make-buffer) + +;; end of line for gnuplot-mode +;;-------------------------------------------------------------------- diff --git a/gnuplot/dot.el b/gnuplot/dot.el new file mode 100644 index 0000000..3ecc1c9 --- /dev/null +++ b/gnuplot/dot.el @@ -0,0 +1,7 @@ +;; These are some lines to help compilation of gnuplot-mode proceed +;; with fewer warning messages +(setq load-path (append (list ".") load-path) + byte-compile-verbose nil + byte-compile-warnings nil) +(require 'font-lock) +(defun hilit-repaint-command (foo)) diff --git a/gnuplot/gnuplot-gui.el b/gnuplot/gnuplot-gui.el new file mode 100644 index 0000000..02960b0 --- /dev/null +++ b/gnuplot/gnuplot-gui.el @@ -0,0 +1,1748 @@ +;;;; gnuplot-gui.el -- GUI interface to setting options in gnuplot-mode + +;; Copyright (C) 1998-2000 Bruce Ravel + +;; Author: Bruce Ravel +;; Maintainer: Bruce Ravel +;; Created: 19 December 1998 +;; Updated: 16 November 2000 +;; Version: (same as gnuplot.el) +;; Keywords: gnuplot, plotting, interactive, GUI + +;; This file is not part of GNU Emacs. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. +;; +;; This lisp script 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. +;; +;; Permission is granted to distribute copies of this lisp script +;; provided the copyright notice and this permission are preserved in +;; all copies. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, you can either send email to this +;; program's maintainer or write to: The Free Software Foundation, +;; Inc.; 675 Massachusetts Avenue; Cambridge, MA 02139, USA. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; send bug reports to the authors (ravel@phys.washington.edu) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; Commentary: +;; +;; This file provides a graphical user interface to setting arguments +;; to gnuplot commands. Positioning point near a command and invoking +;; `gnuplot-gui-set-options-and-insert' (C-c C-c or shift-mouse-2) +;; will pop open a frame with widgets for setting the various +;; arguments appropriate the the item that was near point. The goal +;; is to provide point-and-click functionality to gnuplot-mode. +;; +;; gnuplot-gui is designed for gnuplot 3.7, but since much of 3.7 is +;; backward compatible to 3.5, it will work well for that version +;; also. +;; +;; gnuplot-gui.el was developed using Emacs 19.34 and is known to work +;; on Emacs 20.x and XEmacs 20.x. I do not know what is the earliest +;; version for which it will work, but I make no guarantees for +;; versions before 19.34. Note that this makes heavy use of the +;; widget package, so this will not work on Emacs 19.34 unless you +;; install the widget package separately. +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; To do: +;; +;; Widgets I need: +;; -- 'position: two or three comma separated numbers used to denote a +;; position or a tic start/end/increment (see arrow, +;; need a prefix) +;; -- 'modifier: colon separated fields used for datafile modifiers +;; +;; command types which are currently unsupported or contain mistakes +;; -- unsupported: cntrparam +;; -- plot, splot, fit: rather lame +;; -- label: position information missing +;; -- label: font string handled in overly simple manner +;; -- hidden3d: not really suited to 'list, but all options are exclusive... +;; -- pointstyle argument to "set label" +;; +;; overall: +;; -- continuation lines (ugh!) +;; -- multiple frames end up displaying same window after setting options +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Code: + +(require 'gnuplot) +(eval-and-compile + (condition-case () + (progn + (require 'widget) + (require 'wid-edit)) + (error nil))) +(require 'cl) +(eval-when-compile ; suppress some compiler warnings + (defvar gnuplot-xemacs-p nil) + (defvar gnuplot-quote-character nil) + (defvar gnuplot-info-display nil) + (defvar gnuplot-mode-map nil)) + +;; (eval-when-compile +;; (require 'wid-edit)) + +(eval-and-compile ; I need this! + (if (fboundp 'split-string) + () + (defun split-string (string &optional pattern) + "Return a list of substrings of STRING which are separated by PATTERN. +If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"." + (or pattern + (setq pattern "[ \f\t\n\r\v]+")) + ;; The FSF version of this function takes care not to cons in case + ;; of infloop. Maybe we should synch? + (let (parts (start 0)) + (while (string-match pattern string start) + (setq parts (cons (substring string start (match-beginning 0)) parts) + start (match-end 0))) + (nreverse (cons (substring string start) parts)))) )) + + + +;;; customizable variables + +(defgroup gnuplot-gui nil + "Graphical interface to setting arguments in gnuplot scrips." + :prefix "gnuplot-gui-" + :group 'gnuplot) + +(defcustom gnuplot-gui-popup-flag nil + "*Non-nil means to open arguments pop-ups automatically. +This would be done after menu insertion of Gnuplot commands." + :group 'gnuplot-gui + :type 'boolean) + +(defvar gnuplot-gui-frame nil + "Frame used to hold the buffer for setting options.") +(defcustom gnuplot-gui-frame-plist + '(height 18 width 65 border-width 0 + user-position t top 150 left 150 + internal-border-width 0 unsplittable t + default-toolbar-visible-p nil has-modeline-p nil + menubar-visible-p nil) + "Frame plist for the input run-time display frame in XEmacs." + :type '(repeat (group :inline t + (symbol :tag "Property") + (sexp :tag "Value"))) + :group 'gnuplot-gui) +(defcustom gnuplot-gui-frame-parameters + '((height . 18) + (width . 65) + (user-position . t) + (top . 150) + (left . 150) + (border-width . 0) + (menu-bar-lines . 0) + (unsplittable . t)) + "Frame parameters for the input run-time display frame in Emacs." + :group 'gnuplot-gui + :type '(repeat (sexp :tag "Parameter:"))) + +(defcustom gnuplot-gui-fontname-list + '(" " "\"Helvetica\"" "\"Times-Roman\"") + "List of known font names. +These *must* be quoted, like so \"\\\"Helvetica\\\"\". This allows +for fonts with names like \"\\\"Arial Bold Italic\\\"\" to be treated +as single entries in the menu-buttons. And it is really important that +the first entry in the list be a blank string." + :group 'gnuplot-gui + :type '(repeat (string :tag "Font name:"))) + +;; some global variables +(defvar gnuplot-current-frame nil) +(defvar gnuplot-current-buffer nil) +(defvar gnuplot-current-buffer-point nil) +(defvar gnuplot-gui-alist nil) +(defvar gnuplot-gui-current-string nil) + + +;;; various tools for handling data structures and text in the buffer + +;; tools for accessing the elements of the lists in `gnuplot-gui-all-types' +(defsubst gnuplot-gui-type-tag (obj) (elt obj 0)) +(defsubst gnuplot-gui-type-symbol (obj) (elt obj 1)) +(defsubst gnuplot-gui-type-default (obj) (elt obj 2)) +(defsubst gnuplot-gui-type-prefix (obj) (elt obj 3)) ; also 'range seperator +(defsubst gnuplot-gui-type-fourth (obj) (elt obj 4)) +(defsubst gnuplot-gui-type-list (obj) (cddr obj)) + +(defun gnuplot-this-word () + "Return the word under point." + (let ((begin (save-excursion (beginning-of-line) (point-marker))) + (end (save-excursion (end-of-line) (point-marker)))) + (save-excursion + (or (looking-at "\\<") (= (current-column) 0) (forward-word -1)) + (if (> (point) begin) (setq begin (point-marker))) + (forward-word 1) + (if (> (point) end) (goto-char end)) + (buffer-substring-no-properties begin (point))))) + + + +;;; data structures containing regarding options in Gnuplot 3.7 + +;; various constants used for options that take the same sorts of arguments +(defconst gnuplot-gui-mtics-list + '(("FREQUENCY" 'number " ") + ("DEFAULT" 'list " " "default"))) +(defconst gnuplot-gui-data-list + '(("DATA TYPE" 'list " " "time"))) +(defconst gnuplot-gui-label-list + '(("LABEL" 'string " ") + ("POSITION" 'position " " "" 2) + ("FONTNAME" 'list " " gnuplot-gui-fontname-list) + ("FONTSIZE" 'fontsize " "))) +(defconst gnuplot-gui-range-list + '(("RANGE" 'range (" " . " ") ":") + ("REVERSE" 'list " " "reverse" "noreverse") + ("WRITEBACK" 'list " " "writeback" "nowriteback"))) +(defconst gnuplot-gui-tics-list + '(("WHERE" 'list " " "axis" "border") + ("MIRROR" 'list " " "mirror" "nomirror") + ("ROTATE" 'list " " "rotate" "norotate") + ("SERIES" 'position " " "" 3) + ("LABEL ARRAY" 'labels () ))) +(defconst gnuplot-gui-zeroaxis-list + '(("LINETYPE" 'number " "))) + +(defvar gnuplot-gui-terminal-types nil + "Associated list of terminal descriptions. +See the doc-string for `gnuplot-gui-all-types'.") +(setq gnuplot-gui-terminal-types + (list (cons "aifm" + '(("COLOR" 'list " " "monochrome" "gray" "color") + ("FONTNAME" 'list " " gnuplot-gui-fontname-list) + ("FONTSIZE" 'fontsize " "))) + (cons "cgm" + '(("MODE" 'list " " "landscape" "portrait" "default") + ("COLOR" 'list " " "color" "monochrome") + ("ROTATION" 'list " " "rotate" "norotate") + ("WIDTH" 'number " " "width") + ("LINEWIDTH" 'number " " "linewidth") + ("FONTNAME" 'list " " "\"Arial\"" "\"Arial Italic\"" + "\"Arial Bold\"" "\"Arial Bold Italic\"" + "\"Times Roman\"" "\"Times Roman Italic\"" + "\"Times Roman Bold\"" "\"Times Roman Bold Italic\"" + "\"Helvetica\"" "\"Roman\"") + ("FONTSIZE" 'fontsize " "))) + (cons "corel" + '(("COLOR" 'list " " "default" "color" "monochrome") + ("FONTNAME" 'list " " "\"SwitzerlandLight\"" + "\"Helvetica\"" "\"Times-Roman\"") + ("FONTSIZE " 'number " ") + ("X-SIZE " 'number " ") + ("Y-SIZE " 'number " ") + ("LINEWIDTH" 'number " "))) + (cons "dumb" + '(("LINEFEED" 'list " " "feed" "nofeed") + ("X-SIZE" 'number " ") + ("Y-SIZE" 'number " "))) + (cons "emf" + '(("COLOR" 'list " " "color" "monochrome") + ("LINE" 'list " " "solid" "dashed") + ("FONTNAME" 'string " ") + ("FONTSIZE" 'number " "))) + (cons "emtex" + '(("FONTNAME" 'list " " "courier" "roman") + ("FONTSIZE" 'fontsize " "))) + (cons "fig" + '(("COLOR" 'list " " "color" "monochrome") + ("FRAMESIZE" 'list " " "small" "big") + ("POINTSMAX" 'number " " "pointsmax") + ("ORIENTATION" 'list " " "landscape" "portrait") + ("UNITS" 'list " " "metric" "inches") + ("FONT SIZE" 'number " " "fontsize") + ("SIZE" 'pair (" " . " ") "size") + ("LINE THICKNESS" 'number " " "thickness") + ("LAYER DEPTH" 'number " " "depth"))) + (cons "hp500c" + '(("RESOLUTION" 'list " " "75" "100" "150" "300") + ("COMPRESSION" 'list " " "rle" "tiff"))) + (cons "hpgl" + '(("PENS" 'number " ") + ("EJECT" 'list " " "eject"))) + (cons "hpdj" + '(("RESOLUTION" 'list " " "75" "100" "150" "300"))) + (cons "hpljii" + '(("RESOLUTION" 'list " " "75" "100" "150" "300"))) + (cons "hppj" + '(("FONT" 'list " " "FNT9X17" "FNT5X9" "FNT13X25"))) + (cons "imagen" + '(("FONT SIZE" 'number " ") + ("LAYOUT" 'list " " "portrait" "landscape") + ("NUMBER OF GRAPHS" 'range (" " . " ") ","))) + (cons "gpic" + '(("X ORIGIN" 'number " ") + ("Y ORIGIN" 'number " " ","))) + (cons "latex" + '(("FONTNAME" 'list " " "courier" "roman") + ("FONTSIZE" 'fontsize " "))) + (cons "mif" + '(("COLOUR" 'list " " "colour" "monochrome") + ("LINETYPE" 'list " " "polyline" "vectors"))) + (cons "nec-cp6" + '(("MODE" 'list " " "monochrome" "colour" "draft"))) + (cons "pbm" + '(("SIZE" 'list " " "small" "medium" "large") + ("COLOR" 'list " " "monochrome" "gray" "color"))) + (cons "pcl5L" + '(("MODE" 'list " " "landscape" "portrait") + ("FONTNAME" 'list " " "stick" "univers" "cg_times") + ("FONTSIZE" 'fontsize " "))) + (cons "png" + '(("SIZE" 'list " " "small" "medium" "large") + ("COLOR" 'list " " "monochrome" "gray" "color"))) + (cons "postscript" + '(("MODE" 'list " " "landscape" "portrait" "eps" "default") + ("ENHANCED" 'list " " "enhanced" "noenhanced") + ("COLOR" 'list " " "color" "monochrome") + ("SOLID" 'list " " "solid" "dashed") + ("DUPLEXING" 'list " " "defaultplex" "simplex" "duplex") + ("FONTNAME" 'list " " gnuplot-gui-fontname-list) + ("FONTSIZE" 'fontsize " "))) + (cons "pslatex" + '(("COLOR" 'list " " "monochrome" "color") + ("DASHED" 'list " " "dashed") + ("ROTATION" 'list " " "rotate" "norotate") + ("AUXFILE" 'list " " "auxfile"))) + (cons "pstex" + '(("COLOR" 'list " " "monochrome" "color") + ("DASHED" 'list " " "dashed") + ("ROTATION" 'list " " "rotate" "norotate") + ("AUXFILE" 'list " " "auxfile"))) + (cons "pstricks" + '(("HACK TEXT" 'list " " "hacktext" "nohacktext") + ("PLOT SCALING" 'list " " "nounit" "unit"))) + (cons "regis" + '(("COLOR DEPTH" 'list "4" "16"))) + (cons "tgif" + '(("LAYOUT" 'list " " "portrait" "landscape") + ("NUMBER OF GRAPHS" 'range (" " . " ") ",") + ("LINE TYPE" 'list " " "solid" "dashed") + ("FONTNAME" 'list " " gnuplot-gui-fontname-list) + ("FONTSIZE" 'fontsize " "))) + (cons "tpic" + '(("POINTSIZE" 'number " ") + ("LINEWIDTH" 'number " ") + ("INTERVAL " 'number " "))) + (cons "vgagl" ; for pm3d patch (also persist, raise in x11) + '(("BACKGROUND" 'position " " "background" 3) + ("INTERPOLATION" 'list " " "uniform" "interpolate") + ("DUMP" 'file " ") + ("MODE" 'string " " ""))) + (cons "x11" + '(("RESET" 'list " " "reset") + ("TERMINAL NUMBER" 'number " ") + ("PERSIST" 'list " " "persist" "nopersist") + ("RAISE" 'list " " "raise" "noraise"))) )) + +(defvar gnuplot-gui-terminal-list nil) +(setq gnuplot-gui-terminal-list + (append (list " ") (mapcar 'car gnuplot-gui-terminal-types))) + +(defvar gnuplot-gui-set-types nil + "Associated list of set option descriptions. +See the doc-string for `gnuplot-gui-all-types'.") +(setq gnuplot-gui-set-types + (list (cons "angles" + '(("UNITS" 'list " " "degrees" "radians"))) + (cons "arrow" + '(("TAG" 'tag " ") + ("FROM" 'position " " "from" 3) + ("TO" 'position " " "to" 3) + ("HEAD" 'list " " "head" "nohead") + ("LINESTYLE" 'number " " "ls") + ("LINETYPE " 'number " " "lt") + ("LINEWIDTH" 'number " " "lw"))) + (cons "noarrow" + '(("TAG" 'tag " "))) + (cons "autoscale" + '(("AXIS" 'list " " "x" "y" "z" "x2" "y2" "xy" + "xmin" "ymin" "zmin" "x2min" "y2min" "xymin" + "xmax" "ymax" "zmax" "x2max" "y2max" "xymax"))) + (cons "noautoscale" + '(("AXIS" 'list " " "x" "y" "z" "x2" "y2" "xy" + "xmin" "ymin" "zmin" "x2min" "y2min" "xymin" + "xmax" "ymax" "zmax" "x2max" "y2max" "xymax"))) + (cons "bar" + '(("SIZE" 'list " " "small" "large"))) + (cons "border" + '(("BORDER CODE" 'number " ") + ("LINE STYLE" 'list " " "lines" + "dots" "points" "linespoints") + ("LINESTYLE" 'number " " "ls") + ("LINETYPE" 'number " " "lt") + ("LINEWIDTH" 'number " " "lw") + )) + (cons "boxwidth" + '(("WIDTH" 'number " "))) + (cons "clabel" + '(("FORMAT" 'format " "))) + (cons "clip" + '(("CLIP TYPE" 'list " " "points" "one" "two"))) + (cons "noclip" + '(("CLIP TYPE" 'list " " "points" "one" "two"))) + ;;(cons "cntrparam" + ;; '(("INTERPOLATION" 'list " " "linear" "cubicspline" "bspline") + ;; ("POINTS" 'number " " "points") + ;; ("ORDER" 'number " " "order"))) + (cons "contour" + '(("WHERE" 'list " " "base" "surface" "both"))) + (cons "dgrid3d" + '(("ROW,COLUMN,NORM" 'position " " "" 3))) + (cons "encoding" + '(("ENCODING" 'list " " "default" "iso_8859_1" + "cp850" "cp437"))) + (cons "format" + '(("AXIS" 'list " " "x" "y" "z" "xy" "x2" "y2") + ("FORMAT" 'format " "))) + (cons "dummy" + '(("VAR 1" 'string " " "") + ("VAR 2" 'string " " ","))) + (cons "grid" + '(("XTICS" 'list " " "xtics" "mxtics" "noxtics" "nomxtics") + ("YTICS" 'list " " "ytics" "mytics" "noytics" "nomytics") + ("ZTICS" 'list " " "ztics" "mztics" "noztics" "nomztics") + ("X2TICS" 'list " " "x2tics" "mx2tics" "nox2tics" "nomx2tics") + ("Y2TICS" 'list " " "y2tics" "my2tics" "noy2tics" "nomy2tics") + ("POLAR" 'number " " "polar") + ("MAJOR LINETYPE" 'number " ") + ("MINOR LINETYPE" 'number " "))) + (cons "hidden3d" + '(("ALGORITHM" 'list " " "defaults" + "offset" + "nooffset" + ;;"trianglepattern # bitpattern between 0 and 7" + "trianglepattern 0" "trianglepattern 1" + "trianglepattern 2" "trianglepattern 3" + "trianglepattern 4" "trianglepattern 5" + "trianglepattern 6" "trianglepattern 7" + ;;"undefined # level between 0 and 3" + "undefined 0" "undefined 1" "undefined 2" "undefined 3" + "noundefined" "altdiagonal" "noaltdiagonal" + "bentover" "nobentover"))) + (cons "historysize" + '(("SIZE" 'number " "))) + (cons "isosamples" + '(("ISO_U LINES" 'number " ") + ("ISO_V LINES" 'number " " ","))) + (cons "key" + '(("LOCATION" 'list " " "left" "right" "top" "bottom" + "outside" "below") + ("POSITION" 'position " " "" 3) + ("JUSTIFICATION" 'list " " "Left" "Right") + ("REVERSE" 'list " " "reverse" "noreverse") + ("SAMPLE LENGTH" 'number " " "samplen") + ("SPACING" 'number " " "spacing") + ("WIDTH" 'number " " "width") + ("TITLE" 'string " " "title ") + ("BOX LINETYPE" 'number " " "box") ;; linetype data + ("NOBOX" 'list " " "nobox"))) + (cons "label" + '(("TAG" 'tag " ") + ("LABEL TEXT" 'string " ") + ("POSITION" 'position " " "at" 3) + ;; first, second, graph, screen + ("JUSTIFICATION" 'list " " "left" "right" "center") + ("ROTATE" 'list " " "rotate" "norotate") + ("FONT" 'string " " "font"))) ;; font "name,size" + (cons "nolabel" + '(("TAG" 'tag " "))) + (cons "linestyle" + '(("TAG " 'tag " ") + ("LINE STYLE" 'list " " "boxerrorbars" "boxes" + "boxxyerrorbars" "candlesticks" "dots" + "financebars" "fsteps" "histeps" "impulses" + "lines" "linespoints" "points" "steps" "vector" + "xerrorbars" "xyerrorbars" "yerrorbars") + ("LINETYPE " 'number " " "lt") + ("LINEWIDTH" 'number " " "lw") + ("POINTTYPE" 'number " " "pt") + ("POINTSIZE" 'number " " "ps"))) + (cons "locale" + '(("LOCALE" 'string " "))) + (cons "logscale" + '(("AXIS" 'list " " "x" "y" "z" "xy" "xz" "yz" "xyz" + "x2" "y2") + ("BASE" 'number " "))) + (cons "nologscale" + '(("AXIS" 'list " " "x" "y" "z" "xy" "xz" "yz" "xyz" + "x2" "y2"))) + (cons "mapping" + '(("COORDINATE SYSTEM" 'list " " "cartesian" "spherical" + "cylindrical"))) + ; _margin + (cons "bmargin" + '(("BOTTOM MARGIN" 'number " "))) + (cons "lmargin" + '(("LEFT MARGIN" 'number " "))) + (cons "rmargin" + '(("RIGHT MARGIN" 'number " "))) + (cons "tmargin" + '(("TOP MARGIN" 'number " "))) + + (cons "missing" + '(("CHARACTER" 'string " " 1))) + ; m_tics + (cons "mxtics" gnuplot-gui-mtics-list) + (cons "mytics" gnuplot-gui-mtics-list) + (cons "mztics" gnuplot-gui-mtics-list) + (cons "mx2tics" gnuplot-gui-mtics-list) + (cons "my2tics" gnuplot-gui-mtics-list) + + ; pm3d additions + (cons "mouse" + '(("DOUBLECLICK" 'number " " "doubleclick") + ("ZOOM" 'list " " "zoomcoordinates" "nozoomcoordinates") + ("POLAR" 'list " " "polarcoordinates" "nopolarcoordinates") + ("FORMAT" 'string " " "format") + ("CLIPBOARDFORMAT" 'string " " "clipboardformat") + ("MOUSEFORMAT" 'string " " "mouseformat") + ("LABELS" 'list " " "labels" "nolabels") + ("LABELOPTIONS" 'string " " "labeloptions") + ("ZOOMJUMP" 'list " " "zoomjump" "nozoomjump") + ("VERBOSE" 'list " " "verbose" "noverbose"))) + (cons "palette" + '(("COLOR" 'list " " "gray" "color") + ("RGBFORMULAE" 'position " " "rgbformulae" 3) + ("PARITY" 'list " " "positive" "negative") + ("FORMULAE" 'list " " "nops_allcF" "ps_allcF") + ("MAXCOLORS" 'number " ") + ("COLOR_BOX" 'list " " "nocb" "cbdefault" "cbuser") + ("ORIENTATION" 'list " " "cbvertical" "cbhorizontal") + ("ORIGIN" 'position " " "origin" 2) + ("SIZE" 'position " " "size" 2) + ("BORDER" 'number " ") + ("NOBORDER" 'list " " "bdefault" "noborder"))) + (cons "pm3d" + '(("AT" 'list* " " "b" "s" "t" "bs" "bt" "st" "bst") + ("SCANS" 'list " " "scansautomatic" "scansforward" "scansbackward") + ("FLUSH" 'list* " " "begin" "center" "end") + ("CLIP" 'list " " "clip1in" "clip4in") + ("ZRANGE" 'range (" " . " ") ":") + ("HIDDEN3D" 'number " ") + ("NOHIDDEN3D" 'list " " "nohidden3d") + ("FILLING" 'list " " "transparent" "solid") + ("MAP" 'list " " "map"))) + + (cons "offsets" + '(("LEFT " 'number " ") + ("RIGHT " 'number " " ",") + ("TOP " 'number " " ",") + ("BOTTOM" 'number " " ","))) + (cons "origin" + '(("X ORIGIN" 'number " ") + ("Y ORIGIN" 'number " " ","))) + (cons "output" + '(("FILENAME" 'file " "))) + (cons "pointsize" + '(("MULTIPLIER" 'number " "))) + (cons "samples" + '(("2D PLOT" 'number " ") + ("3D PLOT" 'number " " ","))) + (cons "size" + '(("ASPECT" 'list " " "square" "nosquare" + "ratio" "noratio") + ("X-SCALE OR RATIO" 'number " ") + ("Y-SCALE" 'number " " ","))) + (cons "style" + '(("DATA TYPE" 'list " " "data" "function") + ("PLOT STYLE" 'list " " "boxerrorbars" "boxes" + "boxxyerrorbars" "candlesticks" "dots" + "financebars" "fsteps" "histeps" "impulses" + "lines" "linespoints" "points" "steps" "vector" + "xerrorbars" "xyerrorbars" "yerrorbars"))) + (cons "terminal" + '(("TERMINAL TYPE" 'list " " gnuplot-gui-terminal-list))) + (cons "tics" + '(("DIRECTION" 'list " " "in" "out"))) + (cons "ticslevel" + '(("RELATIVE HEIGHT" 'number " "))) + (cons "ticscale" + '(("MAJOR" 'number " ") + ("MINOR" 'number " "))) + (cons "timestamp" + '(("FORMAT STRING" 'format " ") + ("WHERE" 'list " " "top" "bottom") + ("ROTATE" 'list " " "rotate" "norotate") + ("X-OFFSET" 'number " ") + ("Y-OFFSET" 'number " " ",") + ("FONTNAME" 'list " " gnuplot-gui-fontname-list))) + (cons "timefmt" + '(("FORMAT STRING" 'string " "))) + (cons "title" + '(("TITLE" 'string " "))) + (cons "view" + '(("X-ROTATION" 'number " ") + ("Z-ROTATION" 'number " " ",") + ("SCALE" 'number " " ",") + ("Z-SCALE" 'number " " ","))) + ;; ("SCALE" 'position " " "," 4) + ; _data + (cons "xdata" gnuplot-gui-data-list) + (cons "ydata" gnuplot-gui-data-list) + (cons "zdata" gnuplot-gui-data-list) + (cons "x2data" gnuplot-gui-data-list) + (cons "y2data" gnuplot-gui-data-list) + ; _label + (cons "xlabel" gnuplot-gui-label-list) + (cons "ylabel" gnuplot-gui-label-list) + (cons "zlabel" gnuplot-gui-label-list) + (cons "x2label" gnuplot-gui-label-list) + (cons "y2label" gnuplot-gui-label-list) + ; _range, note that the [] syntax for + ; the writeback argument is + ; not properly supported + (cons "xrange" gnuplot-gui-range-list) + (cons "yrange" gnuplot-gui-range-list) + (cons "zrange" gnuplot-gui-range-list) + (cons "x2range" gnuplot-gui-range-list) + (cons "y2range" gnuplot-gui-range-list) + (cons "trange" gnuplot-gui-range-list) + (cons "rrange" gnuplot-gui-range-list) + (cons "urange" gnuplot-gui-range-list) + (cons "vrange" gnuplot-gui-range-list) + ; _tics + (cons "xtics" gnuplot-gui-tics-list) + (cons "ytics" gnuplot-gui-tics-list) + (cons "ztics" gnuplot-gui-tics-list) + (cons "x2tics" gnuplot-gui-tics-list) + (cons "y2tics" gnuplot-gui-tics-list) + ; zeroaxis + (cons "zeroaxis" gnuplot-gui-zeroaxis-list) + (cons "xzeroaxis" gnuplot-gui-zeroaxis-list) + (cons "yzeroaxis" gnuplot-gui-zeroaxis-list) + (cons "y2zeroaxis" gnuplot-gui-zeroaxis-list) + (cons "x2zeroaxis" gnuplot-gui-zeroaxis-list) + + (cons "zero" + '(("THRESHOLD" 'number " "))) + )) + +(defvar gnuplot-gui-command-types nil + "Associated list of command descriptions. +See the doc-string for `gnuplot-gui-all-types'.") +(setq gnuplot-gui-command-types + (list (cons "cd" + '(("FILENAME" 'file " "))) + (cons "call" + '(("INPUT FILE" 'file " ") + ("PARAMETER LIST" 'string " "))) + (cons "load" + '(("INPUT FILE" 'file " "))) + (cons "pause" + '(("TIME" 'number " ") + ("MESSAGE" 'string " "))) + (cons "print" + '(("EXPRESSION" 'string " "))) + (cons "save" + '(("SAVE" 'list " " "functions" "variables" "set") + ("FILE" 'file " "))) + (cons "update" + '(("INITIAL FILE" 'file " " t) + ("UPDATED FILE" 'file " " t))) )) + + +(defcustom gnuplot-gui-plot-splot-fit-style 'simple + "Control the complexity of the GUI display for plot, splot, and fit. +The values are 'simple, which causes a limited set of plot, splot, or +fit options to be displayed, and 'complete, which attempts to display +all options. The 'complete setting is prone to making errors when +parsing values already in the script buffer." + :group 'gnuplot-gui + :type '(radio (const :tag "Simple listing" simple) + (const :tag "Complete listing" complete))) + + +(defconst gnuplot-gui-plot-simple-list + '(("X RANGE" 'range (" " . " ") ":") + ("Y RANGE" 'range (" " . " ") ":") + ("DATA FILE" 'file " ") + ("THRU" 'string* " " "thru") + ("USING" 'modifier " ") + ("TITLE" 'string " ") + ("WITH" 'list* " " "boxerrorbars" "boxes" + "boxxyerrorbars" "candlesticks" "dots" "financebars" + "fsteps" "histeps" "impulses" "lines" "linespoints" + "points" "steps" "vector" "xerrorbars" "xyerrorbars" + "yerrorbars"))) +(defconst gnuplot-gui-plot-full-list + '(;;("T RANGE" 'range (" " . " ") ":") + ("X RANGE" 'range (" " . " ") ":") + ("Y RANGE" 'range (" " . " ") ":") + ("xa" 'text "\t---------------------") + ("FUNCTION" 'string " ") + ("xc" 'text " or") + ("DATA FILE" 'file " ") + ("INDEX" 'modifier " ") + ("EVERY" 'modifier " ") + ("THRU" 'string* " " "thru") + ("USING" 'modifier " ") + ("SMOOTH" 'list* " " "unique" "csplines" "acsplines" + "bezier" "sbezier") + ;; datafile modifiers + ("AXES" 'list* " " "x1y1" "x2y2" "x1y2" "x2y1") + ("TITLE" 'string " ") + ("NOTITLE" 'list " " "notitle") + ("xf" 'text "\t---------------------") + ("xi" 'text "Select a standard plotting style") + ("WITH" 'list* " " "boxerrorbars" "boxes" + "boxxyerrorbars" "candlesticks" "dots" "financebars" + "fsteps" "histeps" "impulses" "lines" "linespoints" + "points" "steps" "vector" "xerrorbars" "xyerrorbars" + "yerrorbars") + ("xo" 'text " or a previously defined style") + ("LINE STYLE " 'number " " "ls") + ("xr" 'text " or specify a style in-line") + ("LINE TYPE " 'number " " "lt") + ("LINE WIDTH " 'number " " "lw") + ("POINT TYPE " 'number " " "pt") + ("POINT STYLE" 'number " " "ps") + )) +(defconst gnuplot-gui-splot-simple-list + '(("DATA FILE" 'file " ") + ("TITLE" 'string " ") + ("WITH" 'list* " " "lines" "linespoints" "points" "dots" "impulses"))) +(defconst gnuplot-gui-splot-full-list + '(;;("U RANGE" 'range (" " . " ") ":") + ;;("V RANGE" 'range (" " . " ") ":") + ("X RANGE" 'range (" " . " ") ":") + ("Y RANGE" 'range (" " . " ") ":") + ("Z RANGE" 'range (" " . " ") ":") + ("xa" 'text "\t---------------------") + ("FUNCTION" 'string " ") + ("xc" 'text " or") + ("DATA FILE" 'file " ") + ("INDEX" 'modifier " ") + ("EVERY" 'modifier " ") + ("THRU" 'string* " " "thru") + ("USING" 'modifier " ") + ("SMOOTH" 'list* " " "unique" "csplines" "acsplines" + "bezier" "sbezier") + ("TITLE" 'string " ") + ("NOTITLE" 'list " " "notitle") + ("WITH" 'list* " " "lines" "linespoints" "points" "dots" "impulses"))) +(defconst gnuplot-gui-fit-simple-list + '(("FUNCTION" 'string* " " "") + ("DATA FILE" 'file " ") + ("VIA (params)" 'string* " " "via") )) +(defconst gnuplot-gui-fit-full-list + '(("X RANGE" 'range (" " . " ") ":") + ("Y RANGE" 'range (" " . " ") ":") + ("xa" 'text "----- fitting functionn and file --------") + ("FUNCTION" 'string* " " "") + ("DATA FILE" 'file " ") + ("xb" 'text "----- datafile modifiers ----------------") + ("INDEX" 'modifier " ") + ("EVERY" 'modifier " ") + ("THRU" 'string* " " "thru") + ("USING" 'modifier " ") + ("SMOOTH" 'list* " " "unique" "csplines" "acsplines" + "bezier" "sbezier") + ("xc" 'text "----- parameters (file or parameters) ---") + ("VIA (file)" 'string " " "via") + ("VIA (params)" 'string* " " "via") )) + +(defvar gnuplot-gui-plot-splot-fit nil + "Associated list of plot, splot, and fit descriptions. +See the doc-string for `gnuplot-gui-all-types'.") +(setq gnuplot-gui-plot-splot-fit + (list (cons "plot" (if (equal gnuplot-gui-plot-splot-fit-style 'complete) + gnuplot-gui-plot-full-list + gnuplot-gui-plot-simple-list)) + (cons "splot" (if (equal gnuplot-gui-plot-splot-fit-style 'complete) + gnuplot-gui-splot-full-list + gnuplot-gui-splot-simple-list)) + (cons "fit" (if (equal gnuplot-gui-plot-splot-fit-style 'complete) + gnuplot-gui-fit-full-list + gnuplot-gui-fit-simple-list))) ) + + +(defvar gnuplot-gui-test-type nil) +(setq gnuplot-gui-test-type + (list (cons "test" + '(("TAG" 'tag " ") + ("LIST" 'list " " "1" "2" "3") + ("LIST*" 'list* " " "1" "2" "3") + ("NUMBER" 'number " " "number") + ("RANGE" 'range (" " . " ") ":") + ("PAIR" 'pair (" " . " ") "pair") + ("LABELS" 'labels ()) + ("FILE" 'file " ") + ("TEXT" 'text "this is text") + ("STRING" 'string " ") + ("STRING*" 'string* " " "string*") + ("FORMAT" 'format " ") + ("POSITION" 'position " " "at" 3) + ("FONTSIZE" 'fontsize " ") )))) + +(defvar gnuplot-gui-all-types nil + "Associated list of terminal, set option, and command arguments. + +Each entry in the list is a cons cell of the form + (OPTION . ALIST) +where OPTION is one of the recognized options in Gnuplot, either a +command, something that is set, or a terminal type. Only those +commands, set options, and terminal types that actually take arguments +are in this associated list. + +ALIST is itself an associated list where each entry is of the form: + + (TAG TYPE DEFAULT REST) + +TAG is the name used on the widget and indicates one of the options +for this command, set option, or terminal type. + +TYPE is one of + 'list a menu-list of strings + 'list* a menu-list of strings with a prefix + 'number a number with an optional prefix + 'tag like number but must be the first argument + 'fontsize like number but must be the last argument + 'range a pair of numbers like [#,#] or [#:#] + 'pair a pair of numbers with no punctuation and a prefix + 'file a quoted string and a file browser + 'string a quoted string with an optional prefix + 'string* an unquoted string with a prefix + 'format a quoted string and an info-link to (gnuplot)format + 'labels an array as needed for xtics, ytics, etc + 'position 2 or 3 comma separated numbers with an optional prefix + +DEFAULT is the default value for this option. Note that the default +for 'range and 'pair is a cons cell and the default for 'labels is a +list. For most things, the best choice of DEFAULT is a string of +white space or a cons cell of two strings of white space. Strings of +white space are better defaults than empty strings or nil. + +The value of REST depends upon TYPE: + + For 'list & REST is the list of options that will go into the + 'list* menu-button. This can also be a symbol which + evaluates to a list containing the options to go into + the menu-button. This list variable must contain the + DEFAULT. + For 'number REST is the prefix string (if it exists) for that number. + For 'range REST is the separator, \":\" for plot ranges and + \",\" for plot dimensions (see for example the tgif + terminal type) + For 'string & REST may a number denoting the width of the editable-text + 'string* field or it may be a string denoting a prefix. By + default, the width is half the width of the frame + and there is no prefix. It may be useful to + specify \"1\" when the input is a single character + as in 'set missing'. + For 'file REST determines the label placed before the file insertion + field. If non-nil, then TAG is used. If nil, then + the default \"File\" is used. + For 'position REST is the prefix and the number of comma separated numbers + For others REST is not used. + +Here is an example entry for the png terminal type: + + (cons \"png\" + '((\"SIZE\" 'list \" \" \"small\" \"medium\" \"large\") + (\"COLOR\" 'list \" \" \"monochrome\" \"gray\" \"color\"))) + +This alist is formed at load time by appending together +`gnuplot-gui-terminal-types', `gnuplot-gui-set-types' and +`gnuplot-gui-command-types'.") + +(setq gnuplot-gui-all-types (append gnuplot-gui-terminal-types + gnuplot-gui-set-types + gnuplot-gui-command-types + gnuplot-gui-plot-splot-fit + gnuplot-gui-test-type + )) + + +(defun gnuplot-gui-swap-simple-complete () + (interactive) + (setq gnuplot-gui-plot-splot-fit-style + (if (equal gnuplot-gui-plot-splot-fit-style 'complete) + 'simple 'complete)) + (if (equal gnuplot-gui-plot-splot-fit-style 'complete) + (progn + (setcdr (assoc "plot" gnuplot-gui-all-types) gnuplot-gui-plot-full-list) + (setcdr (assoc "splot" gnuplot-gui-all-types) gnuplot-gui-splot-full-list) + (setcdr (assoc "fit" gnuplot-gui-all-types) gnuplot-gui-fit-full-list)) + (setcdr (assoc "plot" gnuplot-gui-all-types) gnuplot-gui-plot-simple-list) + (setcdr (assoc "splot" gnuplot-gui-all-types) gnuplot-gui-splot-simple-list) + (setcdr (assoc "fit" gnuplot-gui-all-types) gnuplot-gui-fit-simple-list)) + (message "Using %s lists for plot, splot, and fit." + gnuplot-gui-plot-splot-fit-style) ) + + + + +;;; user interface to the widget-y stuff + +(defun gnuplot-gui-mouse-set (event) + "Use the mouse to begin setting options using a GUI interface. +EVENT is a mouse event. Bound to \\[gnuplot-gui-mouse-set] +Note that \"plot\", \"splot\", \"fit\", and \"cntrparam\" are not +currently supported." + (interactive "@e") + (when (fboundp 'widget-create) + (save-excursion + (mouse-set-point event) + (gnuplot-gui-set-options-and-insert)))) + +(defun gnuplot-gui-get-frame-param (param) + (if gnuplot-xemacs-p + (plist-get gnuplot-gui-frame-plist param) + (cdr (assoc param gnuplot-gui-frame-parameters)))) +(defun gnuplot-gui-set-frame-param (param value) + (if gnuplot-xemacs-p + (plist-put gnuplot-gui-frame-plist param value) + (setcdr (assoc param gnuplot-gui-frame-parameters) value))) + +(defun gnuplot-gui-set-options-and-insert () + "Insert arguments using a GUI interface. +Determine contents of current line and set up the appropriate GUI +frame. Bound to \\[gnuplot-gui-set-options-and-insert] +Note that \"cntrparam\" is not currently supported." + (interactive) + (when (fboundp 'widget-create) + (let ((begin (gnuplot-point-at-beginning-of-command)) + (end (save-excursion (end-of-line) (point-marker))) + (termin (concat "\\(,\\s-*" (regexp-quote "\\") "\\|;\\)")) + (set nil) (term nil)) + (save-excursion + ;; there can be more then one command per line + (if (re-search-forward termin end "to_limit") + (progn (backward-char (length (match-string 1))) + (setq end (point-marker)))) + (goto-char begin) + (skip-syntax-forward "-" end) + ;; various constructions are recognized here. at the end of this + ;; cond, point should be just after the word whose arguments are + ;; to be set + (cond ((looking-at "set\\s-+") + (setq set t) + (goto-char (match-end 0)) + (if (looking-at "\\sw+") (goto-char (match-end 0))) + (when (string-match "^ter" (gnuplot-this-word)) ; terminal? + (setq term t) + (forward-word 1)) + (when (string-match "^\\(da\\|fu\\)" (gnuplot-this-word)) + (unless (looking-at "\\s-+st") + (insert " style") (forward-word 1)) + (forward-word 1))) + ((looking-at (concat "\\(cd\\|ca\\|lo\\|pa\\|pr\\|sa\\|u\\)" + "\\w*" + "[\\s-\\']")) + (forward-word 1)) + ;;(goto-char (match-end 0))) + (t + (forward-word 1))) + (if (> (point) end) (goto-char end)) + (let* ((w (gnuplot-this-word)) + (wd (try-completion w gnuplot-gui-all-types)) + (word "") wrd list) + (cond ((equal wd t) (setq word w)) + ((equal wd nil) (setq word w)) + ((assoc wd gnuplot-gui-all-types) (setq word wd)) + (t (setq wd nil))) + (cond ((equal (string-match "^\\s-*$" w) 0) + (message "Blank line")) + ((and wd (stringp word)) + (gnuplot-gui-correct-command word set term begin) + (setq gnuplot-gui-alist nil + gnuplot-gui-current-string + (buffer-substring-no-properties (point) end)) + (gnuplot-gui-set-alist word gnuplot-gui-current-string) + (let* ((old-height (gnuplot-gui-get-frame-param 'height)) + (old-top (gnuplot-gui-get-frame-param 'top))) + (when (or + (and (equal gnuplot-gui-plot-splot-fit-style 'complete) + (member* word '("plot" "splot" "fit") + :test 'string=)) + (equal word "test")) + (gnuplot-gui-set-frame-param 'height 32) + (gnuplot-gui-set-frame-param 'top 50)) + (gnuplot-gui-prompt-for-frame word) + (when (or + (and (equal gnuplot-gui-plot-splot-fit-style 'complete) + (member* word '("plot" "splot" "fit") + :test 'string=)) + (equal word "test")) + (gnuplot-gui-set-frame-param 'height old-height) + (gnuplot-gui-set-frame-param 'top old-top)) )) + ((setq wrd (car (all-completions w '(("cntrparam"))))) + (message + "Setting arguments for %S is currently unsuported in gnuplot-mode" + wrd)) + ((setq list (all-completions w gnuplot-gui-all-types)) + (message "%S could be one of %S" w list)) + (t + (message + "%S is not a gnuplot command which takes options" w)))) )))) + +(defun gnuplot-gui-toggle-popup () + (interactive) + (setq gnuplot-gui-popup-flag (not gnuplot-gui-popup-flag)) + (message (if gnuplot-gui-popup-flag + "Argument popup will appear after insertions." + "Argument popup will no longer appear after insertions."))) + + +(defun gnuplot-gui-y-n (foo)) +(if gnuplot-xemacs-p + (defalias 'gnuplot-gui-y-n 'y-or-n-p-maybe-dialog-box) + (defalias 'gnuplot-gui-y-n 'y-or-n-p)) + +(defun gnuplot-gui-correct-command (word set term begin) + "Check syntax of set command and terminal specifications. +WORD is the item being set. SET and TERM are non-nil if the words +\"set\" and \"terminal\" were found preceding WORD in the buffer. +BEGIN is the beginning of the command." + (save-excursion + (cond ((assoc word gnuplot-gui-terminal-types) + (when (and (not (and set term)) + (gnuplot-gui-y-n + (format + "%S must be preceded by \"set terminal\". Add it? " + word))) + (backward-word 1) + (let ((e (point-marker))) + (goto-char begin) + (skip-syntax-forward "-" e) + (delete-region (point) e) + (insert "set terminal ")))) + ((assoc word gnuplot-gui-set-types) + (when (and (not set) + (gnuplot-gui-y-n + (format + "%S must be preceded by \"set\". Add \"set\"? " word))) + (backward-word 1) + (let ((e (point-marker))) + (goto-char begin) + (skip-syntax-forward "-" e) + (delete-region (point) e) + (insert "set ")))))) + (message nil)) + + + +;;; handle the actual arguments + +(defun gnuplot-gui-fix-arg-list (list) + "Correct the result of splitting `gnuplot-gui-current-string'. +LIST is the split string. This removes empty and all-blank strings +from the list and concatenates the strings that are part of a quoted +argument, for example an axis label or a font name. It also replaces +bounding single quotes with double quotes, since double quotes are +used in `gnuplot-gui-all-types'." + (let (fixed-list quote quoted) ; remove blanks + (setq list (remove* "\\s-+" list :test 'string-match) + list (remove* "" list :test 'string=)) + (while list ; concatinate parts of quoted string + (if (not (string-match "^\\([\]\[()'\"]\\)" (car list))) + (setq fixed-list (append fixed-list (list (car list)))) + (setq quote (match-string 1 (car list)) + quoted (car list)) + (if (string= quote "[") (setq quote "]")) + (if (string= quote "(") (setq quote ")")) + (while (and list + (or (equal (length quoted) 1) + (not (string-match (concat (regexp-quote quote) "$") + quoted)))) + (setq quoted (concat quoted " " (cadr list)) + list (cdr list))) + (if (string= quote "'") + (setq quoted (concat "\"" (substring quoted 1)) + quoted (concat (substring quoted 0 -1) "\""))) + (setq fixed-list (append fixed-list (list quoted)))) + (setq list (cdr list)) ) + fixed-list)) + +(defun gnuplot-gui-set-alist (word string) + "Set defaults for arguments, using text from buffer if appropriate. +WORD is the Gnuplot expression whose arguments are being set. STRING +is text from the buffer containing the previous values for WORD's +arguments." + (let ((alist (cdr (assoc word gnuplot-gui-all-types))) + (arg-list (gnuplot-gui-fix-arg-list (split-string string)) )) + ;; arg-list contains the arguments taken from the buffer + (setq gnuplot-gui-alist nil) + (while alist + (let* ((list (car alist)) + (tag (gnuplot-gui-type-tag list)) + (symbol (eval (gnuplot-gui-type-symbol list))) + (default (gnuplot-gui-type-default list)) + (prefix (gnuplot-gui-type-prefix list)) + (values (gnuplot-gui-type-list list)) + (this-cons (cond ((stringp default) (cons tag default)) + ((consp default) ; set cons valued default w/care + (cons tag (cons (car default) (cdr default)))) + (t (cons tag default)))) + (temp-list arg-list) ) + ;;(message "%S" temp-list) ; want to lop values off arg-list + ; as they are found + (if (symbolp (cadr values)) + (setq values (symbol-value (cadr values)))) + ;; check if an argument of this type is in arg-list + ;; set the current cons cell if it is + (while temp-list + (cond + ;; ---------------------------- list + ((member* symbol '(list list*) :test 'equal) + (let* ((case-fold-search nil) + (match-cons (member* (concat "^" (car temp-list)) + values :test 'string-match))) + (if (and (car match-cons) ; " " may be first elem. of list + (not (string= " " (car match-cons)))) + (setq this-cons (cons tag (car match-cons)) + arg-list (remove* (car temp-list) arg-list + :test 'string= :count 1) + temp-list nil) + (setq temp-list (cdr temp-list))))) + ;; ---------------------------- tag (first number in list) + ((equal symbol 'tag) + (if (string-match "^[-0-9.]+$" (car arg-list)) + (setq this-cons (cons tag (car arg-list)) + temp-list nil) + (setq temp-list (cdr temp-list))) ) + ;; ---------------------------- fontsize (last number in list) + ((equal symbol 'fontsize) + (if (string-match "^[-0-9.]+$" (car (last arg-list))) + (setq this-cons (cons tag (car (last arg-list))) + temp-list nil) + (setq temp-list (cdr temp-list))) ) + ;; ---------------------------- number with prefix + ((equal symbol 'number) + (cond ((and (string= prefix (car temp-list)) + (string-match "^[-0-9.]+$" (cadr temp-list))) + (setq this-cons (cons tag (cadr temp-list)) + arg-list (remove* (car temp-list) arg-list + :test 'string= :count 1) + arg-list (remove* (cadr temp-list) arg-list + :test 'string= :count 1) + temp-list nil)) + ;; --------------------- number without prefix + ((and (not prefix) + (string-match "^[-0-9.]+$" (car temp-list))) + (setq this-cons (cons tag (car temp-list)) + arg-list (remove* (car temp-list) arg-list + :test 'string= :count 1) + temp-list nil)) + (t + (setq temp-list (cdr temp-list))))) + ;; ---------------------------- pair with prefix + ((equal symbol 'pair) + (if (and (string= prefix (car temp-list)) + (string-match "^[-0-9.]+$" (cadr temp-list))) + (let ((this-car (cadr temp-list)) + (this-cdr (if (string-match "^[-0-9.]+$" (caddr temp-list)) + (caddr temp-list) ""))) + (setq this-cons (cons tag (cons this-car this-cdr)) + temp-list nil)) + (setq temp-list (cdr temp-list)))) + ;; ---------------------------- range + ((equal symbol 'range) + (if (string-match (concat "\\[\\s-*" ; opening bracket + "\\([^:, \t]*\\)" ; first argument + "\\s-*[:,]\\s-*" ; separator + "\\([^\] \t]*\\)" ; second argument + "\\s-*\\]") ; closing bracket + (car temp-list)) + (setq this-cons + (cons tag (cons (match-string 1 (car temp-list)) + (match-string 2 (car temp-list)))) + arg-list (remove* (car temp-list) arg-list + :test 'string= :count 1) + temp-list nil) + (setq temp-list (cdr temp-list)) )) + ;; ---------------------------- labels + ((equal symbol 'labels) + (if (string-match (concat "(" ; opening paren + "\\([^\)]*\\)" ; string + ")") ; closing paren + (car temp-list)) + (let* ((list (split-string (car temp-list) "[ \t(),]+")) + (list (remove* "" list :test 'string=)) + (return ())) + (while list + (if (string-match "['\"]\\([^'\"]*\\)['\"]" (car list)) + (setq return (append return + (list (match-string 1 (car list)))) + list (cdr list) + return (append return (list (car list))) ) + (setq return (append return (list "" (car list))))) + (setq list (cdr list)) ) + (setq this-cons (cons tag return) + arg-list (remove* (car temp-list) arg-list + :test 'string= :count 1) + temp-list nil)) + (setq temp-list (cdr temp-list))) ) + ;; ---------------------------- string, file, format + ((member* symbol '(string file format) :test 'equal) + (if (string-match (concat "['\"]" ; opening quote + "\\([^'\"]*\\)" ; string + "['\"]") ; closing quote + (car temp-list)) + (setq this-cons (cons tag (match-string 0 (car temp-list))) + arg-list (remove* (car temp-list) arg-list + :test 'string= :count 1) + temp-list nil) + (setq temp-list (cdr temp-list)) )) + ;; ---------------------------- string* + ((equal symbol 'string*) + (if (string= prefix (car temp-list)) + (setq this-cons (cons tag (cadr temp-list)) + arg-list (remove* (car temp-list) arg-list + :test 'string= :count 1) + arg-list (remove* (cadr temp-list) arg-list + :test 'string= :count 1) + temp-list nil) + (setq temp-list (cdr temp-list)) ) ) + ;; ---------------------------- other or unknown + (t + (setq temp-list nil)) + )) + (setq gnuplot-gui-alist + (append gnuplot-gui-alist (list this-cons)))) + (setq alist (cdr alist))) )) + + +(defun gnuplot-gui-post-process-alist (type) + "A few types need some additional processing. +'range, 'pair, and 'labels are cons or list valued and need to b made +into strings. This is called right before inserting the arguments +into the buffer. TYPE is the object whose arguments are being set." + (let ((alist gnuplot-gui-alist) + (types (cdr (assoc type gnuplot-gui-all-types))) ) + (while alist ;; loop thru alist looking for tyeps needing post-processing + (let* ((list (assoc (caar alist) types)) + (value (cdr (assoc (caar alist) gnuplot-gui-alist))) + (prefix (gnuplot-gui-type-prefix list)) + (symb (gnuplot-gui-type-symbol list)) ) + (cond + ;;-------------------------- flat text + ((equal (eval symb) 'text) + (setcdr (assoc (caar alist) gnuplot-gui-alist) "")) + ;;-------------------------- range [#:#] or [#,#] + ((equal (eval symb) 'range) + (if (and (string-match "^\\s-*$" (car value)) + (string-match "^\\s-*$" (cdr value))) + (setcdr (assoc (caar alist) gnuplot-gui-alist) "") + (setcdr (assoc (caar alist) gnuplot-gui-alist) + (concat "[" (car value) prefix (cdr value) "]")) ) ) + ;;-------------------------- pair + ((equal (eval symb) 'pair) + (if (and (string-match "^\\s-*$" (car value)) + (string-match "^\\s-*$" (cdr value))) + (setcdr (assoc (caar alist) gnuplot-gui-alist) "") + (setcdr (assoc (caar alist) gnuplot-gui-alist) + (concat prefix " " (car value) " " (cdr value) )) ) ) + ;;-------------------------- labels + ((equal (eval symb) 'labels) + (if (consp value) + (let ((word "") (list value)) + (while list + (if (string-match "^\\s-*$" (car list)) + (setq word (concat word (format "%s, " (cadr list)))) + (setq word (concat word (format "%S %s, " (car list) + (cadr list))))) + (setq list (cddr list)) ) + (setq value (concat "(" (substring word 0 -2) ")"))) + (setq value "") ) + (setcdr (assoc (caar alist) gnuplot-gui-alist) value) )) + + (setq alist (cdr alist))) ))) + + +;;; GUI frames + +(defun gnuplot-gui-prompt-for-frame (&optional option save-frame) + (setq option (or option (completing-read "Option: " gnuplot-gui-all-types + nil t nil t))) + (gnuplot-gui-make-frame + option (cdr (assoc option gnuplot-gui-all-types)) save-frame) ) + + +(defface gnuplot-gui-error-face '((((class color) (background light)) + (:foreground "grey30")) + (((class color) (background dark)) + (:foreground "grey70"))) + "Face used to display message about unknown widget types." + :group 'gnuplot-faces) + +(defface gnuplot-gui-flat-text-face '((((class color) (background light)) + (:foreground "MediumBlue")) + (((class color) (background dark)) + (:foreground "LightSteelBlue"))) + "Face used to display message about unknown widget types." + :group 'gnuplot-faces) + +(defun gnuplot-gui-make-frame (item alist &optional save-frame) + "Open the frame and populate it with widgets. +ITEM is the object for which arguments are being set. ALIST is +the alist of arguments for ITEM taken from `gnuplot-gui-all-types'. +SAVE-FRAME is non-nil when the widgets are being reset." + (unless save-frame + (setq gnuplot-current-frame (selected-frame) + gnuplot-current-buffer (current-buffer) + gnuplot-current-buffer-point (point-marker)) + (unless (and gnuplot-gui-frame (frame-live-p gnuplot-gui-frame)) + (setq gnuplot-gui-frame (if gnuplot-xemacs-p + (make-frame gnuplot-gui-frame-plist) + (make-frame gnuplot-gui-frame-parameters)))) + (select-frame gnuplot-gui-frame) + ;;(set-frame-position gnuplot-gui-frame 150 150) ;; so herky-jerky + (if gnuplot-xemacs-p + (set-mouse-position (selected-window) 0 0) + (set-mouse-position gnuplot-gui-frame 0 0))) + (kill-buffer (get-buffer-create "*Gnuplot GUI*")) + (switch-to-buffer (get-buffer-create "*Gnuplot GUI*")) + (kill-all-local-variables) + (if gnuplot-xemacs-p + (progn + (set (make-local-variable 'frame-title-format) + "Set Gnuplot Options") + (set (make-local-variable 'frame-icon-title-format) + "Set Gnuplot Options")) + (modify-frame-parameters (selected-frame) + '((title . "Set Gnuplot Options"))) ) + (widget-insert "\nSet options for \"" item "\" ") + (let (tag help val) + (cond ((string-match "^[xyz]2?tics" item) + (setq tag "info on tic labels" + help "Open a frame displaying the info entry for tic labels" + val "xtics")) + ((string-match "^no" item) + (setq tag (concat "info on " (substring item 2)) + help (format "Open a frame displaying the info entry for %S" + item) + val item)) + (t + (setq tag (concat "info on " item) + help (format "Open a frame displaying the info entry for %S" + item) + val item))) + (widget-create 'gnuplot-gui-info-link :tag tag :help-echo help :value val)) + + (widget-insert "\n\n") + (while alist + (let* ((this (car alist)) + (tag (gnuplot-gui-type-tag this)) + (wtype (gnuplot-gui-type-symbol this)) + (prefix (gnuplot-gui-type-prefix this)) + (default (cdr (assoc tag gnuplot-gui-alist))) + (list (gnuplot-gui-type-list this))) + (if (symbolp (cadr list)) + (setq list (symbol-value (cadr list)))) + (widget-insert "\t") ; insert the appropriate widget + (cond + ;;------------------------------ list, list* ------------ + ((member* (eval wtype) '(list list*) :test 'equal) + (let ((starred (if (equal (eval wtype) 'list*) t nil))) + (gnuplot-gui-menu-choice tag default list starred))) + ;;------------------------------ number, tag, fontsize -- + ((member* (eval wtype) '(number tag fontsize) :test 'equal) + (gnuplot-gui-number tag default prefix)) + ;;------------------------------ position --------------- + ;;------------------------------ range, pair ------------ + ((member* (eval wtype) '(range pair) :test 'equal) + (let ((is-range (equal (eval wtype) 'range))) + (gnuplot-gui-range tag default prefix is-range))) + ;;------------------------------ string, string* -------- + ((member* (eval wtype) '(string string*) :test 'equal) + (let ((starred (if (equal (eval wtype) 'string) nil t))) + (gnuplot-gui-string tag default prefix starred))) + ;;------------------------------ format ----------------- + ((equal (eval wtype) 'format) + (gnuplot-gui-format tag default)) + ;;------------------------------ file ------------------- + ((equal (eval wtype) 'file) + (gnuplot-gui-file tag default prefix)) + ;;------------------------------ labels ----------------- + ((equal (eval wtype) 'labels) + (gnuplot-gui-labels tag default)) + ;;------------------------------ text ------------------- + ((equal (eval wtype) 'text) + (let ((str (gnuplot-gui-type-default this))) + (put-text-property 0 (length str) 'face 'gnuplot-gui-flat-text-face str) + (widget-insert str "\n"))) + ;;------------------------------ unknown ---------------- + (t + (let ((str (concat "<" (downcase tag) "> ('" + (symbol-name (eval wtype)) + " arguments are not yet supported)\n"))) + (put-text-property 0 (length str) 'face 'gnuplot-gui-error-face str) + (widget-insert str)) ))) + (setq alist (cdr alist))) + ;; insert control buttons: [Set options] [Reset] [Clear] [Cancel] + (widget-insert "\n\t") + (widget-create 'push-button + :value "Set options" + :doc item + :button-face 'gnuplot-gui-button-face + :help-echo "Push this button to set options" + :notify + (lambda (widget &rest ignore) + (kill-buffer (get-buffer-create "*Gnuplot GUI*")) + (delete-frame) + (select-frame gnuplot-current-frame) + (switch-to-buffer gnuplot-current-buffer) + (goto-char gnuplot-current-buffer-point) + (gnuplot-gui-post-process-alist + (widget-get widget :doc)) + (let ((alist gnuplot-gui-alist) marker + (eol (save-excursion (end-of-line) (point-marker) )) ) + (if (re-search-forward ";" eol "to_limit") + (backward-char 1)) + (delete-region gnuplot-current-buffer-point (point-marker)) + (delete-horizontal-space) + (setq marker (point-marker)) + (while alist + (let ((val (cdar alist))) + (if (string-match "^\\s-+$" val) () + (if (string-match "^['\"]\\(.*\\)['\"]$" val) + (setq val (concat gnuplot-quote-character + (match-string 1 val) + gnuplot-quote-character))) + (insert (format " %s" val)))) + (setq alist (cdr alist))) + (setq eol (point-marker)) + (goto-char marker) + (while (< (point) eol) ; a few odd cases + (unless (looking-at (concat "[" (regexp-quote "(") + (regexp-quote "*") ",]")) + (just-one-space)) + (forward-sexp))) + (delete-horizontal-space) + (if (string= "terminal" (widget-get widget :doc)) + (gnuplot-gui-set-options-and-insert)) )) + (widget-insert " ") + (widget-create 'push-button :value "Reset" + :help-echo "Push this button to reset all values" + :button-face 'gnuplot-gui-button-face + :doc item + :notify + (lambda (widget &rest ignore) + (let ((word (widget-get widget :doc))) + (gnuplot-gui-set-alist word gnuplot-gui-current-string) + (gnuplot-gui-prompt-for-frame word t)))) + (widget-insert " ") + (widget-create 'push-button :value "Clear" + :help-echo "Push this button to clear all values" + :button-face 'gnuplot-gui-button-face + :doc item + :notify + (lambda (widget &rest ignore) + (let* ((word (widget-get widget :doc)) + (alist (cdr (assoc word gnuplot-gui-all-types)))) + (while alist + (setcdr (assoc (gnuplot-gui-type-tag (car alist)) + gnuplot-gui-alist) + (gnuplot-gui-type-default (car alist))) + (setq alist (cdr alist))) + (gnuplot-gui-prompt-for-frame word t))) ) + (widget-insert " ") + (widget-create 'push-button :value "Cancel" + :help-echo "Quit setting options and dismiss frame" + :button-face 'gnuplot-gui-button-face + :notify (lambda (widget &rest ignore) + (kill-buffer (get-buffer-create "*Gnuplot GUI*")) + (setq gnuplot-gui-alist nil + gnuplot-gui-current-string nil) + (delete-frame) + (select-frame gnuplot-current-frame))) + (goto-char (point-min)) + (use-local-map widget-keymap) + (widget-setup)) + + +;;; widgets + +(defface gnuplot-gui-menu-face '((((class color) (background light)) + (:bold t :foreground "darkolivegreen")) + (((class color) (background dark)) + (:bold t :foreground "seagreen")) + (t + (:italic t))) + "Face used for menu-buttons." + :group 'gnuplot-faces) +(defface gnuplot-gui-button-face '((((class color) (background light)) + (:bold t :foreground "sienna")) + (((class color) (background dark)) + (:bold t :foreground "tan")) + (t + (:italic t))) + "Face used for push-buttons. +Only used in Emacs. XEmacs displays push-buttons with a pixmap." + :group 'gnuplot-faces) +(defface gnuplot-gui-labels-face '((((class color) (background light)) + (:bold t :foreground "darkslateblue")) + (((class color) (background dark)) + (:bold t :foreground "lightslateblue")) + (t + (:italic t))) + "Face used for insert and delete button in the labels widget." + :group 'gnuplot-faces) + +(defun gnuplot-gui-menu-choice (item default list &optional starred) + "Create a menu widget for the Gnuplot GUI. +ITEM is the object whose arguments are set by this widget, DEFAULT +is the default argument value, LIST contains the items for the pop-up +menu. STARRED is true if this a 'list* widget." + (let ((widget + (apply 'widget-create + 'menu-choice :value default :tag item :doc starred + :button-face 'gnuplot-gui-menu-face + :button-prefix "[" :button-suffix "]" + :help-echo (format "Mouse-2 to view the %S menu" (downcase item)) + :notify + (lambda (widget &rest ignore) + (let ((lab (if (widget-get widget :doc) + (concat (downcase (widget-get widget :tag)) " ") + "" ))) + (setcdr (assoc (widget-get widget :tag) gnuplot-gui-alist) + (if (string= (widget-value widget) " ") "" + (format "%s%s" lab (widget-value widget))) ))) + (mapcar (lambda (x) (list 'item :value x)) + list)))) + (widget-value-set widget default) + (if (and starred (not (string-match "^\\s-*$" default))) + (setcdr (assoc item gnuplot-gui-alist) + (format "%s %s" (downcase item) default))) + widget)) + +(defun gnuplot-gui-number (item default &optional prefix) + "Create a number widget for the Gnuplot GUI. +ITEM is the object whose arguments are set by this widget, DEFAULT +is the default value for the widget, PREFIX is a text string preceding +the numerical argument." + (let ((help-label (or prefix (downcase item)))) + (widget-insert (capitalize item) ": ") + (widget-create 'editable-field + :size 2 :tag item :value default :doc prefix + :help-echo (format "Insert new value of %S here" help-label) + :notify (lambda (widget &rest ignore) + (let ((val (widget-value widget)) + (pre (concat (widget-get widget :doc) " "))) + (setcdr (assoc (widget-get widget :tag) + gnuplot-gui-alist) + (if (string-match + "^\\s-*[-0-9.*]+\\s-*$" val) + (format "%s%s" pre val) "") ))))) + (unless (string-match "^\\s-*$" default) + (setcdr (assoc item gnuplot-gui-alist) (format "%s %s" prefix default))) + (widget-insert " " (make-string (- 40 (current-column)) ?.) + " (numeric value)\n")) + +(defun gnuplot-gui-string (item default &optional width_or_prefix starred) + "Create a string widget for the Gnuplot GUI. +ITEM is the object whose arguments are set by this widget, DEFAULT is +the default value for the widget, and WIDTH_OR_PREFIX is the width of +the text entry field (which defaults to half the frame width) or the +prefix for the string. STARRED is t if quotes are not to be used." + (let ((help-label (downcase item)) width (prefix "") (pp "")) + (cond ((stringp width_or_prefix) + (setq prefix width_or_prefix + pp prefix) + (if starred (setq prefix (concat prefix "_star"))) ) + ((numberp width_or_prefix) + (setq width width_or_prefix))) + (setq width (or width (/ (frame-width) 2))) + (if (string-match "^['\"]" default) + (setq default (replace-match "" nil nil default))) + (if (string-match "['\"]$" default) + (setq default (replace-match "" nil nil default))) + (widget-insert (capitalize item) ": ") + (widget-create + 'editable-field + :size width :tag item :doc prefix :value default + :help-echo (format "Insert new value of %S here" help-label) + :notify (lambda (widget &rest ignore) + (let ((val (widget-value widget)) + (q gnuplot-quote-character) + (p (widget-get widget :doc)) ) + (setcdr (assoc (widget-get widget :tag) gnuplot-gui-alist) + (if (string-match "^\\s-*$" val) + "" + (progn + (if (string-match "_star$" p) + (setq p (concat (substring p 0 -5) " ") + q "")) + (if (string-match "^\\s-+" val) + (setq val (replace-match "" nil nil val))) + (if (string-match "\\s-+$" val) + (setq val (replace-match "" nil nil val))) + (format "%s%s%s%s" p q val q))))))) + (unless (string-match "^\\s-*$" default) + (setcdr (assoc item gnuplot-gui-alist) (format "%s %s" pp default))) + (widget-insert "\n"))) + +(defun gnuplot-gui-format (item default) + "Create a string widget for the Gnuplot GUI. +ITEM is the object whose arguments are set by this widget, DEFAULT is +the default value for the widget, and WIDTH_OR_PREFIX is the width of +the text entry field (which defaults to half the frame width) or the +prefix for the string." + (if (string-match "^['\"]" default) + (setq default (replace-match "" nil nil default))) + (if (string-match "['\"]$" default) + (setq default (replace-match "" nil nil default))) + (widget-insert (capitalize item) ": ") + (widget-create 'editable-field + :size (/ (frame-width) 3) :tag item :value default + :help-echo (format "Insert new format string here") + :notify (lambda (widget &rest ignore) + (let ((val (widget-value widget))) + (setcdr (assoc (widget-get widget :tag) + gnuplot-gui-alist) + (format "%s%s%s" + gnuplot-quote-character + val + gnuplot-quote-character))))) + (widget-insert " ") + (widget-create 'gnuplot-gui-info-link + :tag (concat "info on format") + :help-echo "Open a frame displaying the info entry for format" + :value "format") + (widget-insert "\n")) + + +;; swiped from widget-color-complete +(defun gnuplot-gui-file-completion (widget) + "Complete the filename in WIDGET." + (let* ((str (buffer-substring-no-properties (widget-field-start widget) + (point))) + (file (or (file-name-nondirectory str) "")) + (dir (or (file-name-directory str) "./")) + (val (file-name-completion file dir)) ) + (cond ((eq val t) + (message "Exact match")) + ((null val) + (error "Can't find completion for \"%s\"" str)) + ((not (string-equal str val)) + (insert (substring val (length file)))) + (t + (message "Making completion list...") + (let ((list (file-name-all-completions file dir))) + (with-output-to-temp-buffer "*Completions*" + (display-completion-list list))) + (message "Making completion list...done"))))) + +(defun gnuplot-gui-file (item default &optional tag) + "Create a file widget for the Gnuplot GUI. +ITEM is the object whose arguments is set by this widget, DEFAULT is +the default value for the argument. TAG is non-nil if ITEM rather than +\"File:\" is to be used as the tag." + (setq tag (if tag (capitalize item) "File")) + (if (string-match "^['\"]" default) + (setq default (replace-match "" nil nil default))) + (if (string-match "['\"]$" default) + (setq default (replace-match "" nil nil default))) + (let ((widg (widget-create + 'file + :value default :tag tag + :size (- (/ (frame-width) 2) 3) + :doc item :help-echo "Insert a filename here" + :complete 'gnuplot-gui-file-completion + :notify + (lambda (widget &rest ignore) + (setcdr (assoc (widget-get widget :doc) gnuplot-gui-alist) + (format "%s%s%s" gnuplot-quote-character + (widget-value widget) + gnuplot-quote-character)) )) )) + (widget-insert " ") + (widget-create + 'push-button :value "Browse" + :doc item :help-echo "Browse directories for a filename." + :parent widg + :notify (lambda (widget &rest ignore) + (let ((fname (file-relative-name (read-file-name "File: ") + default-directory)) + (q gnuplot-quote-character)) + (widget-value-set (widget-get widget :parent) fname) + (setcdr (assoc (widget-get widget :doc) gnuplot-gui-alist) + (format "%s%s%s" q fname q)) + (widget-setup)))) + (widget-insert "\n"))) + +(defun gnuplot-gui-labels (item default) + "Create a labels widget for the Gnuplot GUI. +ITEM is the object whose arguments is set by this widget, DEFAULT is +the default value for the argument." + (widget-create + '(editable-list + (list :inline t :tag "Tic label" + (string :tag "label" :size 10 + :help-echo "Enter the tic label here" ) + (string :tag " position" :size 10 + :help-echo "Enter an expression for the tic location here" ))) + :tag (capitalize item) + :value default + :format "%{%t%}:\n%v\t %i\n" + :entry-format "\t %i %d %v\n" + :button-face 'gnuplot-gui-labels-face + :notify (lambda (widget &rest ignore) + (setcdr (assoc (upcase (widget-get widget :tag)) + gnuplot-gui-alist) + (widget-value widget))))) + +(defun gnuplot-gui-range (item default separator is-range) + "Create a range or pair widget for the Gnuplot GUI. +ITEM is the object whose arguments are set by this widget, DEFAULT is +the default value for the widget, SEPARATOR is a text string preceding +the numerical argument, or the prefix for a pair operator. IS-RANGE +is non-nil if this is a 'range widget." + (widget-insert (capitalize item) ": ") + (if is-range (widget-insert "[")) + (widget-create 'editable-field + :size 4 :tag item :value (car default) + :help-echo (format "Insert the first value of the %S here" + (downcase item)) + :notify (lambda (widget &rest ignore) + (setcar (cdr (assoc (widget-get widget :tag) + gnuplot-gui-alist)) + (format "%s" (widget-value widget))))) + (if is-range (widget-insert separator) (widget-insert " ")) + (widget-create 'editable-field + :size 4 :tag item :value (cdr default) + :help-echo (format "Insert the second value of the %S here" + (downcase item)) + :notify (lambda (widget &rest ignore) + (setcdr (cdr (assoc (widget-get widget :tag) + gnuplot-gui-alist)) + (format "%s" (widget-value widget))))) + (if is-range (widget-insert "]")) + (widget-insert " " (make-string (- 39 (current-column)) ?.) + " (numeric values)\n")) + + +;; suppress compiler warning +;;(eval-when-compile (defun gnuplot-info-lookup-symbol (sym mode))) +(define-widget 'gnuplot-gui-info-link 'info-link + "A link to an info file for the Gnuplot GUI." + :action '(lambda (widget &optional event) + (let ((gnuplot-info-display 'frame)) + (if gnuplot-keywords-pending ; + (gnuplot-setup-info-look)) + (gnuplot-info-lookup-symbol (widget-value widget) + 'gnuplot-mode)))) + + +;;; just about done + +(provide 'gnuplot-gui) +;;;============================================================================ +;;; +;;; gnuplot-gui.el ends here diff --git a/gnuplot/gnuplot.el b/gnuplot/gnuplot.el new file mode 100644 index 0000000..1ead637 --- /dev/null +++ b/gnuplot/gnuplot.el @@ -0,0 +1,2945 @@ +;;; gnuplot.el --- drive gnuplot from within emacs + +;; Copyright (C) 1998, 2011 Phil Type and Bruce Ravel, 1999-2002 Bruce Ravel + +;; Author: Bruce Ravel and Phil Type +;; Maintainer: Bruce Ravel +;; Created: June 28 1998 +;; Updated: April 20 2012 +;; Version: 0.6.1 +;; Keywords: gnuplot, plotting + +;; This file is not part of GNU Emacs. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. +;; +;; This lisp script 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. +;; +;; Permission is granted to distribute copies of this lisp script +;; provided the copyright notice and this permission are preserved in +;; all copies. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, you can either send email to this +;; program's maintainer or write to: The Free Software Foundation, +;; Inc.; 675 Massachusetts Avenue; Cambridge, MA 02139, USA. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; send bug reports to the author (bruceravel1@gmail.com) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; Commentary: + +;; +;; This is a major mode for composing gnuplot scripts and displaying +;; their results using gnuplot. It is optimized for use with gnuplot +;; 3.7 or one of the later patchlevels of "version 3.6". It should +;; also work very handily with version 3.5. This mode offers several +;; tools to help you compose your scripts, including syntax +;; colorization using either font-lock or hilit19, a syntax table +;; appropriate to gnuplot, key bindings, pull-down menus, indentation, +;; keyword completions and variable customization using the Custom +;; package. Once the script is composed, there are several function +;; for sending some or all of the script to gnuplot. The interaction +;; with the gnuplot process is within a comint buffer. +;; +;; C-c C-l send current line to gnuplot +;; C-c C-v send current line to gnuplot and move forward 1 line +;; C-c C-r send current region to gnuplot +;; C-c C-b send entire buffer to gnuplot +;; C-c C-f send a file to gnuplot +;; C-c C-i insert filename at point +;; C-c C-n negate set option on current line +;; C-c C-c comment region +;; C-c C-o set arguments for command at point +;; S-mouse-2 set arguments for command under mouse cursor +;; C-c C-h read the gnuplot info file +;; C-c C-e show-gnuplot-buffer +;; C-c C-k kill gnuplot process +;; C-c C-u submit a bug report about gnuplot-mode +;; M-tab or M-ret complete keyword before point +;; ret newline and indent +;; tab indent current line +;; +;; Gnuplot-mode adds two key bindings to the comint buffer: +;; M-C-p plot the current script buffer line-by-line +;; M-C-f save the current script buffer and load that file +;; +;; These two functions are useful for starting up gnuplot-mode. +;; +;; M-x gnuplot-mode +;; start gnuplot-mode in the current buffer +;; +;; M-x gnuplot-make-buffer +;; open a new buffer (which is not visiting a file) and start +;; gnuplot-mode in that buffer +;; +;; --------------------------------------------------------------------- +;; +;; Other lisp files used by gnuplot.el +;; +;; info-look.el (comes with GNU Emacs 20): +;; This provides the interface to the gnuplot-info file and provides +;; on-line help and keyword completion functionality. The version +;; of info-look.el that comes with version 20.2 of Emacs contains a +;; bug that will impede its interaction with the gnuplot info file. +;; You should use the version from the gnuplot-mode homepage +;; instead. info-look is not distributed with XEmacs and so should +;; be installed along with gnuplot-mode when using XEmacs. +;; +;; gnuplot-gui.el (written by Bruce): +;; Defines the GUI interface for setting setting arguments to +;; gnuplot options. This uses the widget package extensively. +;; +;; --------------------------------------------------------------------- +;; +;; This mode was inspired by the original gnu-plot-mode by Gershon +;; Elber, which is distributed with gnuplot itself and which dates +;; back to the early 90's. Although this mode encompasses the +;; functionality of the original, the two share no code and the +;; current implementation takes advantage of many features of modern +;; versions of emacs and adheres (or so I intend) to the major mode +;; conventions described in the emacs-lisp reference for version 19 +;; and later. +;; +;; --------------------------------------------------------------------- +;; +;; Installation +;; ============ +;; +;; A recent version of this file can be found at +;; http://github.com/bruceravel/gnuplot-mode/ +;; +;; To autoload gnuplot-mode on any file with gp extension, put this in +;; your .emacs file +;; (autoload 'gnuplot-mode "gnuplot" "gnuplot major mode" t) +;; (autoload 'gnuplot-make-buffer "gnuplot" "open a buffer in gnuplot-mode" t) +;; +;; Something like +;; (setq auto-mode-alist (append '(("\\.gp$" . gnuplot-mode)) +;; auto-mode-alist)) +;; is useful for having files ending in .gp start up in gnuplot-mode. +;; +;; Something like +;; (global-set-key [(f9)] 'gnuplot-make-buffer) +;; may be useful. This binds f9 to the function that opens a scratch +;; buffer (i.e. one that is not visiting a file) in gnuplot-mode. +;; This is handy for your quick 'n' dirty plotting chores. +;; +;; To use the `gnuplot-info-lookup-symbol' function, the file +;; gnuplot.info MUST be installed somewhere that info can find it. +;; This means you must either: +;; 1. Copy gnuplot.info to the normal info directory or +;; 2. Make sure info can find gnuplot.info by putting this in your +;; .emacs file: +;; (setenv "INFOPATH" +;; (concat (getenv "INFOPATH") ":" +;; (expand-file-name "/path/to/file"))) +;; where "/path/to/file" is the location of gnuplot.info +;; +;; This had been tested extensively with Emacs 19.34 and 20.2 and +;; XEmacs 20.3 and in a limited manner with Emacs 19.30 and XEmacs +;; 19.14. +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; History: + +;; +;; 0.1 Jun 25 1998 Finished with initial release. +;; 0.2 Sep 4 1998 Added filename insertion, indentation, and +;; colorization/completion in comint buffer.
+;; 0.2a Sep 11 1998 made `indent-line-function' buffer-local (whoops!) +;; and fixed some stuff in the installation script
+;; 0.3 Sep 12 1998 include insertions menu
+;; 0.3a Sep 14 1998 fixed bug finding info file if missing, fixed bug +;; starting font-lock, fixed bug re overwriting files in +;; installation script
+;; 0.3b Sep 15 1998 Added (require 'info) to `(eval-and-compile' +;; clause, Added (kill-all-local-variables) to `gnuplot-mode', +;; altered order of:- +;; (provide 'gnuplot) +;; (run-hooks 'gnuplot-load-hook) +;; at the end of the file in case something in the load hook +;; requires gnuplot (oh not that old one again...), added +;; `gnuplot-comint-setup-hook', corrected `gnuplot-mark-active' +;; which caused an error to be raised by (mark) when the mark +;; was inactive Some changes to font-lock rules &
+;; 0.4 Nov 14 1998
Use info-look for info interface. No +;; change to gnuplot-mode user interface, but cleaner code. +;; With info-look, the help funcion works regardless of the +;; version number of gnuplot. Also, `gnuplot-keywords' (used +;; for help, keyword-completion, and hilit19 highlighting) is +;; now generated automatically. +;; 0.4a Nov 18 1998
info-look leaves a couple of really useless +;; buffers lying around so I cleaned them up. Also fixed +;; font-lock rules so that things in quotes get highlighted +;; correctly and the surrounding text is unhighlighted. Fixed +;; up font-lock rules for plot and splot. Added +;; `gnuplot-send-line-and-forward' as suggested by . +;; 0.4b Nov 21 1998
added toolbar for xemacs -- see file +;; gnuplot-toolbar.el. fixed error message in plot line +;; function when line is empty. option added to display the +;; comint buffer showing the gnuplot process in a separate +;; frame +;; 0.4c Minor stuff: Nov 30 1998
fixed highlighting in comint +;; buffer. fixed frame behavior. added "[:]" to range +;; insertions. added :link to defgroup. Dec 1 1998
fixed +;; some mismatched defcustoms. added a few lines to suppress +;; some compile-time warnings. Dec 3 1998
Fixed behavior +;; of filename insertion function. Added more :links to +;; defgroup. +;; 0.4d Dec 6 1998
Added function gnuplot-setup-info-look and +;; variable gnuplot-info-hook to handle various versions of the +;; gnuplot info file. +;; 0.4e Dec 12 1998
Split up gnuplot-insertions-menu for ease of +;; custimization, put menubar initialization in a function. +;; 0.4f Dec 14 1998
defcustom the insertions submenus, add +;; gnuplot-insertion-menu-flag, intelligent Makefile knows +;; which info-look to compile +;; 0.5 Dec 27 1998
wrote initial draft of gnuplot-gui.el, +;; included it in insertions menu and in `gnuplot-insert'. +;; Negate option function, bound to C-c C-n. Dec 29 1998
+;; C-c C-h with no response goes to Commands menu. Transparent +;; toolbar icons. Replace kw-compl with a simple completion +;; function. Put gnuplot-toolbar code in gnuplot.el. +;; 0.5a Jan 23 1999
send file uses the load command. add +;; gnuplot-plot-from-comint and +;; gnuplot-save-and-plot-from-comint and keybindings in the +;; comint buffer. do (process-kill-without-query +;; gnuplot-process nil). `gnuplot-negate-option' checks if set +;; option has a negated form. +;; 0.5b `gnuplot-kill-gnuplot-buffer' made more robust. fixed a bug +;; in `gnuplot-plot-from-comint'. fixed description of +;; gnuplot-faces group. +;; 0.5c update copyright information, update gpelcard +;; 0.5d Mar 20 1999
adopt installation materials from . Add +;; some support for hidden3d. Use constants in types alists in +;; gui. Various other minor improvements to the types alists. +;; 0.5e Apr 6 1999
at the suggestion of I did away with the +;; gnuplot-which-highlight variable and revamped how +;; colorization gets turned on. This is a bit tricky since I +;; want it to work with font-lock under emacs and xemacs and +;; with hilit19. Apr 11 1999
insert space at end of +;; unique completion. add a few GUI types, rewrite some stuff +;; in the GUI interface. primitive support for plot, splot, +;; and fit. Fixed completion in file widget. +;; 0.5f May 15 1999
Add pgnuplot.c and Win9x install instructions +;; to the distribution. Fixed a defface bug. Added +;; `gnuplot-keywords-when' allowing deferral of parsing the +;; info file. +;; 0.5g May 27 1999
Fixed font-locking of strings and +;; comments. Figure out gnuplot-version number from startup +;; message and set `gnuplot-echo-command-line-flag' +;; accordingly. Added `gnuplot-program-version' variable. +;; Check that font-lock is actually a feature, as suggested by +;; +;; 0.5h Aug 15 1999
Added `gnuplot-determine-gnuplot-version' so +;; that the gnuplot version number and `comint-process-echos' +;; actually get set correctly. Actually, the first time +;; something is plotted, the echoing might not work, but the +;; second time it will. +;; 0.5i Sep 2 1999
Once again changed how +;; `comint-process-echos' gets set. Maybe I got it right this +;; time? Also fixed certain situations where the info file +;; did notget properly loaded (insertion with info toggle on +;; and info button in GUI). +;; 0.5j Sep 9 1999
Do a more robust check for the gnuplot +;; process before killing the gnuplot buffer, as suggested by +;; . +;; 0.5k Sep 22 1999
make `gnuplot-send-line-and-forward' skip +;; over blank and comment lines as suggested by . Jan 10 +;; 2000 Bound C-c C-j to `gnuplot-forward-script-line'. +;; 0.5l Nov 16 2000
support for pm3d in gnuplot-gui and in plot +;; options insertions menu. mentioned pm3d in gpelcard. gui +;; support for x11 pm3d and vgagl terms. +;; `gnuplot-negate-option' works with new syntax. +;; 0.5m Nov 17 2000
add colorization and gui support for new +;; commands in 3.8. gui support for emf term. gui support for +;; new "set style" syntax. much better scheme for determining +;; gnuplot version number + make better use of it. +;; 0.5n Jan 4 2001
corrected a serious problem interacting with +;; speedbar +;; 0.5o skipped +;; 0.5p Mar 14 2001
fixed problem with toolbar creation and +;; speedbar clicking +;; 0.5q May 30 2001
added font-lock bindings for words associated +;; with plotting +;; 0.5r Oct 17 2001
Incorporate two suggestions by , bind +;; C-c C-c to comment-region and C-c C-o to the GUI, also make +;; C-c C-l respect continuation lines +;; April 12, 2002
added feature to trim length of gnuplot +;; process buffer +;; 0.5s Jun 7 2002
Yet again changed how `comint-process-echos' +;; gets set. It really needs to be nil on NTEmacs 21.1 or +;; comint gets stuck in an infinate loop. +;; 0.5t Sep 16 2002
Fixed a problem with C-c C-v jumping +;; forward 2 lines at a time +;; 0.6.0 Dec 13 2002
Changed numbering scheme to accommodate +;; gnuplot packaging requirements +;; 0.6.1 Sep 13 2011
Moved to github, updated contact info +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Acknowledgements: +;; David Batty (numerous corrections) +;; Laurent Bonnaud (suggestions regarding font-lock rules) +;; Markus Dickebohm (suggested `gnuplot-send-line-and-forward') +;; Stephen Eglan (suggested the use of info-look, +;; contributed a bug fix regarding shutting +;; down the gnuplot process, improvement to +;; `gnuplot-send-line-and-forward') +;; Robert Fenk (suggested respecting continuation lines) +;; Michael Karbach (suggested trimming the gnuplot process buffer) +;; Alex Chan Libchen (suggested font-lock for plotting words) +;; Kuang-Yu Liu (pointed out buggy dependence on font-lock) +;; Hrvoje Niksic (help with defcustom arguments for insertions) +;; Andreas Rechtsteiner (pointed out problem with C-c C-v) +;; Michael Sanders (help with the info-look interface) +;; Jinwei Shen (suggested functionality in comint buffer) +;; Michael M. Tung (prompted me to add pm3d support) +;; Holger Wenzel (suggested using `gnuplot-keywords-when') +;; Wolfgang Zocher (pointed out problem with gnuplot-mode + speedbar) +;; and especially to Lars Hecking for including gnuplot-mode +;; with the gnuplot 3.7-beta distribution and for providing me with +;; installation materials +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; To Do: +;; +;; 1. Since `gnuplot-display-process' can be nil, it would be +;; handy to have a function to put on +;; `gnuplot-after-plot-buffer-hook' to check and see if the script +;; executed properly. Alas I am not sure how gnuplot signals its +;; errors. +;; 2. improve plot, splot, fit in GUI +;; 3. interface to setting bind command using `read-key-sequence'. +;; this is a pain because the nomenclature is really different in +;; gnuplot than in `read-key-sequence' +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; Code: + +(require 'comint) +(require 'easymenu) + + +;;; --- variable definitions + eval-and-compile clauses + +;; handle defcustom +(eval-and-compile + (condition-case () + (require 'custom) + (error nil)) + (if (and (featurep 'custom) (fboundp 'custom-declare-variable)) + nil ;; We've got what we needed + ;; We have the old custom-library, hack around it! + (if (fboundp 'defgroup) + nil + (defmacro defgroup (&rest args) + nil)) + (if (fboundp 'defface) + nil + (defmacro defface (var values doc &rest args) + (` (progn + (defvar (, var) (quote (, var))) + ;; To make colors for your faces you need to set your .Xdefaults + ;; or set them up ahead of time in your .emacs file. + (make-face (, var)) + )))) + (if (fboundp 'defcustom) + nil + (defmacro defcustom (var value doc &rest args) + (` (defvar (, var) (, value) (, doc))))))) + +;; (eval-and-compile +;; (condition-case () +;; (require 'kw-compl) +;; (error nil))) +(eval-and-compile ;; + (require 'info)) +(eval-and-compile + (condition-case () + (require 'info-look) + (error nil))) + +;; this just gets rid of an annoying compile time error message +;; (eval-when-compile +;; (defun gnuplot-dummy ()) +;; (defalias 'hilit-set-mode-patterns 'gnuplot-dummy)) + + +(defconst gnuplot-xemacs-p (string-match "XEmacs" (emacs-version))) +(defconst gnuplot-ntemacs-p (string-match "msvc" (emacs-version))) +(defvar gnuplot-three-eight-p "") + +(defconst gnuplot-maintainer "Bruce Ravel") +(defconst gnuplot-maintainer-email "ravel@phys.washington.edu") +(defconst gnuplot-maintainer-url + "http://github.com/bruceravel/gnuplot-mode/") +(defconst gnuplot-version "0.6.1") + +(defgroup gnuplot nil + "Gnuplot-mode for Emacs." + :prefix "gnuplot-" + :group 'processes + :group 'applications + :group 'local + :link '(emacs-library-link :tag "Lisp File" "gnuplot.el") + :link '(url-link :tag "Homepage" + "http://github.com/bruceravel/gnuplot-mode/") + :link '(custom-manual "(gnuplot)Top") + :link '(emacs-commentary-link :tag "Commentary" "gnuplot.el") ) +(defgroup gnuplot-insertions nil + "Insert commands into gnuplot-scripts from a pull-down menu." + :prefix "gnuplot-insertions-" + :group 'gnuplot) +(defgroup gnuplot-hooks nil + "Hook variables used by `gnuplot-mode'." + :prefix "gnuplot-" + :group 'gnuplot) + +(defcustom gnuplot-mode-hook nil + "*Hook run when `gnuplot-mode' is entered." + :group 'gnuplot-hooks + :type 'hook) +(defcustom gnuplot-load-hook nil + "*Hook run when gnuplot.el is first loaded." + :group 'gnuplot-hooks + :type 'hook) +(defcustom gnuplot-after-plot-hook nil + "*Hook run after gnuplot plots something. +This is the last thing done by the functions for plotting a line, a +region, a buffer, or a file." + :group 'gnuplot-hooks + :type 'hook) + +(defcustom gnuplot-info-hook nil + "*Hook run before setting up the info-look interface. +This hook is necessary to handle inconsistencies in versions of and +sources of the gnuplot info file. If Gnuplot-mode can find the info +file generated from the 3.6beta patchlevel 347 (or later) release of +Gnuplot, then this hook probably is not necessary. Some versions of +the info file may have a General Index session, which can be used by +info-look. In that case the following (or something similar with the +value of `info-lookup-symbol-alist' altered appropriately) should be +placed in the .emacs file. + +Emacs version 20.2 ships with a different version of info-look that +does 20.3. If you use any version of Emacs 19, you must use the +version from 20.2. Any version of XEmacs 20 or 21 should use the +version from 20.3 but can use either. XEmacs 19 should use the +version 20.2. + +For the newer version of info-look, do this: + + (add-hook \'gnuplot-info-hook + \'(lambda () + (let ((elem (assoc \'gnuplot-mode info-lookup-alist))) + (delete elem info-lookup-alist) + (info-lookup-maybe-add-help + :mode 'gnuplot-mode :topic 'symbol + :regexp \"[a-zA-Z][_a-zA-Z0-9]*\" + :doc-spec '((\"(gnuplot)General Index\" nil + \"[_a-zA-Z0-9]+\")))))) + +For the older version of info-look, do this: + + (add-hook \'gnuplot-info-hook + \'(lambda () + (let ((elem (assoc \'gnuplot-mode info-lookup-alist))) + (delete elem info-lookup-alist) + (setq info-lookup-alist + (append info-lookup-alist + \'((gnuplot-mode + \"[a-zA-Z][_a-zA-Z0-9]*\" nil + ((\"(gnuplot)General Index\" nil + \"[_a-zA-Z0-9]+\" )))))))))" + :group 'gnuplot-hooks + :type 'hook) + +;; comint hook suggested by +(defcustom gnuplot-comint-setup-hook nil + "*Hook run after setting up the gnuplot buffer in comint mode. +So the configuration can be customised by the user." + :group 'gnuplot-hooks + :type 'hook) + +(defcustom gnuplot-comint-mode-hook nil + "*Hook run after setting up the gnuplot buffer in gnuplot-comint-mode. +By default this runs the hook named `gnuplot-comint-setup-hook', +for backward compatibility." + :group 'gnuplot-hooks + :type 'hook) + +(defvar gnuplot-recently-sent nil + "This is a record of the most recent kind of text sent to gnuplot. +It takes as its value nil, 'line, 'region, 'buffer, or 'file. It is +useful for functions included in `gnuplot-after-plot-hook'.") +(make-variable-buffer-local 'gnuplot-recently-sent) + +(defcustom gnuplot-program "gnuplot" + "*The name of the gnuplot executable." + :group 'gnuplot + :type 'string) +(defvar gnuplot-program-version nil + "Version number of gnuplot. +This is using `gnuplot-fetch-version-number'.") +(defvar gnuplot-program-major-version nil + "Major version number of gnuplot. +This is found using `gnuplot-fetch-version-number'.") +(defvar gnuplot-program-minor-version nil + "Minor version number of gnuplot. +This is found using `gnuplot-fetch-version-number'.") + +(defcustom gnuplot-process-name "gnuplot" + "Name given to the gnuplot buffer and process." + :group 'gnuplot + :type 'string) +(defvar gnuplot-buffer nil + "*The name of the buffer displaying the gnuplot process.") +(defvar gnuplot-process nil + "Variable holding the process handle.") +(defvar gnuplot-process-frame nil + "The frame for displaying the gnuplot process. +This is used when `gnuplot-display-process' is equal to 'frame.") +(defvar gnuplot-comint-recent-buffer nil + "The most recently plotted gnuplot script buffer. +This is used by the function that plot from the comint buffer. It is +reset every time something is plotted from a script buffer.") + +(defcustom gnuplot-gnuplot-buffer "plot.gp" + "*The name of the gnuplot scratch buffer opened by 'gnuplot-make-buffer'." + :group 'gnuplot + :type 'string) + +(defcustom gnuplot-display-process 'window + "This controls how the gnuplot process buffer is displayed. +The values are + 'frame display gnuplot process in a separate frame + 'window display gnuplot process in this frame but in another window + nil `gnuplot-process' is in the current frame but not displayed" + :group 'gnuplot + :type '(radio (const :tag "Separate frame" frame) + (const :tag "Separate window" window) + (const :tag "Not displayed" nil))) +(defcustom gnuplot-info-display 'window + "*Determines how `gnuplot-info-lookup-symbol' displays the info file. +The values are + 'frame display info file in a separate frame + 'window display info file in another window + nil display info file in the current window" + :group 'gnuplot + :type '(radio (const :tag "Separate frame" frame) + (const :tag "Separate window" window) + (const :tag "This window" nil))) + +(defcustom gnuplot-echo-command-line-flag (not gnuplot-ntemacs-p) + "*This sets the fall-back value of `comint-process-echos'. +If `gnuplot-mode' cannot figure out what version number of gnuplot +this is, then the value of this variable will be used for +`comint-process-echos'. It seems that gnuplot 3.5 wants this to be +nil and 3.7 wants it to be t. If lines that you send to gnuplot from +the `gnuplot-mode' buffer are not appearing at the gnuplot prompt in +the process buffer, try toggling it. Also see the document string for +`comint-process-echos'. If you change this, kill the gnuplot process +and start it again." + :group 'gnuplot + :type 'boolean) +(defcustom gnuplot-insertions-show-help-flag nil + "*Non-nil means to display certain help messages automatically. +These messages are shown after menu insertion of gnuplot commands." + :group 'gnuplot-insertions + :type 'boolean) + +(defcustom gnuplot-delay 0.01 + "*Amount of time to delay before sending a new line to gnuplot. +This is needed so that the the line is not written in the gnuplot +buffer in advance of its prompt. Increase this number if the +prompts and lines are displayed out of order." + :group 'gnuplot + :type 'number) +(defcustom gnuplot-buffer-max-size 1000 + "*The maximum size in lines of the gnuplot process buffer. +Each time text is written in the gnuplot process buffer, lines are +trimmed from the beginning of the buffer so that the buffer is this +many lines long. The lines are deleted after the most recent lines +were interpretted by gnuplot. Setting to 0 turns off this feature +\(i.e. no lines get trimmed)." + :group 'gnuplot + :type 'integer) +(defcustom gnuplot-quote-character "\'" + "*Quotation character used for inserting quoted strings. +Gnuplot can use single or double quotes. If you prefer to have the +filename insertion function never insert quotes for you, set this +to the empty string." + :group 'gnuplot + :type '(radio (const :tag "double quote" "\"") + (const :tag "single quote" "\'") + (const :tag "none" "" ))) +;; (defcustom gnuplot-gnuplot-version nil +;; "*Force gnuplot-mode to behave for this version of gnuplot." +;; :group 'gnuplot +;; :type '(radio (const :tag "unspecified" nil) +;; (const :tag "3.8 or newer" "3.8") +;; (const :tag "3.7 or older" "3.7"))) + +(defvar gnuplot-info-frame nil) +(defvar gnuplot-info-nodes '()) + +(defvar gnuplot-first-call t) + +;; with info-look, there is no need to carry this list around -- it +;; can be generated on the fly appropriate to the currently installed +;; version of gnuplot.info +(defvar gnuplot-keywords nil + "A list of keywords used in GNUPLOT. +These are set by `gnuplot-set-keywords-list' from the values in +`info-lookup-cache'.") +(defvar gnuplot-keywords-alist nil) ;; For all-completions +(defvar gnuplot-keywords-pending t ;; + "A boolean which gets toggled when the info file is probed.") +(defcustom gnuplot-keywords-when 'deferred ;; 'immediately + "This variable controls when the info file is parsed. +The choices are immediately upon starting gnuplot-mode or the first +time that data is needed. If you use hilit19, then the info file is +parsed immediately regardless of the value of this variable. But +you're not using that musty old thing, are you..." + :group 'gnuplot + :type + '(radio (const :tag "Parse info file when gnuplot-mode starts" immediately) + (const :tag "Parse info file the first time it is needed" deferred))) + +(defgroup gnuplot-faces nil + "Text faces used by gnuplot-mode." + :prefix "gnuplot-" + :group 'gnuplot) + +(cond ((and (featurep 'custom) (fboundp 'custom-declare-variable)) + (defface gnuplot-prompt-face '((((class color)) + (:foreground "firebrick")) + (t + (:bold t :underline t))) + "Face used for the prompt in the gnuplot process buffer." + :group 'gnuplot-faces)) + (t + (make-face 'gnuplot-prompt-face) + (set-face-foreground 'gnuplot-prompt-face "firebrick"))) + + +;;; --- key bindings and menus + +(defvar gnuplot-mode-map nil) +(unless gnuplot-mode-map + (setq gnuplot-mode-map (make-sparse-keymap)) + + (define-key gnuplot-mode-map "\C-c\C-b" 'gnuplot-send-buffer-to-gnuplot) + (define-key gnuplot-mode-map "\C-c\C-c" 'comment-region) ; + (define-key gnuplot-mode-map "\C-c\C-o" 'gnuplot-gui-set-options-and-insert) + (define-key gnuplot-mode-map "\C-c\C-d" 'gnuplot-show-version) + (define-key gnuplot-mode-map "\C-c\C-e" 'gnuplot-show-gnuplot-buffer) + (define-key gnuplot-mode-map "\C-c\C-f" 'gnuplot-send-file-to-gnuplot) + (define-key gnuplot-mode-map "\C-c\C-h" 'gnuplot-info-lookup-symbol) + (define-key gnuplot-mode-map "\C-c\C-i" 'gnuplot-insert-filename) + (define-key gnuplot-mode-map "\C-c\C-j" 'gnuplot-forward-script-line) + (define-key gnuplot-mode-map "\C-c\C-k" 'gnuplot-kill-gnuplot-buffer) + (define-key gnuplot-mode-map "\C-c\C-l" 'gnuplot-send-line-to-gnuplot) + (define-key gnuplot-mode-map "\C-c\C-n" 'gnuplot-negate-option) + (define-key gnuplot-mode-map "\C-c\C-p" 'gnuplot-show-gnuplot-version) + (define-key gnuplot-mode-map "\C-c\C-r" 'gnuplot-send-region-to-gnuplot) + ;;(define-key gnuplot-mode-map "\C-c\C-t" 'gnuplot-gui-swap-simple-complete) + (define-key gnuplot-mode-map "\C-c\C-u" 'gnuplot-bug-report) + (define-key gnuplot-mode-map "\C-c\C-v" 'gnuplot-send-line-and-forward) + (define-key gnuplot-mode-map "\C-c\C-z" 'gnuplot-customize) + (define-key gnuplot-mode-map "\C-i" 'indent-for-tab-command) + (define-key gnuplot-mode-map "\C-m" 'newline-and-indent) + + (let ((completion-function + (if (featurep 'xemacs) + 'gnuplot-xemacs-completion-at-point + 'completion-at-point))) + (define-key gnuplot-mode-map "\M-\r" completion-function) + (define-key gnuplot-mode-map "\M-\t" completion-function)) + + ;;(define-key gnuplot-mode-map "\C-m" 'reindent-then-newline-and-indent) + ;;(if (featurep 'kw-compl) + ;; (define-key gnuplot-mode-map "\M-\r" 'kw-compl-abbrev))) + (cond (gnuplot-xemacs-p + (define-key gnuplot-mode-map '(shift button2) + 'gnuplot-gui-mouse-set)) + (t + (define-key gnuplot-mode-map [S-mouse-2] + 'gnuplot-gui-mouse-set)))) + +(defvar gnuplot-mode-menu nil) +(defvar gnuplot-menu nil + "Menu for `gnuplot-mode'.") +(setq gnuplot-menu + '("Gnuplot" + ["Send line to gnuplot" gnuplot-send-line-to-gnuplot t] + ["Send line & move forward" gnuplot-send-line-and-forward (not (eobp))] + ["Send region to gnuplot" gnuplot-send-region-to-gnuplot + (gnuplot-mark-active)] + ["Send buffer to gnuplot" gnuplot-send-buffer-to-gnuplot t] + ["Send file to gnuplot" gnuplot-send-file-to-gnuplot t] + "---" + ["Insert filename at point" gnuplot-insert-filename t] + ["Negate set option" gnuplot-negate-option t] + ;;["Set key binding" gnuplot-set-binding gnuplot-three-eight-p] + ["Keyword help" gnuplot-info-lookup-symbol + (or gnuplot-keywords gnuplot-keywords-pending)] + ["Show gnuplot process buffer" gnuplot-show-gnuplot-buffer t] + ["Set arguments at point" gnuplot-gui-set-options-and-insert + (fboundp 'gnuplot-gui-set-options-and-insert)] + ["Swap plot/splot/fit lists in GUI" gnuplot-gui-swap-simple-complete + (fboundp 'gnuplot-gui-swap-simple-complete)] + "---" + ["Customize gnuplot" gnuplot-customize t] + ["Submit bug report" gnuplot-bug-report t] + ["Show gnuplot-mode version" gnuplot-show-version t] + ["Show gnuplot version" gnuplot-show-gnuplot-version t] + "---" + ["Kill gnuplot" gnuplot-kill-gnuplot-buffer t] + )) + + +;;; --- insertions variables and menus + +;;(load-library "gnuplot-insertions") +(defvar gnuplot-mode-insertions-menu nil) +(defvar gnuplot-insertions-menu nil + "Menu for insertions in `gnuplot-mode'. + +The insertions menu is composed of several sub-menus. The variables +describing the sub-menus are: + `gnuplot-insertions-adornments' + `gnuplot-insertions-plot-options' + `gnuplot-insertions-terminal' + `gnuplot-insertions-x-axis' + `gnuplot-insertions-y-axis' + `gnuplot-insertions-z-axis' + `gnuplot-insertions-x2-axis' + `gnuplot-insertions-y2-axis' + `gnuplot-insertions-parametric-plots' + `gnuplot-insertions-polar-plots' + `gnuplot-insertions-surface-plots' +These variables can be customized by the user. For example, there are +many terminal types which are not in the terminal submenu but which +may be compiled into a user's copy of gnuplot. + +Each of these variables is a list whose first element is a string and +all the rest are vectors as described in the document string for +`easy-menu-define'. The callback used throughout these menus is +`gnuplot-insert' which inserts the appropriate set expression and, +optionally, looks up that item in the gnuplot info file. + +The easiest way to customize the submenus is to use the custom +package. Just type \\[gnuplot-customize] and follow your nose. + +You can also add new items to any of these sub-menus by adding to the +`gnuplot-load-hook' in your .emacs file. Here is an example of adding +the \"regis\" terminal type to the terminal sub-menu: + + (add-hook + 'gnuplot-load-hook + '(lambda () + (setq gnuplot-insertions-terminal + (append gnuplot-insertions-terminal + (list + [\"regis\" + (gnuplot-insert \"set terminal regis\") + t])))))") + +(defvar gnuplot-insertions-top () + "Top part of insertions menu. +See the document string for `gnuplot-insertions-menu'") + +(defcustom gnuplot-insertions-menu-flag t + "*Non-nil means to place the insertion menu in the menubar. +Changing this will not effect a change in any currently existing +`gnuplot-mode' buffer. You will see the change the next time you +create a `gnuplot-mode' buffer." + :group 'gnuplot-insertions + :type 'boolean) + +(defcustom gnuplot-insertions-adornments ; this is icky... + (if gnuplot-three-eight-p + '("adornments" + ["arrow" (gnuplot-insert "set arrow ") t] + ["bar" (gnuplot-insert "set bar") t] + ["border" (gnuplot-insert "set border") t] + ["boxwidth" (gnuplot-insert "set boxwidth ") t] + ["format" (gnuplot-insert "set format ") t] + ["grid" (gnuplot-insert "set grid") t] + ["key" (gnuplot-insert "set key ") t] + ["label" (gnuplot-insert "set label ") t] + ["pointsize" (gnuplot-insert "set pointsize ") t] + ["samples" (gnuplot-insert "set samples ") t] + ["size" (gnuplot-insert "set size ") t] + ["style" (gnuplot-insert "set style ") t] + ["tics" (gnuplot-insert "set tics ") t] + ["timefmt" (gnuplot-insert "set timefmt ") t] + ["timestamp" (gnuplot-insert "set timestamp ") t] + ["title" (gnuplot-insert "set title ") t] + ["zeroaxis" (gnuplot-insert "set zeroaxis") t] ) + '("adornments" + ["data style" (gnuplot-insert "set data style ") t] + ["function style" (gnuplot-insert "set function style ") t] + ["arrow" (gnuplot-insert "set arrow ") t] + ["bar" (gnuplot-insert "set bar") t] + ["border" (gnuplot-insert "set border") t] + ["boxwidth" (gnuplot-insert "set boxwidth ") t] + ["format" (gnuplot-insert "set format ") t] + ["grid" (gnuplot-insert "set grid") t] + ["key" (gnuplot-insert "set key ") t] + ["label" (gnuplot-insert "set label ") t] + ["pointsize" (gnuplot-insert "set pointsize ") t] + ["samples" (gnuplot-insert "set samples ") t] + ["size" (gnuplot-insert "set size ") t] + ["tics" (gnuplot-insert "set tics ") t] + ["timefmt" (gnuplot-insert "set timefmt ") t] + ["timestamp" (gnuplot-insert "set timestamp ") t] + ["title" (gnuplot-insert "set title ") t] + ["zeroaxis" (gnuplot-insert "set zeroaxis") t] )) + "Adornments submenu in the insertions menu. +See the document string for `gnuplot-insertions-menu' +Changing this will not effect a change in any currently existing +`gnuplot-mode' buffer. You will see the change the next time you +create a `gnuplot-mode' buffer." + :group 'gnuplot-insertions + :type '(list (string :tag "Title") + (repeat :inline t + (vector (string :tag "Name") + (function :tag "Callback") + (boolean :tag "Enabled" t))))) + + + +(defcustom gnuplot-insertions-plot-options + '("plot options" + ["autoscale" (gnuplot-insert "set autoscale ") t] + ["clip" (gnuplot-insert "set clip ") t] + ["encoding" (gnuplot-insert "set encoding ") t] + ["locale" (gnuplot-insert "set locale ") t] + ["logscale" (gnuplot-insert "set logscale ") t] + ["multiplot" (gnuplot-insert "set multiplot") t] + ["missing" (gnuplot-insert "set missing \"\"") t] + ["palette" (gnuplot-insert "set palette ") t] ; + ["pm3d" (gnuplot-insert "set pm3d ") t] + ["offsets" (gnuplot-insert "set offsets ") t] + ["output" (gnuplot-insert "set output ") t] + ["zero" (gnuplot-insert "set zero ") t] ) + "Plot options submenu in the insertions menu. +See the document string for `gnuplot-insertions-menu' +Changing this will not effect a change in any currently existing +`gnuplot-mode' buffer. You will see the change the next time you +create a `gnuplot-mode' buffer." + :group 'gnuplot-insertions + :type '(list (string :tag "Title") + (repeat :inline t + (vector (string :tag "Name") + (function :tag "Callback") + (boolean :tag "Enabled" t))))) + + +(defcustom gnuplot-insertions-terminal + '("terminal" + ["eepic" (gnuplot-insert "set terminal eepic") t] + ["fig" (gnuplot-insert "set terminal fig") t] + ["gpic" (gnuplot-insert "set terminal gpic") t] + ["latex" (gnuplot-insert "set terminal latex") t] + ["linux" (gnuplot-insert "set terminal linux") t] + ["pbm" (gnuplot-insert "set terminal pbm") t] + ["png" (gnuplot-insert "set terminal png") t] + ["postscript" (gnuplot-insert "set terminal postscript") t] + ["pslatex" (gnuplot-insert "set terminal pslatex") t] + ["table" (gnuplot-insert "set terminal table") t] + ["tek40xx" (gnuplot-insert "set terminal tek40xx") t] + ["tkcanvas" (gnuplot-insert "set terminal tkcanvas") t] + ["tpic" (gnuplot-insert "set terminal tpic") t] + ["vgagl" (gnuplot-insert "set terminal vgagl") t] ; for pm3d patch + ["vttek" (gnuplot-insert "set terminal vttek") t] + ["x11" (gnuplot-insert "set terminal x11") t] ) + "Terminal submenu in the insertions menu. +See the document string for `gnuplot-insertions-menu' +Changing this will not effect a change in any currently existing +`gnuplot-mode' buffer. You will see the change the next time you +create a `gnuplot-mode' buffer." + :group 'gnuplot-insertions + :type '(list (string :tag "Title") + (repeat :inline t + (vector (string :tag "Name") + (function :tag "Callback") + (boolean :tag "Enabled" t))))) + + +(defcustom gnuplot-insertions-x-axis + '("x-axis" + ["xdata" (gnuplot-insert "set xdata ") t] + ["xlabel" (gnuplot-insert "set xlabel ") t] + ["xrange" (gnuplot-insert "set xrange [:]") t] + ["xtics" (gnuplot-insert "set xtics ") t] + ["mxtics" (gnuplot-insert "set mxtics ") t] + ["xzeroaxis" (gnuplot-insert "set xzeroaxis ") t] + ["xdtics" (gnuplot-insert "set xdtics ") t] + ["xmtics" (gnuplot-insert "set xmtics ") t]) + "X-axis submenu in the insertions menu. +See the document string for `gnuplot-insertions-menu' +Changing this will not effect a change in any currently existing +`gnuplot-mode' buffer. You will see the change the next time you +create a `gnuplot-mode' buffer." + :group 'gnuplot-insertions + :type '(list (string :tag "Title") + (repeat :inline t + (vector (string :tag "Name") + (function :tag "Callback") + (boolean :tag "Enabled" t))))) + + +(defcustom gnuplot-insertions-x2-axis + '("x2-axis" + ["x2data" (gnuplot-insert "set xdata ") t] + ["x2label" (gnuplot-insert "set xlabel ") t] + ["x2range" (gnuplot-insert "set xrange [:]") t] + ["x2tics" (gnuplot-insert "set xtics ") t] + ["mx2tics" (gnuplot-insert "set mxtics ") t] + ["x2zeroaxis" (gnuplot-insert "set xzeroaxis ") t] + ["x2dtics" (gnuplot-insert "set xdtics ") t] + ["x2mtics" (gnuplot-insert "set xmtics ") t]) + "X2-axis submenu in the insertions menu. +See the document string for `gnuplot-insertions-menu' +Changing this will not effect a change in any currently existing +`gnuplot-mode' buffer. You will see the change the next time you +create a `gnuplot-mode' buffer." + :group 'gnuplot-insertions + :type '(list (string :tag "Title") + (repeat :inline t + (vector (string :tag "Name") + (function :tag "Callback") + (boolean :tag "Enabled" t))))) + + +(defcustom gnuplot-insertions-y-axis + '("y-axis" + ["ydata" (gnuplot-insert "set ydata ") t] + ["ylabel" (gnuplot-insert "set ylabel ") t] + ["ymtics" (gnuplot-insert "set ymtics ") t] + ["yrange" (gnuplot-insert "set yrange [:]") t] + ["ytics" (gnuplot-insert "set ytics ") t] + ["yzeroaxis" (gnuplot-insert "set yzeroaxis ") t] + ["ydtics" (gnuplot-insert "set ydtics ") t] + ["mytics" (gnuplot-insert "set mytics ") t]) + "Y-axis submenu in the insertions menu. +See the document string for `gnuplot-insertions-menu' +Changing this will not effect a change in any currently existing +`gnuplot-mode' buffer. You will see the change the next time you +create a `gnuplot-mode' buffer." + :group 'gnuplot-insertions + :type '(list (string :tag "Title") + (repeat :inline t + (vector (string :tag "Name") + (function :tag "Callback") + (boolean :tag "Enabled" t))))) + +(defcustom gnuplot-insertions-y2-axis + '("y2-axis" + ["y2data" (gnuplot-insert "set ydata ") t] + ["y2label" (gnuplot-insert "set ylabel ") t] + ["y2range" (gnuplot-insert "set yrange [:]") t] + ["y2tics" (gnuplot-insert "set ytics ") t] + ["my2tics" (gnuplot-insert "set mytics ") t] + ["y2zeroaxis" (gnuplot-insert "set yzeroaxis ") t] + ["y2mtics" (gnuplot-insert "set ymtics ") t] + ["y2dtics" (gnuplot-insert "set ydtics ") t]) + "Y2-axis submenu in the insertions menu. +See the document string for `gnuplot-insertions-menu' +Changing this will not effect a change in any currently existing +`gnuplot-mode' buffer. You will see the change the next time you +create a `gnuplot-mode' buffer." + :group 'gnuplot-insertions + :type '(list (string :tag "Title") + (repeat :inline t + (vector (string :tag "Name") + (function :tag "Callback") + (boolean :tag "Enabled" t))))) + + + +(defcustom gnuplot-insertions-z-axis + '("z-axis" + ["zdata" (gnuplot-insert "set zdata ") t] + ["zlabel" (gnuplot-insert "set zlabel ") t] + ["zrange" (gnuplot-insert "set zrange [:]") t] + ["ztics" (gnuplot-insert "set ztics ") t] + ["mztics" (gnuplot-insert "set mztics ") t] + ["zdtics" (gnuplot-insert "set zdtics ") t] + ["zmtics" (gnuplot-insert "set zmtics ") t] ) + "Z-axis submenu in the insertions menu. +See the document string for `gnuplot-insertions-menu' +Changing this will not effect a change in any currently existing +`gnuplot-mode' buffer. You will see the change the next time you +create a `gnuplot-mode' buffer." + :group 'gnuplot-insertions + :type '(list (string :tag "Title") + (repeat :inline t + (vector (string :tag "Name") + (function :tag "Callback") + (boolean :tag "Enabled" t))))) + + +(defcustom gnuplot-insertions-parametric-plots + '("parametric plots" + ["parametric" (gnuplot-insert "set parametric") t] + ["isosamples" (gnuplot-insert "set isosamples ") t] + ["dummy" (gnuplot-insert "set dummy ") t] + ["trange" (gnuplot-insert "set trange [:]") t] + ["urange" (gnuplot-insert "set urange [:]") t] + ["vrange" (gnuplot-insert "set vrange [:]") t] ) + "Parametric plots submenu in the insertions menu. +See the document string for `gnuplot-insertions-menu' +Changing this will not effect a change in any currently existing +`gnuplot-mode' buffer. You will see the change the next time you +create a `gnuplot-mode' buffer." + :group 'gnuplot-insertions + :type '(list (string :tag "Title") + (repeat :inline t + (vector (string :tag "Name") + (function :tag "Callback") + (boolean :tag "Enabled" t))))) + + +(defcustom gnuplot-insertions-polar-plots + '("polar plots" + ["polar" (gnuplot-insert "set polar") t] + ["angles" (gnuplot-insert "set angles ") t] + ["rrange" (gnuplot-insert "set rrange [:]") t] ) + "Polar plots submenu in the insertions menu. +See the document string for `gnuplot-insertions-menu' +Changing this will not effect a change in any currently existing +`gnuplot-mode' buffer. You will see the change the next time you +create a `gnuplot-mode' buffer." + :group 'gnuplot-insertions + :type '(list (string :tag "Title") + (repeat :inline t + (vector (string :tag "Name") + (function :tag "Callback") + (boolean :tag "Enabled" t))))) + + +(defcustom gnuplot-insertions-surface-plots + '("surface plots" + ["clabel" (gnuplot-insert "set clabel ") t] + ["cntrparam" (gnuplot-insert "set cntrparam ") t] + ["contour" (gnuplot-insert "set contour") t] + ["dgrid3d" (gnuplot-insert "set dgrid3d ") t] + ["hidden3d" (gnuplot-insert "set hidden3d ") t] + ["mapping" (gnuplot-insert "set mapping ") t] + ["surface" (gnuplot-insert "set surface ") t] + ["view" (gnuplot-insert "set view ") t] ) + "Surface plots submenu in the insertions menu. +See the document string for `gnuplot-insertions-menu' +Changing this will not effect a change in any currently existing +`gnuplot-mode' buffer. You will see the change the next time you +create a `gnuplot-mode' buffer." + :group 'gnuplot-insertions + :type '(list (string :tag "Title") + (repeat :inline t + (vector (string :tag "Name") + (function :tag "Callback") + (boolean :tag "Enabled" t))))) + + + +(defvar gnuplot-insertions-bottom () + "Bottom part of the insertions menu. +This part contains the toggle buttons for displaying info or +opening an argument-setting popup.") +(setq gnuplot-insertions-bottom + '("---" + ["Display of info with insertion" gnuplot-toggle-info-display + :style toggle :selected gnuplot-insertions-show-help-flag] + ["Display GUI popup with insertion" gnuplot-gui-toggle-popup + :active (fboundp 'gnuplot-gui-toggle-popup) + :style toggle :selected (and (fboundp 'gnuplot-gui-toggle-popup) + gnuplot-gui-popup-flag)] )) + + +;; Regarding a comment by : +;; +;; This is from the header in easymenu.el distributed with XEmacs: +;; +;; ;; - Function: easy-menu-add MENU [ MAP ] +;; ;; Add MENU to the current menubar in MAP. +;; ;; +;; ;; - Function: easy-menu-remove MENU +;; ;; Remove MENU from the current menubar. +;; ;; +;; ;; Emacs 19 never uses `easy-menu-add' or `easy-menu-remove', menus +;; ;; automatically appear and disappear when the keymaps specified by +;; ;; the MAPS argument to `easy-menu-define' are activated. +;; ;; +;; ;; XEmacs will bind the map to button3 in each MAPS, but you must +;; ;; explicitly call `easy-menu-add' and `easy-menu-remove' to add and +;; ;; remove menus from the menu bar. +;; +;; in Emacs, easy-menu-add is defined like this: +;; (defun easy-menu-add (menu &optional map)) + +(defun gnuplot-setup-menubar () + "Initial setup of gnuplot and insertions menus." + (if gnuplot-insertions-menu-flag ; set up insertions menu + (progn + (if gnuplot-xemacs-p + (setq gnuplot-insertions-top + '("insert set expression" "--:doubleLine")) + (setq gnuplot-insertions-top + '("insert set expression" "---"))) + (setq gnuplot-insertions-menu + (append (list "Insertions") + gnuplot-insertions-top + (list gnuplot-insertions-adornments) + (list gnuplot-insertions-plot-options) + (list gnuplot-insertions-terminal) + (list gnuplot-insertions-x-axis) + (list gnuplot-insertions-y-axis) + (list gnuplot-insertions-z-axis) + (list gnuplot-insertions-x2-axis) + (list gnuplot-insertions-y2-axis) + (list gnuplot-insertions-parametric-plots) + (list gnuplot-insertions-polar-plots) + (list gnuplot-insertions-surface-plots) + gnuplot-insertions-bottom)) + (easy-menu-define gnuplot-mode-insertions-menu gnuplot-mode-map + "Insertions menu used in Gnuplot-mode" + gnuplot-insertions-menu) + (easy-menu-add gnuplot-mode-insertions-menu gnuplot-mode-map))) + (easy-menu-define ; set up gnuplot menu + gnuplot-mode-menu gnuplot-mode-map "Menu used in gnuplot-mode" + gnuplot-menu) + (easy-menu-add gnuplot-mode-menu gnuplot-mode-map) ) + +;; There is no `mark-active' variable in XEmacs. Hassle! This is not +;; only replicates mark-active, but it only returns true if the region +;; is of non-zero width. +;; Error checking suggested by +(defun gnuplot-mark-active () + "Return non-nil if the mark is active and it is not equal to point." + (condition-case nil + (and (mark) (/= (mark) (point))) + (error nil))) + + +;;; --- XEmacs toolbar + +(defgroup gnuplot-toolbar nil + "Toolbar used by XEmacs." + :prefix "gnuplot-toolbar-" + :group 'gnuplot) + +(defcustom gnuplot-toolbar-display-flag gnuplot-xemacs-p + "*Non-nil means to display display a toolbar in XEmacs." + :group 'gnuplot-toolbar + :type 'boolean) + +(defcustom gnuplot-toolbar-use-toolbar (if (featurep 'toolbar) 'left-toolbar nil) + "*If nil, do not use a toolbar. +If it is non-nil, it must be a toolbar. The five legal values are +`default-toolbar', `top-toolbar', `bottom-toolbar', `right-toolbar', +and `left-toolbar', although choosing `default-toolbar' or +`top-toolbar' may be a bad idea since either will make the GNUPLOT +toolbar replace the standard toolbar. Changing this will not change +the toolbar in a currently existing buffer, but it will take effect +the next time you use `gnuplot-mode' and emacs. + +This is only used if a toolbar can be displayed, thus this is used in +XEmacs and ignored in FSF Emacs." + :type '(choice (const default-toolbar) + (const top-toolbar) + (const bottom-toolbar) + (const left-toolbar) + (const right-toolbar) + (const :tag "No toolbar" nil)) + :group 'gnuplot-toolbar) + +(defvar gnuplot-toolbar-location "") + +(defun gnuplot-toolbar-setup-toolbar (toolbar) + "Setup function for the `gnuplot-mode' toolbar. +TOOLBAR contains the toolbar specification. +This is basically swiped from VM." + (let ((width 46) (height 46) + (buffer (current-buffer)) + (frame (selected-frame)) + (tag-set '(win))) + (cond + ((eq (symbol-value gnuplot-toolbar-use-toolbar) right-toolbar) + (setq gnuplot-toolbar-location "right") + (set-specifier right-toolbar toolbar buffer) + (set-specifier right-toolbar-width width frame tag-set)) + ((eq (symbol-value gnuplot-toolbar-use-toolbar) left-toolbar) + (setq gnuplot-toolbar-location "left") + (set-specifier left-toolbar toolbar buffer) + (set-specifier left-toolbar-width width frame tag-set)) + ((eq (symbol-value gnuplot-toolbar-use-toolbar) bottom-toolbar) + (setq gnuplot-toolbar-location "bottom") + (set-specifier bottom-toolbar toolbar buffer) + (set-specifier bottom-toolbar-height height frame tag-set)) + ((eq (symbol-value gnuplot-toolbar-use-toolbar) top-toolbar) + (setq gnuplot-toolbar-location "top") + (set-specifier top-toolbar toolbar buffer) + (set-specifier top-toolbar-height height frame tag-set))) )) + +(defvar gnuplot-line-xpm + (if (featurep 'xpm) + (toolbar-make-button-list + "/* XPM */ +static char *line[] = { +/* width height num_colors chars_per_pixel */ +\" 40 40 5 1\", +/* colors */ +\". c #000000\", +\"a c #bebebe s backgroundToolBarColor\", +\"b c #2f4f4f\", +\"c c #ff6347\", +\"d c #0000ff\", +/* pixels */ +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaa..a..aaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaa..aaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaa..a..a....aaa...aaaaaaaaaaaa\", +\"aaaaaaaaaaaa..a..a..a..a..a..aaaaaaaaaaa\", +\"aaaaaaaaaaaa..a..a.aa..a.....aaaaaaaaaaa\", +\"aaaaaaaaaaa..a..a..a..a..aaaaaaaaaaaaaaa\", +\"aaaaaaaaaaa..a..a..a..a..a..aaaaaaaaaaaa\", +\"aaaaaaaaaaa..a..a..a..aa...aaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaadaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaadaaaaaaaaa\", +\"aaaaaaa..aaaaaaaaaaaaaaaaaaaadaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaadaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaacaaaadaadaaaaaaaaaaaa\", +\"aaaaaaaa.caaadaaaccaccadaddaaaaaccaaaaaa\", +\"aaaaaaa..accdaddcaaaaaccaaaaaaccaaaaaaaa\", +\"aaaaaaaa.aadcaccdaaaadaaccaaccaaaaaaaaaa\", +\"aaaaaaaa.adaacaaaddadaaaaaccaaaaaaaaaaaa\", +\"aaaaaaaa.daaaaaaaaadaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaa............................aaaaaa\", +\"aaaaaaaa.aaaa.aaaa.aaaa.aaaa.aaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"};") + "XPM format image used for the \"plot line\" button")) + +(defvar gnuplot-region-xpm + (if (featurep 'xpm) + (toolbar-make-button-list + "/* XPM */ +static char *region[] = { +/* width height num_colors chars_per_pixel */ +\" 40 40 5 1\", +/* colors */ +\". c #000000\", +\"a c #bebebe s backgroundToolBarColor\", +\"b c #2f4f4f\", +\"c c #ff6347\", +\"d c #0000ff\", +/* pixels */ +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaa..aaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaa.a..a...aaa....a..aa...aa....aaaaa\", +\"aaaaaa...a..a..a..a..a..a..a..a..a..aaaa\", +\"aaaaaa..aa.....a.aa..a....aa..a.aa..aaaa\", +\"aaaaa..a...aaaa..aa.a..a..aa....a..aaaaa\", +\"aaaaa..a...a..a..a..a..a..a..a..a..aaaaa\", +\"aaaa..aaaa...aaa....a..aa...aa..a..aaaaa\", +\"aaaaaaaaaaaaaaaaa..aaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaadaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaadaaaaaaaaa\", +\"aaaaaaa..aaaaaaaaaaaaaaaaaaaadaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaadaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaacaaaadaadaaaaaaaaaaaa\", +\"aaaaaaaa.caaadaaaccaccadaddaaaaaccaaaaaa\", +\"aaaaaaa..accdaddcaaaaaccaaaaaaccaaaaaaaa\", +\"aaaaaaaa.aadcaccdaaaadaaccaaccaaaaaaaaaa\", +\"aaaaaaaa.adaacaaaddadaaaaaccaaaaaaaaaaaa\", +\"aaaaaaaa.daaaaaaaaadaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaa............................aaaaaa\", +\"aaaaaaaa.aaaa.aaaa.aaaa.aaaa.aaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"};") + "XPM format image used for the \"plot region\" button")) + +(defvar gnuplot-buffer-xpm + (if (featurep 'xpm) + (toolbar-make-button-list + "/* XPM */ +static char *buffer[] = { +/* width height num_colors chars_per_pixel */ +\" 40 40 5 1\", +/* colors */ +\". c #000000\", +\"a c #bebebe s backgroundToolBarColor\", +\"b c #2f4f4f\", +\"c c #ff6347\", +\"d c #0000ff\", +/* pixels */ +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa..aaaaaaaaaa......aaaaaaaaaaaaaa\", +\"aaaaaaaa..aaaaaaaaa..a..aaaaaaaaaaaaaaaa\", +\"aaaaaaa....aa..a.........a...aa.a.aaaaaa\", +\"aaaaaaa..a..a..a..a..a..a..a..a...aaaaaa\", +\"aaaaaaa.aa....aa..a..a..a.....a..aaaaaaa\", +\"aaaaaa...a.a..a..a..a..a..aaaa..aaaaaaaa\", +\"aaaaaa.....a..a..a..a..a..a..a..aaaaaaaa\", +\"aaaaaa....aaa..a.a..a..aa...aa..aaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaadaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaadaaaaaaaaa\", +\"aaaaaaa..aaaaaaaaaaaaaaaaaaaadaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaadaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaacaaaadaadaaaaaaaaaaaa\", +\"aaaaaaaa.caaadaaaccaccadaddaaaaaccaaaaaa\", +\"aaaaaaa..accdaddcaaaaaccaaaaaaccaaaaaaaa\", +\"aaaaaaaa.aadcaccdaaaadaaccaaccaaaaaaaaaa\", +\"aaaaaaaa.adaacaaaddadaaaaaccaaaaaaaaaaaa\", +\"aaaaaaaa.daaaaaaaaadaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaa............................aaaaaa\", +\"aaaaaaaa.aaaa.aaaa.aaaa.aaaa.aaaaaaaaaaa\", +\"aaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"};") + "XPM format image used for the \"plot buffer\" button")) + +(defvar gnuplot-doc-xpm + (if (featurep 'xpm) + (toolbar-make-button-list + "/* XPM */ +static char *book_index[] = { +/* width height num_colors chars_per_pixel */ +\" 40 40 6 1\", +/* colors */ +\". c #000000\", +\"a c #bebebe s backgroundToolBarColor\", +\"b c #2f4f4f\", +\"c c #ff0000\", +\"d c #ffffff\", +\"e c #708090\", +/* pixels */ +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaa.........bbeaaaebb..........aaaaaa\", +\"aaaaaa.ddddddddaaebebeaaddddddddd.aaaaaa\", +\"aaaa...dab.bddeebadbdaeebedeeeeed...aaaa\", +\"aaaa.c.dbaddddebeedbdeebeedebebed.c.aaaa\", +\"aaaa.c.d.de.edeebeabdbbeeddebbbed.c.aaaa\", +\"aaaa.c.dbad.ddebeadbdeeebeddeeeed.c.aaaa\", +\"aaaa.c.dab..ddeeeedbdebeeedebebed.c.aaaa\", +\"aaaa.c.dddddddeebeabdebebedeebedd.c.aaaa\", +\"aaaa.c.debebedebeedbdbebeedbeeeeb.c.aaaa\", +\"aaaa.c.debeeedeeeaabdaaddddebedbb.c.aaaa\", +\"aaaa.c.deebeddbebedbdbaa.adeeedeb.c.aaaa\", +\"aaaa.c.ddeebedeeebaba.dd.dddeeedd.c.aaaa\", +\"aaaa.c.debeebdbeeedbd....ddeebeed.c.aaaa\", +\"aaaa.c.deebeedeebadbd.dd.ddeeeedd.c.aaaa\", +\"aaaa.c.dbbebddeeeeabd.aa.adebebbd.c.aaaa\", +\"aaaa.c.deeeeedeebeabaedddddeeeedd.c.aaaa\", +\"aaaa.c.dbebbbdebeadbdaeeeedebeeed.c.aaaa\", +\"aaaa.c.deeebddeeebdbdeebeedeebeed.c.aaaa\", +\"aaaa.c.debeeedebeeabdebebedebeebd.c.aaaa\", +\"aaaa.c.deebbedeeeedbdeeeeddeeeeed.c.aaaa\", +\"aaaa.c.dddddddddaadbdaddddddddddd.c.aaaa\", +\"aaaa.c..........beabaeb...........c.aaaa\", +\"aaaa.c.bbbbbbbbbb.bbbbbbbbbbbbbbb.c.aaaa\", +\"aaaa.c.bbbbbbbbbb..e.bbbbbbbbbbbb.c.aaaa\", +\"aaaa.c.bbbbbbbbbb.b.bbbbbbbbbbbbb.c.aaaa\", +\"aaaa.c............e.e.............c.aaaa\", +\"aaaa.cccccccccccc.a.a.ccccccccccccc.aaaa\", +\"aaaa................................aaaa\", +\"aaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"};") + "XPM format image used for the \"document\" button")) + +(defvar gnuplot-help-xpm + (if (featurep 'xpm) + (toolbar-make-button-list + "/* XPM */ +static char *help_btn[] = { +/* width height num_colors chars_per_pixel */ +\" 40 40 3 1\", +/* colors */ +\"a c #bebebe s backgroundToolBarColor\", +\"b c #000000\", +\"c c #ff0000\", +/* pixels */ +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaabbbbbbbbaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaabbbccccccccbbbaaaaaaaaaaaaa\", +\"aaaaaaaaaaabbccccccccccccccbbaaaaaaaaaaa\", +\"aaaaaaaaaabccccccccccccccccccbaaaaaaaaaa\", +\"aaaaaaaaabccccccccccccccccccccbaaaaaaaaa\", +\"aaaaaaaabcccccccbbbbbbbbcccccccbaaaaaaaa\", +\"aaaaaaaabccccbbbaaaaaaaabbbccccbaaaaaaaa\", +\"aaaaaaabccccbaaaaaaaaaaaaaabccccbaaaaaaa\", +\"aaaaaaabcccbaaaaaaaaaaaaaaaabcccbaaaaaaa\", +\"aaaaaaabcccbaaaaaaaaaaaaaaaabcccbaaaaaaa\", +\"aaaaaaabcccbaaaaaaaaaaaaaaaabcccbaaaaaaa\", +\"aaaaaaabbbbbaaaaaaaaaaaaaaabccccbaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaabbbccccbaaaaaaaa\", +\"aaaaaaaaaaaaaaaabbbbbbbbcccccccbaaaaaaaa\", +\"aaaaaaaaaaaaaaaabcccccccccccccbaaaaaaaaa\", +\"aaaaaaaaaaaaaaaabccccccccccccbaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaabccccccccccbbaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaabccccbbbbbbaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaabccccbaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaabccccbaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaabbbbbbaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaabbbbbbaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaabccccbaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaabccccbaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaabccccbaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaabbbbbbaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", +\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"};") + "XPM format image used for the \"help\" button")) + +(defvar gnuplot-toolbar + '([gnuplot-line-xpm + gnuplot-line-fn t "Plot the line under point"] + [gnuplot-region-xpm + gnuplot-region-fn t "Plot the selected region"] + [gnuplot-buffer-xpm + gnuplot-buffer-fn t "Plot the entire buffer"] + [:style 3d :size 8] + [gnuplot-help-xpm + gnuplot-help-fn t "Look at the gnuplot process buffer"] + [gnuplot-doc-xpm + gnuplot-doc-fn t "Look at the gnuplot document"]) + "The gnuplot toolbar.") + +(fset 'gnuplot-line-fn 'gnuplot-send-line-and-forward) +(fset 'gnuplot-region-fn 'gnuplot-send-region-to-gnuplot) +(fset 'gnuplot-buffer-fn 'gnuplot-send-buffer-to-gnuplot) +(fset 'gnuplot-help-fn 'gnuplot-show-gnuplot-buffer) +(fset 'gnuplot-doc-fn 'gnuplot-info-lookup-symbol) + +(defvar gnuplot-all-buttons-defined + (and (listp gnuplot-line-xpm) (listp gnuplot-region-xpm) + (listp gnuplot-buffer-xpm) (listp gnuplot-doc-xpm) + (listp gnuplot-help-xpm))) + + +(defun gnuplot-make-toolbar-function () + (if (and gnuplot-xemacs-p gnuplot-all-buttons-defined) + (progn + ;;(remove-specifier gnuplot-toolbar-use-toolbar (current-buffer)) + (gnuplot-toolbar-setup-toolbar gnuplot-toolbar) + (add-spec-to-specifier (symbol-value gnuplot-toolbar-use-toolbar) + gnuplot-toolbar + (current-buffer) )))) + +;;(defalias 'gnuplot-make-toolbar 'gnuplot-make-toolbar-function) + + + +;;; --- syntax colorization, syntax table + +(defvar gnuplot-mode-syntax-table + (let ((table (make-syntax-table))) + (modify-syntax-entry ?* "." table) + (modify-syntax-entry ?+ "." table) + (modify-syntax-entry ?- "." table) + (modify-syntax-entry ?/ "." table) + (modify-syntax-entry ?% "." table) + (modify-syntax-entry ?= "." table) + (modify-syntax-entry ?: "." table) + (modify-syntax-entry ?& "." table ) ; rarely used + (modify-syntax-entry ?^ "." table ) ; operators + (modify-syntax-entry ?| "." table ) ; in gnuplot, + (modify-syntax-entry ?& "." table ) ; (by me, + (modify-syntax-entry ?? "." table ) ; anyway...) + (modify-syntax-entry ?~ "." table ) ; + + (modify-syntax-entry ?_ "w" table ) + + ;; In GNU Emacs we scan for strings and comments ourselves in + ;; `gnuplot-scan-after-change'. I can't get this to work in xemacs, + ;; so there we'll make ", ', and # delimiters as normal, and use the + ;; built-in parser + (if (featurep 'xemacs) + (progn + (modify-syntax-entry ?\' "\"" table) + (modify-syntax-entry ?# "<" table) + (modify-syntax-entry ?\n ">" table) + (modify-syntax-entry ?\\ "\\" table)) + + ;; GNU Emacs: Make ", ', and # punctuation, so the built-in parser + ;; doesn't interfere with them + (modify-syntax-entry ?\" "." table) + (modify-syntax-entry ?\' "." table) + (modify-syntax-entry ?` "." table) + (modify-syntax-entry ?\\ "." table)) + + table) + + "Syntax table in use in `gnuplot-mode' buffers. +This is the same as the standard syntax table except that ` and _ +are word characters, and math operators are punctuation +characters.") + +;; Macro to generate efficient regexps for keyword matching +;; +;; These regular expressions treat the gnuplot vocabulary as complete +;; words. Although gnuplot will recognise unique abbreviations, these +;; regular expressions will not. +(defmacro gnuplot-make-regexp (list) + `(regexp-opt ,list 'words)) + +;; Lists of gnuplot keywords for syntax coloring etc. +(defvar gnuplot-keywords-builtin-functions + '("abs" "acosh" "acos" "arg" "asinh" "asin" "atan" "atanh" "atan2" "besj1" "besj0" "besy1" "besy0" "ceil" "column" "cosh" "cos" "erfc" "erf" "exp" "floor" "gamma" "ibeta" "igamma" "imag" "int" "inverf" "invnorm" "lgamma" "log" "log10" "norm" "rand" "real" "sgn" "sinh" "sin" "sqrt" "tanh" "tan" "tm_hour" "tm_mday" "tm_min" "tm_mon" "tm_sec" "tm_wday" "tm_yday" "tm_year" "valid") + "List of GNUPLOT built-in functions, as strings. + +These are highlighted using `font-lock-function-name-face'.") + +(defvar gnuplot-keywords-plotting + '("axes" "every" "index" "lw" "lt" "ls" "linestyle" "linetype" "linewidth" "notitle" "pt" "ps" "pointsize" "pointtype" "smooth" "thru" "title" "using" "with") + "List of GNUPLOT keywords associated with plotting, as strings. + +These are highlighted using `font-lock-type-face'. +This list does not include plotting styles -- for that, see +`gnuplot-keywords-plotting-styles'") + +(defvar gnuplot-keywords-plotting-styles + '("boxerrorbars" "boxes" "boxxyerrorbars" "candlesticks" "dots" "errorbars" "financebars" "fsteps" "histeps" "impulses" "lines" "linespoints" "points" "steps" "vector" "xerrorbars" "xyerrorbars" "yerrorbars") + "List of GNUPLOT plotting styles, as strings. + +These are highlighted using `font-lock-function-name-face'.") + +(defvar gnuplot-keywords-misc + '("bind" "cd" "clear" "exit" "fit" "help" "history" "load" "pause" "print" "pwd" "quit" "replot" "save" "set" "show" "unset") + "List of GNUPLOT miscellaneous commands, as strings. + +These are highlighted using `font-lock-reference-face'.") + +(defvar gnuplot-keywords-negatable-options + '("arrow" "autoscale" "border" "clabel" "clip" "contour" "dgrid3d" "grid" "hidden3d" "historysize" "key" "label" "linestyle" "logscale" "mouse" "multiplot" "mx2tics" "mxtics" "my2tics" "mytics" "mztics" "offsets" "polar" "surface" "timestamp" "title" "x2dtics" "x2mtics" "x2tics" "x2zeroaxis" "xdtics" "xmtics" "xtics" "xzeroaxis" "y2dtics" "y2mtics" "y2tics" "y2zeroaxis" "ydtics" "ymtics" "ytics" "yzeroaxis" "zdtics" "zmtics" "ztics" "zzeroaxis") + + "List of gnuplot options which can be negated using `gnuplot-negate-option'") + +(defvar gnuplot-negatable-options-regexp + (gnuplot-make-regexp gnuplot-keywords-negatable-options)) + +;; Set up colorization for gnuplot. +;; This handles font-lock for emacs and xemacs. +;; hilit19 is handled in `gnuplot-mode'. +(defvar gnuplot-font-lock-keywords nil) +(defvar gnuplot-font-lock-syntactic-keywords nil) +(defvar gnuplot-font-lock-defaults nil) + +(when (featurep 'font-lock) ; + (setq gnuplot-font-lock-keywords + (list + ;; stuff in brackets, sugg. by + '("\\[\\([^]]+\\)\\]" 1 font-lock-reference-face) + + ;; variable/function definitions + '("\\(\\(\\sw\\|\\s_\\)+\\s-*\\((\\s-*\\(\\sw\\|\\s_\\)*\\s-*\\(,\\s-*\\sw*\\)*\\s-*)\\)?\\s-*=\\)[^=]" + 1 font-lock-variable-name-face) + + ;; built-in function names + (cons (gnuplot-make-regexp gnuplot-keywords-builtin-functions) + font-lock-function-name-face) + + ;; reserved words associated with plotting + (cons (gnuplot-make-regexp gnuplot-keywords-plotting) + font-lock-type-face) + (cons (gnuplot-make-regexp gnuplot-keywords-plotting-styles) + font-lock-function-name-face) + + ;; (s)plot -- also thing (s)plotted + '("\\" . font-lock-keyword-face) + ;; '("\\ + (gnuplot-beginning-of-continuation) + (setq start (point)) + (end-of-line) + (while (save-excursion + (backward-char) + (looking-at "\\\\")) ; go to end of last continuation line + (end-of-line 2)) + (beginning-of-line 2) + (setq end (point))) + (if (not (string-match "\\`\\s-*\\'" + (buffer-substring-no-properties start end))) + (gnuplot-send-region-to-gnuplot start end 'line)) + end)) + (t + (message "You can only send lines in gnuplot-mode buffers to gnuplot.") + nil))) + +;; I chose a very easy to type but slightly non-mnemonic key-binding +;; for this (C-c C-v). It seems like the kind of thing one would want +;; to do repeatedly without incurring RSI. 8^) +(defun gnuplot-send-line-and-forward (&optional num) + "Call `gnuplot-send-line-to-gnuplot' and move forward 1 line. +You can use a numeric prefix to send more than one line. Blank lines and +lines with only comments are skipped when moving forward." + (interactive "p") + (let (end) + (while (> num 0) + (setq end (gnuplot-send-line-to-gnuplot)) + (goto-char end) + (backward-char 1) ; + (gnuplot-forward-script-line 1) + (setq num (1- num))))) + + +(defun gnuplot-forward-script-line (&optional num) ; + "Move forward my NUM script lines. +Blank lines and commented lines are not included in the NUM count." + (interactive "p") + (while (> num 0) + (and (not (eobp)) (forward-line 1)) + (while (and (not (eobp)) + (or (looking-at "^\\s-*$") + (looking-at "^\\s-*#"))) + (forward-line 1)) + (setq num (1- num)))) + +(defun gnuplot-send-buffer-to-gnuplot () + "Sends the entire buffer to the gnuplot program. +This sets `gnuplot-recently-sent' to 'buffer." + (interactive) + (if (equal major-mode 'gnuplot-mode) + (gnuplot-send-region-to-gnuplot (point-min) (point-max) 'buffer) + (message "You can only send gnuplot-mode buffers to gnuplot."))) + +(defun gnuplot-send-file-to-gnuplot () + "Sends a selected file to the gnuplot program using the \"load\" command. +This sets `gnuplot-recently-sent' to 'file." + (interactive) + (let ((string (read-file-name "Name of file to send to gnuplot > " nil nil t))) + (setq string (concat "load '" (expand-file-name string) "'\n")) + (message "%S" string) + (gnuplot-make-gnuplot-buffer) ; make sure a gnuplot buffer exists + (gnuplot-send-string-to-gnuplot string 'file))) + +;; suggested by +(defun gnuplot-plot-from-comint () + "Send the contents of a script to gnuplot from the process buffer. +This inserts the contents of the most recently used gnuplot script +into the process buffer and sends those lines to gnuplot. It does +this by copying the script line by line." + (interactive) + (if (not (buffer-live-p gnuplot-comint-recent-buffer)) + (message "Script buffer has been deleted.") + (let (string list (buffer (current-buffer))) + (set-buffer gnuplot-comint-recent-buffer) + (setq string (buffer-substring-no-properties (point-min) (point-max)) + string (concat string "\n") + list (gnuplot-split-string string)) + (set-buffer buffer) + (while list + (insert (car list)) + (comint-send-input) + (sleep-for gnuplot-delay) + (setq list (cdr list))) + (comint-send-input)))) + +(defun gnuplot-save-and-plot-from-comint () + "Send a current script to gnuplot from the process buffer. +This sends the most recently used gnuplot script to gnuplot using the +\"load\" command. This function first saves the script buffer to a +file, prompting for a filename if one is not associated with the script +buffer. Then it sends a load command to gnuplot using the name of the +file visited by the script buffer." + (interactive) + (if (not (buffer-live-p gnuplot-comint-recent-buffer)) + (message "Script buffer has been deleted.") + (let (fname) + (with-current-buffer gnuplot-comint-recent-buffer + (save-buffer) + (setq fname (buffer-file-name))) + (goto-char (point-max)) + (insert (format "load '%s'" fname)) + (comint-send-input)))) + +(defun gnuplot-pop-to-recent-buffer () + "Switch to the most recently-plotted gnuplot script buffer." + (interactive) + (when (buffer-live-p gnuplot-comint-recent-buffer) + (pop-to-buffer gnuplot-comint-recent-buffer))) + +(defun gnuplot-trim-gnuplot-buffer () + "Trim lines from the beginning of the *gnuplot* buffer. +This keeps that buffer from growing excessively in size. Normally, +this function is attached to `gnuplot-after-plot-hook'" + (if (> gnuplot-buffer-max-size 0) + (save-excursion + (set-buffer gnuplot-buffer) + (let ((nlines (count-lines (point-min) (point-max))) + (kill-whole-line t)) + (while (> nlines gnuplot-buffer-max-size) + (goto-char (point-min)) + (kill-line) + (setq nlines (1- nlines))) + (goto-char (point-max)) )))) +(add-hook 'gnuplot-after-plot-hook 'gnuplot-trim-gnuplot-buffer nil nil) + + +;;; --- functions controlling the gnuplot process + +;; Define gnuplot-comint-mode, the mode for the gnuplot process +;; buffer, by deriving from comint-mode +(define-derived-mode gnuplot-comint-mode comint-mode "Gnuplot interaction" + "Major mode for interacting with a gnuplot process in a buffer. + +This sets font-lock and keyword completion in the comint/gnuplot +buffer." + + (if gnuplot-xemacs-p ; deal with font-lock + (if (fboundp 'turn-on-font-lock) (turn-on-font-lock)) + (progn + (setq font-lock-defaults gnuplot-font-lock-defaults) + (set (make-local-variable 'parse-sexp-lookup-properties) t) + (add-hook 'after-change-functions 'gnuplot-scan-after-change nil t))) + + ;; XEmacs needs the call to make-local-hook + (when (and (featurep 'xemacs) + (fboundp 'make-local-hook)) + (make-local-hook 'kill-buffer-hook)) + (add-hook 'kill-buffer-hook 'gnuplot-close-down nil t) + + (add-hook 'comint-output-filter-functions + 'comint-postoutput-scroll-to-bottom + nil t) + (add-hook 'comint-output-filter-functions + 'gnuplot-protect-prompt-fn + nil t) + + (add-hook 'comint-dynamic-complete-functions 'gnuplot-comint-complete) + + ;; Set up menu (see below) + (easy-menu-define + gnuplot-comint-mode-menu gnuplot-comint-mode-map "Menu used in gnuplot-comint-mode" + gnuplot-comint-menu) + (easy-menu-add gnuplot-comint-mode-menu gnuplot-comint-mode-map)) + +;; Key bindings for gnuplot-comint-mode +(define-key gnuplot-comint-mode-map "\M-\C-p" 'gnuplot-plot-from-comint) +(define-key gnuplot-comint-mode-map "\M-\C-f" 'gnuplot-save-and-plot-from-comint) +(define-key gnuplot-comint-mode-map "\C-d" 'gnuplot-delchar-or-maybe-eof) +(define-key gnuplot-comint-mode-map "\M-\r" 'comint-dynamic-complete) +(define-key gnuplot-comint-mode-map "\M-\t" 'comint-dynamic-complete) +(define-key gnuplot-comint-mode-map "\C-c\C-d" 'gnuplot-show-version) +(define-key gnuplot-comint-mode-map "\C-c\C-h" 'gnuplot-info-lookup-symbol) +(define-key gnuplot-comint-mode-map "\C-c\C-i" 'gnuplot-insert-filename) +(define-key gnuplot-comint-mode-map "\C-c\C-n" 'gnuplot-negate-option) +(define-key gnuplot-comint-mode-map "\C-c\C-p" 'gnuplot-show-gnuplot-version) +(define-key gnuplot-comint-mode-map "\C-c\C-u" 'gnuplot-bug-report) +(define-key gnuplot-comint-mode-map "\C-c\C-z" 'gnuplot-customize) +(define-key gnuplot-comint-mode-map "\C-c\C-e" 'gnuplot-pop-to-recent-buffer) + +;; Menu for gnuplot-comint-mode +(defvar gnuplot-comint-mode-menu nil + "Menu for `gnuplot-comint-mode'.") +(defvar gnuplot-comint-menu nil) +(setq gnuplot-comint-menu + '("Gnuplot" + ["Plot most recent gnuplot buffer" gnuplot-plot-from-comint + (buffer-live-p gnuplot-comint-recent-buffer)] + ["Save and plot most recent gnuplot buffer" gnuplot-save-and-plot-from-comint + (buffer-live-p gnuplot-comint-recent-buffer)] + "---" + ["Insert filename at point" gnuplot-insert-filename t] + ["Negate set option" gnuplot-negate-option t] + ["Keyword help" gnuplot-info-lookup-symbol + (or gnuplot-keywords gnuplot-keywords-pending)] + ["Switch to recent gnuplot script buffer" gnuplot-pop-to-recent-buffer + (buffer-live-p gnuplot-comint-recent-buffer)] + "---" + ["Customize gnuplot" gnuplot-customize t] + ["Submit bug report" gnuplot-bug-report t] + ["Show gnuplot-mode version" gnuplot-show-version t] + ["Show gnuplot version" gnuplot-show-gnuplot-version t] + "---" + ["Kill gnuplot" gnuplot-kill-gnuplot-buffer t] + )) + +;; Switch to the gnuplot program buffer +(defun gnuplot-make-gnuplot-buffer () + "Switch to the gnuplot program buffer or create one if none exists." + (or (and gnuplot-process (get-process gnuplot-process) + gnuplot-buffer (buffer-name gnuplot-buffer)) + (progn + (message "Starting gnuplot plotting program...") + (setq gnuplot-buffer (make-comint gnuplot-process-name gnuplot-program) + gnuplot-process (get-process gnuplot-process-name)) + (process-kill-without-query gnuplot-process nil) + (with-current-buffer gnuplot-buffer + (gnuplot-comint-mode) + (message "Starting gnuplot plotting program...Done"))))) + +(defun gnuplot-fetch-version-number () + "Determine the installed version of the gnuplot program. + +If `gnuplot-program-version' is already set, does +nothing. Otherwise, runs `gnuplot-program' and searches the text +printed at startup for a string like \"Version N.N\". + +Sets the variables `gnuplot-program-version', +`gnuplot-program-major-version', `gnuplot-program-minor-version', +and `gnuplot-three-eight-p'. + +If the version number cannot be determined by this method, it +defaults to 3.7." + (unless gnuplot-program-version + (message "gnuplot-mode %s -- determining gnuplot version ......" + gnuplot-version) + (with-temp-buffer + (insert "show version") + (call-process-region (point-min) (point-max) + gnuplot-program t (current-buffer)) + (goto-char (point-min)) + (if (and (re-search-forward "[Vv]ersion\\s-+" (point-max) t) + (looking-at "\\([0-9]\\)\\.\\([0-9]+\\)")) + (progn + (setq gnuplot-program-version (match-string 0) + gnuplot-program-major-version (string-to-number + (match-string 1)) + gnuplot-program-minor-version (string-to-number + (match-string 2)) + gnuplot-three-eight-p + (>= (string-to-number gnuplot-program-version) 3.8))) + + ;; Guess v3.7 if something went wrong + (message "Warning: could not determine gnuplot version, guessing 3.7") + (setq gnuplot-program-version "3.7" + gnuplot-program-major-version 3 + gnuplot-program-minor-version 7 + gnuplot-three-eight-p nil))) + + ;; Setup stuff that depends on version number + (gnuplot-setup-menu-and-toolbar))) + +(defun gnuplot-setup-menu-and-toolbar () + ;; set up the menubar (possibly dependent on version number) + (gnuplot-setup-menubar) + ;; set up the toolbar (possibly dependent on version number) + (if (and gnuplot-xemacs-p gnuplot-toolbar-display-flag) + (condition-case () ; deal with the toolbar + (and (require 'toolbar) + (require 'xpm) + (gnuplot-make-toolbar-function)) + (error nil))) + (message "gnuplot-mode %s (gnuplot %s) -- report bugs with %S" + gnuplot-version gnuplot-program-version + (substitute-command-keys "\\[gnuplot-bug-report]"))) + +(defun gnuplot-protect-prompt-fn (string) + "Prevent the Gnuplot prompt from being deleted or overwritten. +STRING is the text as originally inserted in the comint buffer." + (save-excursion + (let ((b (progn + (goto-char (point-max)) + (beginning-of-line) + (point))) + e) + (if (re-search-forward "^gnuplot> " (point-max) t) + (progn + (setq e (point)) + (put-text-property b e 'rear-nonsticky '(read-only intangible face)) + (put-text-property b e 'intangible t) + (put-text-property b e 'face 'gnuplot-prompt-face) + ;;(put-text-property b e 'read-only t) + )) ))) + +(defun gnuplot-close-down () + "Tidy up when deleting the gnuplot buffer." + (if (and gnuplot-process + (eq (process-status gnuplot-process) 'run)) ; + (kill-process gnuplot-process)) + (setq gnuplot-process nil + gnuplot-buffer nil)) + +(defun gnuplot-delchar-or-maybe-eof (arg) + "Delete ARG characters forward, or (if at eob) send an EOF to subprocess. +This is very similar to `comint-delchar-or-maybe-eof'." + (interactive "p") + (if (eobp) + (gnuplot-kill-gnuplot-buffer) + (delete-char arg))) + +(defun gnuplot-kill-gnuplot-buffer () + "Kill the gnuplot process and its display buffers." + (interactive) + (if (and gnuplot-process + (eq (process-status gnuplot-process) 'run)) ;; + (kill-process gnuplot-process)) + (if (and gnuplot-buffer (get-buffer gnuplot-buffer)) + (progn + (if (one-window-p) () + (delete-window (get-buffer-window gnuplot-buffer))) + (kill-buffer gnuplot-buffer))) + (setq gnuplot-process nil + gnuplot-buffer nil)) + + +(defun gnuplot-show-gnuplot-buffer () + "Switch to the buffer containing the gnuplot process. +When `gnuplot-display-process' is nil this will switch to +the gnuplot process buffer. When that variable is non-nil, the +gnuplot process buffer will be displayed in a window." + (interactive) + (unless (and gnuplot-buffer (get-buffer gnuplot-buffer)) + (gnuplot-make-gnuplot-buffer)) + (cond ((equal gnuplot-display-process 'window) + (switch-to-buffer-other-window gnuplot-buffer)) + ((equal gnuplot-display-process 'frame) + (or (and gnuplot-process-frame + (frame-live-p gnuplot-process-frame)) + (setq gnuplot-process-frame (make-frame))) + (raise-frame gnuplot-process-frame) + (select-frame gnuplot-process-frame) + (switch-to-buffer gnuplot-buffer)) + (t + (switch-to-buffer gnuplot-buffer)))) + + +;;; --- miscellaneous functions: insert file name, indentation, negation + +(defun gnuplot-insert-filename () + "Insert a filename at point, prompting for name in the minibuffer. +This inserts a filename relative to the buffer's default directory. +Uses completion and the value of `gnuplot-quote-character'. +Bound to \\[gnuplot-insert-filename]" + (interactive) + (insert gnuplot-quote-character + (file-relative-name (read-file-name "Filename > " "") + default-directory) + gnuplot-quote-character) ) + + +;; Adjust indentation for the line containing point +(defun gnuplot-indent-line () + "Set indentation in gnuplot buffer. +For most lines, set indentation to previous level of indentation. +Add additional indentation for continuation lines." + (interactive) + (let (indent) + (if (gnuplot-in-string (point-at-bol)) + ;; Continued strings begin at left margin + (setq indent 0) + (save-excursion + (if (gnuplot-continuation-line-p) + ;; This is a continuation line. Indent to the same level as + ;; the second word on the line beginning this command (i.e., + ;; the first non-whitespace character after whitespace) + (progn + (gnuplot-beginning-of-continuation) + (back-to-indentation) + (re-search-forward "\\S-+\\s-+" (point-at-eol) 'end-at-limit) + (setq indent (- (point) (point-at-bol)))) + + ;; Not a continuation line; go back to the first non-blank, + ;; non-continuation line and indent to the same level + (beginning-of-line 0) + (while (and (not (bobp)) + (or (gnuplot-continuation-line-p) + (looking-at "\\s-*$"))) + (beginning-of-line 0)) + (if (bobp) + (setq indent 0) + (setq indent (current-indentation)))))) + + ;; Set indentation + (save-excursion + (indent-line-to indent)) + + (let ((point-at-indent (+ (point-at-bol) indent))) + (when (< (point) point-at-indent) (goto-char point-at-indent))))) + +;; +;; Functions for finding the start and end of continuation blocks +;; + +;; Check if line containing point is a continuation +(defun gnuplot-continuation-line-p () + "Return t if the line containing point is a continuation of the previous line." + (save-excursion + (condition-case () + (progn + (end-of-line 0) + (backward-char) + (looking-at "\\\\")) + (error nil)))) + +;; Move point to start of continuation block +(defun gnuplot-beginning-of-continuation () + "Move point to the beginning of the continuation lines containing point. + +If not in a continuation line, move point to beginning of line." + (beginning-of-line) + (while (gnuplot-continuation-line-p) + (beginning-of-line 0))) + +;; Move point to end of continuation block +(defun gnuplot-end-of-continuation () + "Move point to the end of the continuation lines containing point. + +If there are no continuation lines, move point to end-of-line." + (end-of-line) + (unless (bobp) + (catch 'eob + (while (save-excursion (backward-char) + (looking-at "\\\\")) + (end-of-line 2) + (if (eobp) (throw 'eob nil)))))) + +;; Save-excursion wrappers for the above to return point at beginning +;; or end of continuation +(defun gnuplot-point-at-beginning-of-continuation () + "Return value of point at beginning of the continued block containing point. + +If there are no continuation lines, returns point-at-bol." + (save-excursion + (gnuplot-beginning-of-continuation) + (point))) + +(defun gnuplot-point-at-end-of-continuation () + "Return value of point at the end of the continued block containing point. + +If there are no continuation lines, returns point-at-eol." + (save-excursion + (gnuplot-end-of-continuation) + (point))) + +;; We also treat a block of continuation lines as a 'defun' for +;; movement purposes +(defun gnuplot-beginning-of-defun (&optional arg) + (if (not arg) (setq arg 1)) + (if (> arg 0) + (catch 'bob ; go to beginning of ARGth prev. defun + (dotimes (n arg) + (when (= (point) + (gnuplot-point-at-beginning-of-continuation)) + (forward-line -1) + (if (bobp) (throw 'bob t)) + (while (looking-at "^\\s-*$") + (forward-line -1) + (if (bobp) (throw 'bob t)))) + (gnuplot-beginning-of-continuation)) + t) + + (catch 'eob ; find beginning of (-ARG)th following defun + (dotimes (n (- arg)) + (gnuplot-end-of-continuation) + (forward-line) + (if (eobp) (throw 'eob t)) + (while (looking-at "^\\s-*$") + (forward-line) + (if (eobp) (throw 'eob t))))))) + +;; Movement to start or end of command, including multiple commands +;; separated by semicolons +(defun gnuplot-beginning-of-command () + "Move point to beginning of command containing point." + (let ((limit (gnuplot-point-at-beginning-of-continuation))) + (while + (and + (search-backward ";" limit 'lim) + (gnuplot-in-string-or-comment))) + (skip-chars-forward ";") + (skip-syntax-forward "-"))) + +(defun gnuplot-end-of-command () + "Move point to end of command containing point." + (let ((limit (gnuplot-point-at-end-of-continuation))) + (while + (and + (search-forward ";" limit 'lim) + (gnuplot-in-string-or-comment))) + (skip-chars-backward ";") + (skip-syntax-backward "-"))) + +(defun gnuplot-point-at-beginning-of-command () + "Return position at the beginning of command containing point." + (save-excursion (gnuplot-beginning-of-command) (point))) + +(defun gnuplot-point-at-end-of-command () + "Return position at the end of command containing point." + (save-excursion (gnuplot-end-of-command) (point))) + +(defun gnuplot-negate-option () + "Append \"no\" to or remove \"no\" from the set option on the current line. +This checks if the set option is one which has a negated form. + +Negatable options are defined in `gnuplot-keywords-negatable-options'." + (interactive) + (gnuplot-fetch-version-number) + (let ((begin (gnuplot-point-at-beginning-of-command)) + (end (gnuplot-point-at-end-of-command)) + (regex gnuplot-negatable-options-regexp)) + (save-excursion + (goto-char begin) + (skip-syntax-forward "-" end) + (if (looking-at "\\(un\\)?set\\s-+") + (cond ((> (string-to-number gnuplot-program-version) 3.7) + (cond ((looking-at "unset") + (delete-char 2)) + ((looking-at (concat "set\\s-+\\(" regex "\\)")) + (insert "un")) + (t + (message "There is not a negatable set option on this line")))) + (t + (goto-char (match-end 0)) + (if (> (point) end) (goto-char end)) + (cond ((looking-at "no") + (delete-char 2)) + ((looking-at regex) + (insert "no")) + (t + (message "There is not a negatable set option on this line"))))) + (message "There is not a set option on this line")) ))) + +;; (defun gnuplot-set-binding () +;; "Interactively select a key sequence for binding to a plot function. +;; This is only useful in gnuplot 3.8 and for plot terminals which support +;; key bindings (i.e. those covered by pm3d)." +;; (interactive) +;; (let ((keyseq (read-key-sequence "Choose a key sequence now")) +;; (command (read-string "Bind to this command > "))) +;; (setq keyseq (format "%S" keyseq)) +;; (string-match "keypress-event\\s-+" keyseq) +;; (setq keyseq (substring keyseq (match-end 0) -2)) +;; ;; need to convert from emacs nomenclature to gnuplot. what a pain. +;; (let* ((alist '(("backspace" . "Backspace") ("tab" . "Tab") ("linefeed" . "Linefeed") +;; ("clear" . "Clear") ("return" . "Return") ("pause" . "Pause") +;; ("scroll-lock" . "Scroll_Lock") ("SysReq" . "sys-req") +;; ("escape" . "Escape") ("delete" . "Delete") ("home" . "Home") +;; ("left" . "Left") ("right" . "Right") ("up" . "Up") ("down" . "Down") +;; ("prior" . "PageUp") ("next" . "PageDown") ("end" . "End") +;; ("begin". "Begin"))) +;; (match (assoc keyseq alist))) +;; (if match (setq keyseq (cdr match))) +;; +;; (insert (format "bind \"%s\" \"%s\"" keyseq command))))) + + +(defun gnuplot-customize () + "Customize `gnuplot-mode'." + (interactive) + (if (fboundp 'customize-group) + (customize-group "gnuplot") + (message "The Custom library is not installed."))) + + + +;;; --- help from the info file, keyword list + completion, insert function + + +;; set up stuff for info-look (as suggested by ) +;; modified with suggestion from +(defun gnuplot-setup-info-look () + "Setup info-look in the gnuplot buffer. + +Also set the variable `gnuplot-keywords' and do something sensible if +info-look was not available. +See the comments in `gnuplot-info-hook'." + (interactive) + (setq gnuplot-keywords-pending nil) + (if (featurep 'info-look) + (progn + (gnuplot-fetch-version-number) + + ;; In the absence of evidence to the contrary, I'm guessing + ;; the info file layout changed with gnuplot version 4 + (let ((doc-spec + (if (>= (string-to-number gnuplot-program-version) 4.0) + ;; New info-file layout - works with gnuplot 4.4 + '(("(gnuplot)Command_Index" nil "[_a-zA-Z0-9]+") + ("(gnuplot)Options_Index" nil "[_a-zA-Z0-9]+") + ("(gnuplot)Function_Index" nil "[_a-zA-Z0-9]+") + ("(gnuplot)Terminal_Index" nil "[_a-zA-Z0-9]+")) + + ;; Old info-file layout + '(("(gnuplot)Top" nil "[_a-zA-Z0-9]+") + ("(gnuplot)Commands" nil "[_a-zA-Z0-9]+") + ("(gnuplot)Functions" nil "[_a-zA-Z0-9]+") + ("(gnuplot)plot" nil "[_a-zA-Z0-9]+") + ("(gnuplot)set-show" nil "[_a-zA-Z0-9]+") + ("(gnuplot)data-file" nil "[_a-zA-Z0-9]+") + ("(gnuplot)smooth" nil "[_a-zA-Z0-9]+") + ("(gnuplot)style" nil "[_a-zA-Z0-9]+") + ("(gnuplot)terminal" nil "[_a-zA-Z0-9]+"))))) + (cond ((boundp 'info-lookup-symbol-alist) ; older info-lookup version + (setq info-lookup-symbol-alist + (append + info-lookup-symbol-alist + `((gnuplot-mode + "[a-zA-Z][_a-zA-Z0-9]*" nil + ,doc-spec "[_a-zA-Z0-9]+" ))))) + (t ; newer version + (info-lookup-add-help + :mode 'gnuplot-mode :topic 'symbol + :regexp "[a-zA-Z][_a-zA-Z0-9]*" + :doc-spec doc-spec) + ;; allow help lookup from the comint buffer as well + (info-lookup-add-help + :mode 'gnuplot-comint-mode :topic 'symbol + :regexp "[a-zA-Z][_a-zA-Z0-9]*" + :doc-spec doc-spec) + (message "hi dere")))) + + ;; this hook is my best way of working with info-look and + ;; allowing multiple versions of the gnuplot-info file. + ;; yes, this is a hassle. + (run-hooks 'gnuplot-info-hook) + (let ((there (bufferp (get-buffer "*info*")))) + (info-lookup-setup-mode 'symbol 'gnuplot-mode) + (or there (and (get-buffer "*info*") (kill-buffer "*info*"))) + ;; why are these buffers here? I think that the general + ;; user will not want them lying around + (and (get-buffer "info dir") (kill-buffer "info dir")) + (and (get-buffer "info dir<2>") (kill-buffer "info dir<2>"))) + (setq gnuplot-keywords (gnuplot-set-keywords-list)) + (setq gnuplot-keywords-alist ; needed for all-completions + (mapcar 'list gnuplot-keywords))) + + ;; or do something sensible if info-look is not installed + (defun info-lookup-interactive-arguments (symbol) + (message + "Help is not available. info-look.el is not installed.") + (list nil nil)))) + + +(defun gnuplot-set-keywords-list () + "Set `gnuplot-keywords' from `info-lookup-cache'. +Return a list of keywords." + (let* ((list (cdr (assoc 'symbol info-lookup-cache))) + (list (cdr (cdr (assoc 'gnuplot-mode list)))) + (list (car list)) + (store ()) item) + (while list + (setq item (car (car list)) + item (format "%s" item) ; keep this line for the sake of + store (append (list item) store) ; info-look.el w/o my patch + list (cdr list))) + (delete "nil" store) + store )) + +(defun gnuplot-xemacs-completion-at-point () + "Perform completion on keyword preceding point. + +This binds `comint-dynamic-complete-functions' to +`gnuplot-comint-complete' and uses `comint-dynamic-complete' to do the +real work." + ;; This actually would work in GNU Emacs too, but that seems a bit + ;; hackish when completion-at-point exists + (interactive) + (let ((comint-dynamic-complete-functions + '(gnuplot-comint-complete))) + (comint-dynamic-complete))) + +(defun gnuplot-completion-at-point () + "Return completions of keyword preceding point. + +Uses the cache of keywords generated by info-lookup. See +`gnuplot-setup-info-look'. If not nil, the return value is in the form +\(BEGIN END COMPLETIONS) where BEGIN and END are buffer +positions and COMPLETIONS is a list." + + (if gnuplot-keywords-pending ; + (gnuplot-setup-info-look)) + (let* ((end (point)) + (beg (unwind-protect (save-excursion (backward-sexp 1) (point)))) + (patt (buffer-substring beg end)) + (pattern (if (string-match "\\([^ \t]*\\)\\s-+$" patt) + (match-string 1 patt) patt)) + (completions (all-completions pattern gnuplot-keywords-alist))) + (if completions + (list beg end completions) + (message "No gnuplot keywords complete '%s'" pattern) + nil))) + +(defun gnuplot-comint-complete () + "Complete the keyword preceding point in the gnuplot comint buffer. + +Uses the cache of keywords generated by info-lookup and +`comint-dynamic-simple-complete' to handle the actual +completion." + (if gnuplot-keywords-pending ; + (gnuplot-setup-info-look)) + (let ((completions (gnuplot-completion-at-point))) + (if completions + (let* ((beg (nth 0 completions)) + (end (nth 1 completions)) + (candidates (nth 2 completions)) + (completion-base-position (list beg end))) + (comint-dynamic-simple-complete + (buffer-substring-no-properties beg end) + candidates)) + nil))) + +(defun gnuplot-info-lookup-symbol (symbol &optional mode) + "Wrapper for `info-lookup-symbol'. +Takes SYMBOL and MODE as arguments exactly as `info-lookup-symbol'. +After doing the info lookup, this displays the info file in a window +frame as specified by the value of `gnuplot-info-display'. If +`gnuplot-info-display' is 'window, then the window will be shrunk to +the size of the info entry if it is smaller than half the height of +the frame." + (interactive + (cond (gnuplot-keywords + (info-lookup-interactive-arguments 'symbol)) + (gnuplot-keywords-pending ; + (gnuplot-setup-info-look) + (info-lookup-interactive-arguments 'symbol)) + (t + (list nil (message + "Help is not available. The gnuplot info file could not be found."))))) + + (if (and (featurep 'info-look) gnuplot-keywords) + (let ((buff (current-buffer)) + (info-lookup-other-window-flag + (if gnuplot-info-display t nil))) + (if symbol () (setq symbol "Commands")) + (info-lookup-symbol symbol mode) + (cond ((equal gnuplot-info-display 'window) + ;; Adjust window height only if the frame is split + ;; horizontally, so as not to mess up the minibuffer + ;; we can't use shrink-window-if-larger-than-buffer here + ;; because it doesn't work with Info mode's narrowing + (with-selected-window (get-buffer-window "*info*") + (unless (gnuplot-window-full-height-p) + (enlarge-window + (min (- (count-lines (point-min) (point-max)) (window-height) -1) + (- (/ (frame-height) 2) (window-height))))))) + + ((equal gnuplot-info-display 'frame) + (switch-to-buffer buff) + (delete-other-windows) + (or (and gnuplot-info-frame + (frame-live-p gnuplot-info-frame)) + (setq gnuplot-info-frame (make-frame))) + (select-frame gnuplot-info-frame) + (raise-frame gnuplot-info-frame) + (if gnuplot-xemacs-p (setq toolbar-info-frame gnuplot-info-frame)) + (switch-to-buffer "*info*")))))) + +;; XEmacs doesn't have window-full-height-p +(if (featurep 'xemacs) + ;; The below is taken from GNU Emacs window.el + (defun gnuplot-window-full-height-p (&optional window) + (unless window + (setq window (selected-window))) + (= (window-height window) + (window-height (frame-root-window (window-frame window))))) + (defalias 'gnuplot-window-full-height-p 'window-full-height-p)) + +(defun gnuplot-insert (string) + "Insert STRING at point and display help for for STRING. +Help is not shown if `gnuplot-insertions-show-help-flag' is nil. The +help shown is for STRING unless STRING begins with the word \"set\" or +\"show\", in which case help is shown for the thing being set or +shown." + (interactive) + (cond ((and (not gnuplot-three-eight-p) + (string-match "\\(emf\\|p\\(alette\\|m3d\\)\\|vgagl\\)" string)) + (message "%S is an option introduced in gnuplot 3.8 (You are using %s)" + string gnuplot-program-version) ) + (t + (insert string) + (let ((topic string) term) + (if (string-match + "\\(set\\|show\\)[ \t]+\\([^ \t]+\\)\\(\\s-+\\([^ \t]+\\)\\)?" + string) + (progn + (setq topic (downcase (match-string 2 string)) + term (match-string 4 string)) + (if (string= topic "terminal") (setq topic (downcase term))))) + (cond ((and (fboundp 'gnuplot-gui-set-options-and-insert) + gnuplot-gui-popup-flag) + (gnuplot-gui-set-options-and-insert)) + (gnuplot-insertions-show-help-flag + (if gnuplot-keywords-pending ; + (gnuplot-setup-info-look)) + (gnuplot-info-lookup-symbol topic)) ) )) ) ) + +(defun gnuplot-toggle-info-display () + (interactive) + (setq gnuplot-insertions-show-help-flag (not gnuplot-insertions-show-help-flag)) + (message (if gnuplot-insertions-show-help-flag + "Help will be displayed after insertions." + "Help no longer displayed after insertions."))) + + +;;; --- bug reports +;; grep '(defcustom' gnuplot.el gnuplot-gui.el | awk '{print $2}' +(defun gnuplot-bug-report () + "Submit a bug report about `gnuplot-mode' by email. +Please do not send any bug reports about gnuplot itself to the +maintainer of `gnuplot-mode'." + (interactive) + (let ((line (make-string 62 ?-))) + (require 'reporter) + (and (y-or-n-p + "Do you really want to submit an email report about gnuplot? ") + (y-or-n-p + (concat "Variable values will be written to the message. " + "Don't erase them. OK? ")) + (reporter-submit-bug-report + (format "%s <%s>" gnuplot-maintainer gnuplot-maintainer-email) + (format "gnuplot-mode (version %s)" gnuplot-version) + (append ; variables to display values of in mail + '(gnuplot-mode-hook + gnuplot-load-hook + gnuplot-after-plot-hook + gnuplot-info-hook + gnuplot-comint-setup-hook + gnuplot-program + gnuplot-program-version + gnuplot-process-name + gnuplot-gnuplot-buffer + gnuplot-display-process + gnuplot-info-display + gnuplot-echo-command-line-flag + gnuplot-insertions-show-help-flag + gnuplot-delay + gnuplot-quote-character + gnuplot-keywords-when + ;;gnuplot-insertions-menu-flag + ;;gnuplot-insertions-adornments + ;;gnuplot-insertions-plot-options + ;;gnuplot-insertions-terminal + ;;gnuplot-insertions-x-axis + ;;gnuplot-insertions-x2-axis + ;;gnuplot-insertions-y-axis + ;;gnuplot-insertions-y2-axis + ;;gnuplot-insertions-z-axis + ;;gnuplot-insertions-parametric-plots + ;;gnuplot-insertions-polar-plots + ;;gnuplot-insertions-surface-plots + gnuplot-toolbar-display-flag + gnuplot-toolbar-use-toolbar + gnuplot-gui-popup-flag + gnuplot-gui-frame-plist + gnuplot-gui-frame-parameters + gnuplot-gui-fontname-list + gnuplot-gui-plot-splot-fit-style + ;; plus a few more... + gnuplot-comint-recent-buffer + gnuplot-version + Info-directory-list + exec-path + features )) + nil ; pre-hooks + nil ; post-hooks + (concat line ; salutation + "\nInsert your description of the gnuplot-mode bug here.\n" + "Please be as specific as possible.\n\n" + "There are several known shortcomings of gnuplot-mode.\n" + "Many of these have to do with the complicated and inconsistent\n" + "syntax of gnuplot itself. See the document string for the\n" + "function `gnuplot-mode' (use `" + (substitute-command-keys "\\[describe-function]") + "') for details.\n\n" + "Note that this bug report form should be used for problems\n" + "with gnuplot-mode only. Problems with gnuplot itself should\n" + "be addressed directly to the developers of gnuplot.\n" + "The maintainer of gnuplot-mode will not field questions about\n" + "gnuplot itself. Thank you.\n" + line) + )))) + + + +;;; --- autoloaded functions: gnuplot-mode and gnuplot-make-buffer + +;;;###autoload +(defun gnuplot-mode () + "Major mode for editing and executing GNUPLOT scripts. +This was written with version 3.7 of gnuplot in mind but it should +work fine with version 3.5 and the various 3.6 beta versions. + +Report bugs in `gnuplot-mode' using \\[gnuplot-bug-report]. + + ------O------ + +The help functions, keyword completion, and several other features +depend upon having the info file properly installed. The info file +can be made in the document directory of the gnuplot distribution or +is available at the `gnuplot-mode' web page: + http://github.com/bruceravel/gnuplot-mode/ + +If the help function does not work properly, you may have an older +version of the gnuplot info file. Try the suggestion in the document +string for the variable `gnuplot-info-hook'. See the `gnuplot-mode' +web page for more details. + + ------O------ + +There are several known shortcomings of `gnuplot-mode', version 0.5g +and up. Many of the shortcomings involve the graphical interface +\(refered to as the GUI) to setting arguments to plot options. Here is +a list: + + 1. Currently there is no way for `gnuplot-mode' to know if information + sent to gnuplot was correctly plotted. + 2. Indentation is sometimes a bit flaky. + 3. \"plot\", \"splot\", and \"fit\" are handled in the GUI, but are + a bit flaky. Their arguments may not be read correctly from + existing text, and continuation lines (common for plot and splot) + are not supported. + 4. The GUI does not know how to read from continuation lines. + 5. Comma separated position arguments to plot options are + unsupported in the GUI. Colon separated datafile modifiers (used + for plot, splot, and fit) are not supported either. Arguments + not yet supported by the GUI generate messages printed in grey + text. + 6. The GUI handling of \"hidden3d\" is flaky and \"cntrparam\" is + unsupported. + + ------O------ + + Key bindings: + \\{gnuplot-mode-map}" + (interactive) + (kill-all-local-variables) + (use-local-map gnuplot-mode-map) + (setq major-mode 'gnuplot-mode + mode-name "Gnuplot") + (set (make-local-variable 'comment-start) "# ") + (set (make-local-variable 'comment-end) "") + (set (make-local-variable 'comment-column) 32) + (set (make-local-variable 'comment-start-skip) "#[ \t]*") + (set (make-local-variable 'indent-line-function) 'gnuplot-indent-line) + + (set (make-local-variable 'beginning-of-defun-function) 'gnuplot-beginning-of-defun) + (set (make-local-variable 'end-of-defun-function) 'gnuplot-end-of-continuation) + + (unless (featurep 'xemacs) + (add-hook 'completion-at-point-functions 'gnuplot-completion-at-point nil t)) + + (set-syntax-table gnuplot-mode-syntax-table) + + (if (or (fboundp 'hilit-set-mode-patterns) + (equal gnuplot-keywords-when 'immediately)) ; + (gnuplot-setup-info-look)) ;; + + (if (fboundp 'hilit-set-mode-patterns) ; deal with hilit19 (ho hum!) + (let ((keywords (concat "\\b\\(" (mapconcat 'identity + gnuplot-keywords "\\|") + "\\)\\b"))) + (hilit-set-mode-patterns + 'gnuplot-mode + `(("#.*$" nil comment) + ("\\([a-zA-Z0-9_-]+\\)\\(([^)]*)\\)?\\s *=" nil define) + ,(list keywords 'nil 'keyword) + (hilit-string-find ?\\ string))))) + + (if gnuplot-xemacs-p ; deal with font-lock + (when (fboundp 'turn-on-font-lock) + (turn-on-font-lock)) + (progn + (gnuplot-scan-after-change (point-min) (point-max)) + (add-hook 'after-change-functions 'gnuplot-scan-after-change nil t) + (setq font-lock-defaults gnuplot-font-lock-defaults) + (set (make-local-variable 'font-lock-multiline) t) + (set (make-local-variable 'parse-sexp-lookup-properties) t))) + + + (if (fboundp 'widget-create) ; gnuplot-gui + (condition-case () + (require 'gnuplot-gui) + (error nil))) + (setq gnuplot-first-call nil ; a few more details ... + gnuplot-comint-recent-buffer (current-buffer) + comint-process-echoes gnuplot-echo-command-line-flag) + (run-hooks 'gnuplot-mode-hook) + ;; the first time we need to figure out which gnuplot we are running + (if gnuplot-program-version + (gnuplot-setup-menu-and-toolbar) + (gnuplot-fetch-version-number))) + +;;;###autoload +(defun gnuplot-make-buffer () + "Open a new buffer in `gnuplot-mode'. +When invoked, it switches to a new, empty buffer visiting no file +and then starts `gnuplot-mode'. + +It is convenient to bind this function to a global key sequence. For +example, to make the F10 key open a gnuplot script buffer, put the +following in your .emacs file: + (autoload 'gnuplot-make-buffer \"gnuplot\" + \"open a buffer in gnuplot mode\" t) + (global-set-key [(f10)] 'gnuplot-make-buffer)" + (interactive) + (switch-to-buffer gnuplot-gnuplot-buffer) + (gnuplot-mode)) + +(defun gnuplot-show-version () + "Show version number in echo area" + (interactive) + (message "gnuplot-mode %s -- URL: %s" gnuplot-version gnuplot-maintainer-url)) + +(defun gnuplot-show-gnuplot-version () + "Show gnuplot program and version number in echo area" + (interactive) + (gnuplot-fetch-version-number) + (message "You are calling gnuplot %s as %s" gnuplot-program-version gnuplot-program)) + + +;;; That's it! ---------------------------------------------------------------- + + +;;; --- final chores: provide 'gnuplot and run load-hook +;; provide before run-hooks suggested by +(provide 'gnuplot) +(run-hooks 'gnuplot-load-hook) + +;;;============================================================================ +;;; + +;;; gnuplot.el ends here diff --git a/gnuplot/info-look.20.2.el b/gnuplot/info-look.20.2.el new file mode 100644 index 0000000..c13b679 --- /dev/null +++ b/gnuplot/info-look.20.2.el @@ -0,0 +1,527 @@ +;;; info-look.el --- major-mode-sensitive Info index lookup facility. +;; An older version of this was known as libc.el. + +;; Copyright (C) 1995, 1996, 1997 Ralph Schleicher. + +;; Author: Ralph Schleicher +;; Keywords: help languages + +;; This file is not part of GNU Emacs. (but is slightly modified from +;; a file that is a part of GNU Emacs -- see below) + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;; Bruce Ravel made two chanegs to this +;; file: +;; 1. Added a check for XEmacs +;; 2. Added (format "%s" (match-string 1)) in function +;; `info-lookup-make-completions' so that text properties are not +;; grabbed. + +;;; Code: + +(require 'info) +;; next two lines added by Bruce Ravel to +;; make this file compile properly under XEmacs. +(eval-and-compile + (if (string-match "XEmacs" emacs-version) + (require 'overlay))) + +(defvar info-lookup-mode nil + "*Symbol of the current buffer's help mode. +Provide help according to the buffer's major mode if value is nil. +Automatically becomes buffer local when set in any fashion.") +(make-variable-buffer-local 'info-lookup-mode) + +(defvar info-lookup-other-window-flag t + "*Non-nil means pop up the Info buffer in another window.") + +(defvar info-lookup-highlight-face 'highlight + "*Face for highlighting looked up help items. +Setting this variable to nil disables highlighting.") + +(defvar info-lookup-highlight-overlay nil + "Overlay object used for highlighting.") + +(defvar info-lookup-history nil + "History of previous input lines.") + +(defvar info-lookup-alist '((symbol . info-lookup-symbol-alist) + (file . info-lookup-file-alist)) + "*Alist of known help topics. +Cons cells are of the form + + (HELP-TOPIC . VARIABLE) + +HELP-TOPIC is the symbol of a help topic. +VARIABLE is a variable storing HELP-TOPIC's public data. + Value is an alist with elements of the form + + (HELP-MODE REGEXP IGNORE-CASE DOC-SPEC PARSE-RULE OTHER-MODES) + +HELP-MODE is a mode's symbol. +REGEXP is a regular expression matching those help items whose + documentation can be looked up via DOC-SPEC. +IGNORE-CASE is non-nil if help items are case insensitive. +DOC-SPEC is a list of documentation specifications of the form + + (INFO-NODE TRANS-FUNC PREFIX SUFFIX) + +INFO-NODE is the name (including file name part) of an Info index. +TRANS-FUNC is a function translating index entries into help items; + nil means add only those index entries matching REGEXP, a string + means prepend string to the first word of all index entries. +PREFIX and SUFFIX are parts of a regular expression. If one of + them is non-nil then search the help item's Info node for the + first occurrence of the regular expression `PREFIX ITEM SUFFIX'. + ITEM will be highlighted with `info-lookup-highlight-face' if this + variable is not nil. +PARSE-RULE is either the symbol name of a function or a regular + expression for guessing the default help item at point. Fuzzy + regular expressions like \"[_a-zA-Z0-9]+\" do a better job if + there are no clear delimiters; do not try to write too complex + expressions. PARSE-RULE defaults to REGEXP. +OTHER-MODES is a list of cross references to other help modes.") + +(defsubst info-lookup->topic-value (topic) + (symbol-value (cdr (assoc topic info-lookup-alist)))) + +(defsubst info-lookup->mode-value (topic mode) + (assoc mode (info-lookup->topic-value topic))) + +(defsubst info-lookup->regexp (topic mode) + (nth 1 (info-lookup->mode-value topic mode))) + +(defsubst info-lookup->ignore-case (topic mode) + (nth 2 (info-lookup->mode-value topic mode))) + +(defsubst info-lookup->doc-spec (topic mode) + (nth 3 (info-lookup->mode-value topic mode))) + +(defsubst info-lookup->parse-rule (topic mode) + (nth 4 (info-lookup->mode-value topic mode))) + +(defsubst info-lookup->other-modes (topic mode) + (nth 5 (info-lookup->mode-value topic mode))) + +(defvar info-lookup-cache nil + "Cache storing data maintained automatically by the program. +Value is an alist with cons cell of the form + + (HELP-TOPIC . ((HELP-MODE INITIALIZED COMPLETIONS REFER-MODES) ...)) + +HELP-TOPIC is the symbol of a help topic. +HELP-MODE is a mode's symbol. +INITIALIZED is nil if HELP-MODE is uninitialized, t if + HELP-MODE is initialized, and `0' means HELP-MODE is + initialized but void. +COMPLETIONS is an alist of documented help items. +REFER-MODES is a list of other help modes to use.") + +(defsubst info-lookup->cache (topic) + (or (assoc topic info-lookup-cache) + (car (setq info-lookup-cache + (cons (cons topic nil) + info-lookup-cache))))) + +(defsubst info-lookup->topic-cache (topic) + (cdr (info-lookup->cache topic))) + +(defsubst info-lookup->mode-cache (topic mode) + (assoc mode (info-lookup->topic-cache topic))) + +(defsubst info-lookup->initialized (topic mode) + (nth 1 (info-lookup->mode-cache topic mode))) + +(defsubst info-lookup->completions (topic mode) + (or (info-lookup->initialized topic mode) + (info-lookup-setup-mode topic mode)) + (nth 2 (info-lookup->mode-cache topic mode))) + +(defsubst info-lookup->refer-modes (topic mode) + (or (info-lookup->initialized topic mode) + (info-lookup-setup-mode topic mode)) + (nth 3 (info-lookup->mode-cache topic mode))) + +(defsubst info-lookup->all-modes (topic mode) + (cons mode (info-lookup->refer-modes topic mode))) + +(defvar info-lookup-symbol-alist + '((autoconf-mode + "A[CM]_[_A-Z0-9]+" nil + (("(autoconf)Macro Index" "AC_" + "^[ \t]+- \\(Macro\\|Variable\\): .*\\<" "\\>") + ("(automake)Index" nil + "^[ \t]*`" "'")) + ;; Autoconf symbols are M4 macros. Thus use M4's parser. + ignore + (m4-mode)) + (bison-mode + "[:;|]\\|%\\([%{}]\\|[_a-z]+\\)\\|YY[_A-Z]+\\|yy[_a-z]+" nil + (("(bison)Index" nil + "`" "'")) + "[:;|]\\|%\\([%{}]\\|[_a-zA-Z][_a-zA-Z0-9]*\\)" + (c-mode)) + (c-mode + "\\(struct \\|union \\|enum \\)?[_a-zA-Z][_a-zA-Z0-9]*" nil + (("(libc)Function Index" nil + "^[ \t]+- \\(Function\\|Macro\\): .*\\<" "\\>") + ("(libc)Variable Index" nil + "^[ \t]+- \\(Variable\\|Macro\\): .*\\<" "\\>") + ("(libc)Type Index" nil + "^[ \t]+- Data Type: \\<" "\\>") + ("(termcap)Var Index" nil + "^[ \t]*`" "'")) + info-lookup-guess-c-symbol) + (m4-mode + "[_a-zA-Z][_a-zA-Z0-9]*" nil + (("(m4)Macro index")) + "[_a-zA-Z0-9]+") + (makefile-mode + "\\$[^({]\\|\\.[_A-Z]*\\|[_a-zA-Z][_a-zA-Z0-9-]*" nil + (("(make)Name Index" nil + "^[ \t]*`" "'")) + "\\$[^({]\\|\\.[_A-Z]*\\|[_a-zA-Z0-9-]+") + (texinfo-mode + "@\\([a-zA-Z]+\\|[^a-zA-Z]\\)" nil + (("(texinfo)Command and Variable Index" + ;; Ignore Emacs commands and prepend a `@'. + (lambda (item) + (if (string-match "^\\([a-zA-Z]+\\|[^a-zA-Z]\\)\\( .*\\)?$" item) + (concat "@" (match-string 1 item)))) + "`" "'")))) + "*Alist of help specifications for symbol names. +See the documentation of the variable `info-lookup-alist' for more details.") + +(defvar info-lookup-file-alist + '((c-mode + "[_a-zA-Z0-9./+-]+" nil + (("(libc)File Index")))) + "*Alist of help specifications for file names. +See the documentation of the variable `info-lookup-alist' for more details.") + +;;;###autoload +(defun info-lookup-reset () + "Throw away all cached data. +This command is useful if the user wants to start at the beginning without +quitting Emacs, for example, after some Info documents were updated on the +system." + (interactive) + (setq info-lookup-cache nil)) + +;;;###autoload +(defun info-lookup-symbol (symbol &optional mode) + "Display the documentation of a symbol. +If called interactively, SYMBOL will be read from the mini-buffer. +Prefix argument means unconditionally insert the default symbol name +into the mini-buffer so that it can be edited. +The default symbol is the one found at point." + (interactive + (info-lookup-interactive-arguments 'symbol)) + (info-lookup 'symbol symbol mode)) + +;;;###autoload +(defun info-lookup-file (file &optional mode) + "Display the documentation of a file. +If called interactively, FILE will be read from the mini-buffer. +Prefix argument means unconditionally insert the default file name +into the mini-buffer so that it can be edited. +The default file name is the one found at point." + (interactive + (info-lookup-interactive-arguments 'file)) + (info-lookup 'file file mode)) + +(defun info-lookup-interactive-arguments (topic) + "Return default value and help mode for help topic TOPIC." + (let* ((mode (if (info-lookup->mode-value + topic (or info-lookup-mode major-mode)) + (or info-lookup-mode major-mode) + (info-lookup-change-mode topic))) + (completions (info-lookup->completions topic mode)) + (default (info-lookup-guess-default topic mode)) + (input (if (or current-prefix-arg (not (assoc default completions))) + default)) + (completion-ignore-case (info-lookup->ignore-case topic mode)) + (enable-recursive-minibuffers t) + (value (completing-read + (if (and default (not input)) + (format "Describe %s (default %s): " topic default) + (format "Describe %s: " topic)) + completions nil nil input 'info-lookup-history))) + (list (if (equal value "") default value) mode))) + +(defun info-lookup-change-mode (topic) + (let* ((completions (mapcar (lambda (arg) + (cons (symbol-name (car arg)) (car arg))) + (info-lookup->topic-value topic))) + (mode (completing-read + (format "Use %s help mode: " topic) + completions nil t nil 'info-lookup-history))) + (or (setq mode (cdr (assoc mode completions))) + (error "No %s help available" topic)) + (or (info-lookup->mode-value topic mode) + (error "No %s help available for `%s'" topic mode)) + (setq info-lookup-mode mode))) + +(defun info-lookup (topic item mode) + "Display the documentation of a help item." + (if (not mode) + (setq mode (or info-lookup-mode major-mode))) + (or (info-lookup->mode-value topic mode) + (error "No %s help available for `%s'" topic mode)) + (let ((entry (or (assoc (if (info-lookup->ignore-case topic mode) + (downcase item) item) + (info-lookup->completions topic mode)) + (error "Not documented as a %s: %s" topic (or item "")))) + (modes (info-lookup->all-modes topic mode)) + (window (selected-window)) + found doc-spec node prefix suffix) + (if (not info-lookup-other-window-flag) + (info) + (save-window-excursion (info)) + (switch-to-buffer-other-window "*info*")) + (while (and (not found) modes) + (setq doc-spec (info-lookup->doc-spec topic (car modes))) + (while (and (not found) doc-spec) + (setq node (nth 0 (car doc-spec)) + prefix (nth 2 (car doc-spec)) + suffix (nth 3 (car doc-spec))) + (condition-case nil + (progn + (Info-goto-node node) + (Info-menu (or (cdr entry) item)) + (setq found t) + (if (or prefix suffix) + (let ((case-fold-search + (info-lookup->ignore-case topic (car modes))) + (buffer-read-only nil)) + (goto-char (point-min)) + (re-search-forward + (concat prefix (regexp-quote item) suffix)) + (goto-char (match-beginning 0)) + (and window-system info-lookup-highlight-face + ;; Search again for ITEM so that the first + ;; occurence of ITEM will be highlighted. + (re-search-forward (regexp-quote item)) + (let ((start (match-beginning 0)) + (end (match-end 0))) + (if (overlayp info-lookup-highlight-overlay) + (move-overlay info-lookup-highlight-overlay + start end (current-buffer)) + (setq info-lookup-highlight-overlay + (make-overlay start end)))) + (overlay-put info-lookup-highlight-overlay + 'face info-lookup-highlight-face))))) + (error nil)) + (setq doc-spec (cdr doc-spec))) + (setq modes (cdr modes))) + ;; Don't leave the Info buffer if the help item couldn't be looked up. + (if (and info-lookup-other-window-flag found) + (select-window window)))) + +(defun info-lookup-setup-mode (topic mode) + "Initialize the internal data structure." + (or (info-lookup->initialized topic mode) + (let (cell data (initialized 0) completions refer-modes) + (if (not (info-lookup->mode-value topic mode)) + (message "No %s help available for `%s'" topic mode) + ;; Recursively setup cross references. + ;; But refer only to non-void modes. + (mapcar (lambda (arg) + (or (info-lookup->initialized topic arg) + (info-lookup-setup-mode topic arg)) + (and (eq (info-lookup->initialized topic arg) t) + (setq refer-modes (cons arg refer-modes)))) + (info-lookup->other-modes topic mode)) + (setq refer-modes (nreverse refer-modes)) + ;; Build the full completion alist. + (setq completions + (nconc (info-lookup-make-completions topic mode) + (apply 'append + (mapcar (lambda (arg) + (info-lookup->completions topic arg)) + refer-modes)))) + (setq initialized t)) + ;; Update `info-lookup-cache'. + (setq cell (info-lookup->mode-cache topic mode) + data (list initialized completions refer-modes)) + (if (not cell) + (setcdr (info-lookup->cache topic) + (cons (cons mode data) (info-lookup->topic-cache topic))) + (setcdr cell data)) + initialized))) + +(defun info-lookup-make-completions (topic mode) + "Create a unique alist from all index entries." + (condition-case nil + (let ((doc-spec (info-lookup->doc-spec topic mode)) + (regexp (concat "^\\(" (info-lookup->regexp topic mode) + "\\)\\([ \t].*\\)?$")) + node trans entry item prefix result) + (save-window-excursion + (info) + (while doc-spec + (setq node (nth 0 (car doc-spec)) + trans (cond ((eq (nth 1 (car doc-spec)) nil) + (lambda (arg) + (if (string-match regexp arg) + (match-string 1 arg)))) + ((stringp (nth 1 (car doc-spec))) + (setq prefix (nth 1 (car doc-spec))) + (lambda (arg) + (if (string-match "^\\([^: \t\n]+\\)" arg) + (concat prefix (match-string 1 arg))))) + (t (nth 1 (car doc-spec))))) + (message "Processing Info node \"%s\"..." node) + (Info-goto-node node) + (goto-char (point-min)) + (and (search-forward "\n* Menu:" nil t) + (while (re-search-forward "\n\\* \\([^:\t\n]*\\):" nil t) + ;; Bruce Ravel added format + ;; w/o format, this grabs text properties + (setq entry (format "%s" (match-string 1)) + item (funcall trans entry)) + (and (info-lookup->ignore-case topic mode) + (setq item (downcase item))) + (and (string-equal entry item) + (setq entry nil)) + (or (assoc item result) + (setq result (cons (cons item entry) result))))) + (message "Processing Info node \"%s\"... done" node) + (setq doc-spec (cdr doc-spec))) + (Info-directory)) + result) + (error nil))) + +(defun info-lookup-guess-default (topic mode) + "Pick up default item at point (with favor to look back). +Return nil if there is nothing appropriate." + (let ((modes (info-lookup->all-modes topic mode)) + (start (point)) guess whitespace) + (while (and (not guess) modes) + (setq guess (info-lookup-guess-default* topic (car modes)) + modes (cdr modes)) + (goto-char start)) + ;; Collapse whitespace characters. + (and guess (concat (delete nil (mapcar (lambda (ch) + (if (or (char-equal ch ? ) + (char-equal ch ?\t) + (char-equal ch ?\n)) + (if (not whitespace) + (setq whitespace ? )) + (setq whitespace nil) ch)) + guess)))))) + +(defun info-lookup-guess-default* (topic mode) + (let ((case-fold-search (info-lookup->ignore-case topic mode)) + (rule (or (info-lookup->parse-rule topic mode) + (info-lookup->regexp topic mode))) + (start (point)) end regexp subexp result) + (if (symbolp rule) + (setq result (funcall rule)) + (if (consp rule) + (setq regexp (car rule) + subexp (cdr rule)) + (setq regexp rule + subexp 0)) + (skip-chars-backward " \t\n") (setq end (point)) + (while (and (re-search-backward regexp nil t) + (looking-at regexp) + (>= (match-end 0) end)) + (setq result (match-string subexp))) + (if (not result) + (progn + (goto-char start) + (skip-chars-forward " \t\n") + (and (looking-at regexp) + (setq result (match-string subexp)))))) + result)) + +(defun info-lookup-guess-c-symbol () + "Get the C symbol at point." + (condition-case nil + (progn + (backward-sexp) + (let ((start (point)) prefix name) + ;; Test for a leading `struct', `union', or `enum' keyword + ;; but ignore names like `foo_struct'. + (setq prefix (and (< (skip-chars-backward " \t\n") 0) + (< (skip-chars-backward "_a-zA-Z0-9") 0) + (looking-at "\\(struct\\|union\\|enum\\)\\s ") + (concat (match-string 1) " "))) + (goto-char start) + (and (looking-at "[_a-zA-Z][_a-zA-Z0-9]*") + (setq name (match-string 0))) + ;; Caveat! Look forward if point is at `struct' etc. + (and (not prefix) + (or (string-equal name "struct") + (string-equal name "union") + (string-equal name "enum")) + (looking-at "[a-z]+\\s +\\([_a-zA-Z][_a-zA-Z0-9]*\\)") + (setq prefix (concat name " ") + name (match-string 1))) + (and (or prefix name) + (concat prefix name)))) + (error nil))) + +;;;###autoload +(defun info-complete-symbol (&optional mode) + "Perform completion on symbol preceding point." + (interactive) + (info-complete 'symbol + (or mode + (if (info-lookup->mode-value + 'symbol (or info-lookup-mode major-mode)) + (or info-lookup-mode major-mode) + (info-lookup-change-mode 'symbol))))) + +;;;###autoload +(defun info-complete-file (&optional mode) + "Perform completion on file preceding point." + (interactive + (list (if (info-lookup->mode-value + 'file (or info-lookup-mode major-mode)) + (or info-lookup-mode major-mode) + (info-lookup-change-mode 'file)))) + (info-complete 'file mode)) + +(defun info-complete (topic mode) + "Try to complete a help item." + (barf-if-buffer-read-only) + (if (not mode) + (setq mode (or info-lookup-mode major-mode))) + (or (info-lookup->mode-value topic mode) + (error "No %s completion available for `%s'" topic mode)) + (let ((modes (info-lookup->all-modes topic mode)) + (start (point)) try completion) + (while (and (not try) modes) + (setq mode (car modes) + modes (cdr modes) + try (info-lookup-guess-default* topic mode)) + (goto-char start)) + (and (not try) + (error "Found no %s to complete" topic)) + (setq completion (try-completion + try (info-lookup->completions topic mode))) + (cond ((not completion) + (ding)) + ((stringp completion) + (delete-region (- start (length try)) start) + (insert completion))))) + +(provide 'info-look) + +;;; info-look.el ends here diff --git a/gnuplot/info-look.20.3.el b/gnuplot/info-look.20.3.el new file mode 100644 index 0000000..1089260 --- /dev/null +++ b/gnuplot/info-look.20.3.el @@ -0,0 +1,758 @@ +;;; info-look.el --- major-mode-sensitive Info index lookup facility. +;; An older version of this was known as libc.el. + +;; Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + +;; Author: Ralph Schleicher +;; Keywords: help languages + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Code: + +(require 'info) +(eval-and-compile + (condition-case nil + (require 'custom) + (error + (defmacro defgroup (&rest arg) + nil) + (defmacro defcustom (symbol value doc &rest arg) + `(defvar ,symbol ,value ,doc ,@arg))))) + +(defgroup info-lookup nil + "Major mode sensitive help agent." + :group 'help :group 'languages) + +(defvar info-lookup-mode nil + "Symbol of the current buffer's help mode. +Help is provided according to the buffer's major mode if value is nil. +Automatically becomes buffer local when set in any fashion.") +(make-variable-buffer-local 'info-lookup-mode) + +(defcustom info-lookup-other-window-flag t + "Non-nil means pop up the Info buffer in another window." + :group 'info-lookup :type 'boolean) + +(defcustom info-lookup-highlight-face 'highlight + "Face for highlighting looked up help items. +Setting this variable to nil disables highlighting." + :group 'info-lookup :type 'face) + +(defvar info-lookup-highlight-overlay nil + "Overlay object used for highlighting.") + +(defcustom info-lookup-file-name-alist + '(("\\`configure\\.in\\'" . autoconf-mode) + ("\\`aclocal\\.m4\\'" . autoconf-mode) + ("\\`acsite\\.m4\\'" . autoconf-mode) + ("\\`acinclude\\.m4\\'" . autoconf-mode)) + "Alist of file names handled specially. +List elements are cons cells of the form + + (REGEXP . MODE) + +If a file name matches REGEXP, then use help mode MODE instead of the +buffer's major mode." + :group 'info-lookup :type '(repeat (cons (string :tag "Regexp") + (symbol :tag "Mode")))) + +(defvar info-lookup-history nil + "History of previous input lines.") + +(defvar info-lookup-alist nil + "Alist of known help topics. +Cons cells are of the form + + (HELP-TOPIC . HELP-DATA) + +HELP-TOPIC is the symbol of a help topic. +HELP-DATA is a HELP-TOPIC's public data set. + Value is an alist with elements of the form + + (HELP-MODE REGEXP IGNORE-CASE DOC-SPEC PARSE-RULE OTHER-MODES) + +HELP-MODE is a mode's symbol. +REGEXP is a regular expression matching those help items whose + documentation can be looked up via DOC-SPEC. +IGNORE-CASE is non-nil if help items are case insensitive. +DOC-SPEC is a list of documentation specifications of the form + + (INFO-NODE TRANS-FUNC PREFIX SUFFIX) + +INFO-NODE is the name (including file name part) of an Info index. +TRANS-FUNC is a function translating index entries into help items; + nil means add only those index entries matching REGEXP, a string + means prepend string to the first word of all index entries. +PREFIX and SUFFIX are parts of a regular expression. If one of + them is non-nil then search the help item's Info node for the + first occurrence of the regular expression `PREFIX ITEM SUFFIX'. + ITEM will be highlighted with `info-lookup-highlight-face' if this + variable is not nil. +PARSE-RULE is either the symbol name of a function or a regular + expression for guessing the default help item at point. Fuzzy + regular expressions like \"[_a-zA-Z0-9]+\" do a better job if + there are no clear delimiters; do not try to write too complex + expressions. PARSE-RULE defaults to REGEXP. +OTHER-MODES is a list of cross references to other help modes.") + +(defsubst info-lookup->topic-value (topic) + (cdr (assoc topic info-lookup-alist))) + +(defsubst info-lookup->mode-value (topic mode) + (assoc mode (info-lookup->topic-value topic))) + +(defsubst info-lookup->regexp (topic mode) + (nth 1 (info-lookup->mode-value topic mode))) + +(defsubst info-lookup->ignore-case (topic mode) + (nth 2 (info-lookup->mode-value topic mode))) + +(defsubst info-lookup->doc-spec (topic mode) + (nth 3 (info-lookup->mode-value topic mode))) + +(defsubst info-lookup->parse-rule (topic mode) + (nth 4 (info-lookup->mode-value topic mode))) + +(defsubst info-lookup->other-modes (topic mode) + (nth 5 (info-lookup->mode-value topic mode))) + +(eval-and-compile + (mapcar (lambda (keyword) + (or (boundp keyword) + (set keyword keyword))) + '(:topic :mode :regexp :ignore-case + :doc-spec :parse-rule :other-modes))) + +(defun info-lookup-add-help (&rest arg) + "Add or update a help specification. +Function arguments are one or more options of the form + + KEYWORD ARGUMENT + +KEYWORD is either `:topic', `:mode', `:regexp', `:ignore-case', + `:doc-spec', `:parse-rule', or `:other-modes'. +ARGUMENT has a value as explained in the documentation of the + variable `info-lookup-alist'. + +If no topic or mode option has been specified, then the help topic defaults +to `symbol', and the help mode defaults to the current major mode." + (apply 'info-lookup-add-help* nil arg)) + +(defun info-lookup-maybe-add-help (&rest arg) + "Add a help specification iff no one is defined. +See the documentation of the function `info-lookup-add-help' +for more details." + (apply 'info-lookup-add-help* t arg)) + +(defun info-lookup-add-help* (maybe &rest arg) + (let (topic mode regexp ignore-case doc-spec + parse-rule other-modes keyword value) + (setq topic 'symbol + mode major-mode + regexp "\\w+") + (while arg + (setq keyword (car arg)) + (or (symbolp keyword) + (error "Junk in argument list \"%S\"" arg)) + (setq arg (cdr arg)) + (and (null arg) + (error "Keyword \"%S\" is missing an argument" keyword)) + (setq value (car arg) + arg (cdr arg)) + (cond ((eq keyword :topic) + (setq topic value)) + ((eq keyword :mode) + (setq mode value)) + ((eq keyword :regexp) + (setq regexp value)) + ((eq keyword :ignore-case) + (setq ignore-case value)) + ((eq keyword :doc-spec) + (setq doc-spec value)) + ((eq keyword :parse-rule) + (setq parse-rule value)) + ((eq keyword :other-modes) + (setq other-modes value)) + (t + (error "Unknown keyword \"%S\"" keyword)))) + (or (and maybe (info-lookup->mode-value topic mode)) + (let* ((data (list regexp ignore-case doc-spec parse-rule other-modes)) + (topic-cell (or (assoc topic info-lookup-alist) + (car (setq info-lookup-alist + (cons (cons topic nil) + info-lookup-alist))))) + (mode-cell (assoc mode topic-cell))) + (if (null mode-cell) + (setcdr topic-cell (cons (cons mode data) (cdr topic-cell))) + (setcdr mode-cell data)))) + nil)) + +(defvar info-lookup-cache nil + "Cache storing data maintained automatically by the program. +Value is an alist with cons cell of the form + + (HELP-TOPIC . ((HELP-MODE INITIALIZED COMPLETIONS REFER-MODES) ...)) + +HELP-TOPIC is the symbol of a help topic. +HELP-MODE is a mode's symbol. +INITIALIZED is nil if HELP-MODE is uninitialized, t if + HELP-MODE is initialized, and `0' means HELP-MODE is + initialized but void. +COMPLETIONS is an alist of documented help items. +REFER-MODES is a list of other help modes to use.") + +(defsubst info-lookup->cache (topic) + (or (assoc topic info-lookup-cache) + (car (setq info-lookup-cache + (cons (cons topic nil) + info-lookup-cache))))) + +(defun info-lookup->topic-cache (topic) + (cdr (info-lookup->cache topic))) + +(defun info-lookup->mode-cache (topic mode) + (assoc mode (info-lookup->topic-cache topic))) + +(defun info-lookup->initialized (topic mode) + (nth 1 (info-lookup->mode-cache topic mode))) + +(defun info-lookup->completions (topic mode) + (or (info-lookup->initialized topic mode) + (info-lookup-setup-mode topic mode)) + (nth 2 (info-lookup->mode-cache topic mode))) + +(defun info-lookup->refer-modes (topic mode) + (or (info-lookup->initialized topic mode) + (info-lookup-setup-mode topic mode)) + (nth 3 (info-lookup->mode-cache topic mode))) + +(defun info-lookup->all-modes (topic mode) + (cons mode (info-lookup->refer-modes topic mode))) + +(defun info-lookup-quick-all-modes (topic mode) + (cons mode (info-lookup->other-modes topic mode))) + +;;;###autoload +(defun info-lookup-reset () + "Throw away all cached data. +This command is useful if the user wants to start at the beginning without +quitting Emacs, for example, after some Info documents were updated on the +system." + (interactive) + (setq info-lookup-cache nil)) + +;;;###autoload +(defun info-lookup-symbol (symbol &optional mode) + "Display the documentation of a symbol. +If called interactively, SYMBOL will be read from the mini-buffer. +Prefix argument means unconditionally insert the default symbol name +into the mini-buffer so that it can be edited. +The default symbol is the one found at point." + (interactive + (info-lookup-interactive-arguments 'symbol)) + (info-lookup 'symbol symbol mode)) + +;;;###autoload +(defun info-lookup-file (file &optional mode) + "Display the documentation of a file. +If called interactively, FILE will be read from the mini-buffer. +Prefix argument means unconditionally insert the default file name +into the mini-buffer so that it can be edited. +The default file name is the one found at point." + (interactive + (info-lookup-interactive-arguments 'file)) + (info-lookup 'file file mode)) + +(defun info-lookup-interactive-arguments (topic) + "Return default value and help mode for help topic TOPIC." + (let* ((mode (if (info-lookup->mode-value topic (info-lookup-select-mode)) + info-lookup-mode + (info-lookup-change-mode topic))) + (completions (info-lookup->completions topic mode)) + (default (info-lookup-guess-default topic mode)) + (input (if (or current-prefix-arg (not (assoc default completions))) + default)) + (completion-ignore-case (info-lookup->ignore-case topic mode)) + (enable-recursive-minibuffers t) + (value (completing-read + (if (and default (not input)) + (format "Describe %s (default %s): " topic default) + (format "Describe %s: " topic)) + completions nil nil input 'info-lookup-history))) + (list (if (equal value "") default value) mode))) + +(defun info-lookup-select-mode () + (when (and (not info-lookup-mode) (buffer-file-name)) + (let ((file-name (file-name-nondirectory (buffer-file-name))) + (file-name-alist info-lookup-file-name-alist)) + (while (and (not info-lookup-mode) file-name-alist) + (when (string-match (caar file-name-alist) file-name) + (setq info-lookup-mode (cdar file-name-alist))) + (setq file-name-alist (cdr file-name-alist))))) + (or info-lookup-mode (setq info-lookup-mode major-mode))) + +(defun info-lookup-change-mode (topic) + (let* ((completions (mapcar (lambda (arg) + (cons (symbol-name (car arg)) (car arg))) + (info-lookup->topic-value topic))) + (mode (completing-read + (format "Use %s help mode: " topic) + completions nil t nil 'info-lookup-history))) + (or (setq mode (cdr (assoc mode completions))) + (error "No %s help available" topic)) + (or (info-lookup->mode-value topic mode) + (error "No %s help available for `%s'" topic mode)) + (setq info-lookup-mode mode))) + +(defun info-lookup (topic item mode) + "Display the documentation of a help item." + (or mode (setq mode (info-lookup-select-mode))) + (or (info-lookup->mode-value topic mode) + (error "No %s help available for `%s'" topic mode)) + (let ((entry (or (assoc (if (info-lookup->ignore-case topic mode) + (downcase item) item) + (info-lookup->completions topic mode)) + (error "Not documented as a %s: %s" topic (or item "")))) + (modes (info-lookup->all-modes topic mode)) + (window (selected-window)) + found doc-spec node prefix suffix doc-found) + (if (not info-lookup-other-window-flag) + (info) + (save-window-excursion (info)) + (switch-to-buffer-other-window "*info*")) + (while (and (not found) modes) + (setq doc-spec (info-lookup->doc-spec topic (car modes))) + (while (and (not found) doc-spec) + (setq node (nth 0 (car doc-spec)) + prefix (nth 2 (car doc-spec)) + suffix (nth 3 (car doc-spec))) + (when (condition-case error-data + (progn + (Info-goto-node node) + (setq doc-found t)) + (error + (message "Cannot access Info node %s" node) + (sit-for 1) + nil)) + (condition-case nil + (progn + (Info-menu (or (cdr entry) item)) + (setq found t) + (if (or prefix suffix) + (let ((case-fold-search + (info-lookup->ignore-case topic (car modes))) + (buffer-read-only nil)) + (goto-char (point-min)) + (re-search-forward + (concat prefix (regexp-quote item) suffix)) + (goto-char (match-beginning 0)) + (and window-system info-lookup-highlight-face + ;; Search again for ITEM so that the first + ;; occurence of ITEM will be highlighted. + (re-search-forward (regexp-quote item)) + (let ((start (match-beginning 0)) + (end (match-end 0))) + (if (overlayp info-lookup-highlight-overlay) + (move-overlay info-lookup-highlight-overlay + start end (current-buffer)) + (setq info-lookup-highlight-overlay + (make-overlay start end)))) + (overlay-put info-lookup-highlight-overlay + 'face info-lookup-highlight-face))))) + (error nil))) + (setq doc-spec (cdr doc-spec))) + (setq modes (cdr modes))) + (or doc-found + (error "Info documentation for lookup was not found")) + ;; Don't leave the Info buffer if the help item couldn't be looked up. + (if (and info-lookup-other-window-flag found) + (select-window window)))) + +(defun info-lookup-setup-mode (topic mode) + "Initialize the internal data structure." + (or (info-lookup->initialized topic mode) + (let (cell data (initialized 0) completions refer-modes) + (if (not (info-lookup->mode-value topic mode)) + (message "No %s help available for `%s'" topic mode) + ;; Recursively setup cross references. + ;; But refer only to non-void modes. + (mapcar (lambda (arg) + (or (info-lookup->initialized topic arg) + (info-lookup-setup-mode topic arg)) + (and (eq (info-lookup->initialized topic arg) t) + (setq refer-modes (cons arg refer-modes)))) + (info-lookup->other-modes topic mode)) + (setq refer-modes (nreverse refer-modes)) + ;; Build the full completion alist. + (setq completions + (nconc (info-lookup-make-completions topic mode) + (apply 'append + (mapcar (lambda (arg) + (info-lookup->completions topic arg)) + refer-modes)))) + (setq initialized t)) + ;; Update `info-lookup-cache'. + (setq cell (info-lookup->mode-cache topic mode) + data (list initialized completions refer-modes)) + (if (not cell) + (setcdr (info-lookup->cache topic) + (cons (cons mode data) (info-lookup->topic-cache topic))) + (setcdr cell data)) + initialized))) + +(defun info-lookup-make-completions (topic mode) + "Create a unique alist from all index entries." + (let ((doc-spec (info-lookup->doc-spec topic mode)) + (regexp (concat "^\\(" (info-lookup->regexp topic mode) + "\\)\\([ \t].*\\)?$")) + node trans entry item prefix result doc-found + (buffer (get-buffer-create " temp-info-look"))) + (with-current-buffer buffer + (Info-mode)) + (while doc-spec + (setq node (nth 0 (car doc-spec)) + trans (cond ((eq (nth 1 (car doc-spec)) nil) + (lambda (arg) + (if (string-match regexp arg) + (match-string 1 arg)))) + ((stringp (nth 1 (car doc-spec))) + (setq prefix (nth 1 (car doc-spec))) + (lambda (arg) + (if (string-match "^\\([^: \t\n]+\\)" arg) + (concat prefix (match-string 1 arg))))) + (t (nth 1 (car doc-spec))))) + (with-current-buffer buffer + (message "Processing Info node `%s'..." node) + (when (condition-case error-data + (progn + (Info-goto-node node) + (setq doc-found t)) + (error + (message "Cannot access Info node `%s'" node) + (sit-for 1) + nil)) + (condition-case nil + (progn + (goto-char (point-min)) + (and (search-forward "\n* Menu:" nil t) + (while (re-search-forward "\n\\* \\([^:\t\n]*\\):" nil t) + (setq entry (match-string 1) + item (funcall trans entry)) + (and (info-lookup->ignore-case topic mode) + (setq item (downcase item))) + (and (string-equal entry item) + (setq entry nil)) + (or (assoc item result) + (setq result (cons (cons item entry) result)))))) + (error nil)))) + (message "Processing Info node `%s'...done" node) + (setq doc-spec (cdr doc-spec))) + (or doc-found + (error "Info documentation for lookup was not found")) + result)) + +(defun info-lookup-guess-default (topic mode) + "Pick up default item at point (with favor to look back). +Return nil if there is nothing appropriate." + (let ((modes (info-lookup->all-modes topic mode)) + (start (point)) guess whitespace) + (while (and (not guess) modes) + (setq guess (info-lookup-guess-default* topic (car modes)) + modes (cdr modes)) + (goto-char start)) + ;; Collapse whitespace characters. + (and guess (concat (delete nil (mapcar (lambda (ch) + (if (or (char-equal ch ? ) + (char-equal ch ?\t) + (char-equal ch ?\n)) + (if (not whitespace) + (setq whitespace ? )) + (setq whitespace nil) ch)) + guess)))))) + +(defun info-lookup-guess-default* (topic mode) + (let ((case-fold-search (info-lookup->ignore-case topic mode)) + (rule (or (info-lookup->parse-rule topic mode) + (info-lookup->regexp topic mode))) + (start (point)) end regexp subexp result) + (if (symbolp rule) + (setq result (funcall rule)) + (if (consp rule) + (setq regexp (car rule) + subexp (cdr rule)) + (setq regexp rule + subexp 0)) + (skip-chars-backward " \t\n") (setq end (point)) + (while (and (re-search-backward regexp nil t) + (looking-at regexp) + (>= (match-end 0) end)) + (setq result (match-string subexp))) + (if (not result) + (progn + (goto-char start) + (skip-chars-forward " \t\n") + (and (looking-at regexp) + (setq result (match-string subexp)))))) + result)) + +(defun info-lookup-guess-c-symbol () + "Get the C symbol at point." + (condition-case nil + (progn + (backward-sexp) + (let ((start (point)) prefix name) + ;; Test for a leading `struct', `union', or `enum' keyword + ;; but ignore names like `foo_struct'. + (setq prefix (and (< (skip-chars-backward " \t\n") 0) + (< (skip-chars-backward "_a-zA-Z0-9") 0) + (looking-at "\\(struct\\|union\\|enum\\)\\s ") + (concat (match-string 1) " "))) + (goto-char start) + (and (looking-at "[_a-zA-Z][_a-zA-Z0-9]*") + (setq name (match-string 0))) + ;; Caveat! Look forward if point is at `struct' etc. + (and (not prefix) + (or (string-equal name "struct") + (string-equal name "union") + (string-equal name "enum")) + (looking-at "[a-z]+\\s +\\([_a-zA-Z][_a-zA-Z0-9]*\\)") + (setq prefix (concat name " ") + name (match-string 1))) + (and (or prefix name) + (concat prefix name)))) + (error nil))) + +;;;###autoload +(defun info-complete-symbol (&optional mode) + "Perform completion on symbol preceding point." + (interactive) + (info-complete 'symbol + (or mode + (if (info-lookup->mode-value + 'symbol (info-lookup-select-mode)) + info-lookup-mode + (info-lookup-change-mode 'symbol))))) + +;;;###autoload +(defun info-complete-file (&optional mode) + "Perform completion on file preceding point." + (interactive) + (info-complete 'file + (or mode + (if (info-lookup->mode-value + 'file (info-lookup-select-mode)) + info-lookup-mode + (info-lookup-change-mode 'file))))) + +(defun info-complete (topic mode) + "Try to complete a help item." + (barf-if-buffer-read-only) + (or mode (setq mode (info-lookup-select-mode))) + (or (info-lookup->mode-value topic mode) + (error "No %s completion available for `%s'" topic mode)) + (let ((modes (info-lookup-quick-all-modes topic mode)) + (start (point)) + try) + (while (and (not try) modes) + (setq mode (car modes) + modes (cdr modes) + try (info-lookup-guess-default* topic mode)) + (goto-char start)) + (and (not try) + (error "Found no %S to complete" topic)) + (let ((completions (info-lookup->completions topic mode)) + (completion-ignore-case (info-lookup->ignore-case topic mode)) + completion) + (setq completion (try-completion try completions)) + (cond ((not completion) + (ding) + (message "No match")) + ((stringp completion) + (or (assoc completion completions) + (setq completion (completing-read + (format "Complete %S: " topic) + completions nil t completion + info-lookup-history))) + (delete-region (- start (length try)) start) + (insert completion)) + (t + (message "%s is complete" + (capitalize (prin1-to-string topic)))))))) + + +;;; Initialize some common modes. + +(info-lookup-maybe-add-help + :mode 'c-mode :topic 'symbol + :regexp "\\(struct \\|union \\|enum \\)?[_a-zA-Z][_a-zA-Z0-9]*" + :doc-spec '(("(libc)Function Index" nil + "^[ \t]+- \\(Function\\|Macro\\): .*\\<" "\\>") + ("(libc)Variable Index" nil + "^[ \t]+- \\(Variable\\|Macro\\): .*\\<" "\\>") + ("(libc)Type Index" nil + "^[ \t]+- Data Type: \\<" "\\>") + ("(termcap)Var Index" nil + "^[ \t]*`" "'")) + :parse-rule 'info-lookup-guess-c-symbol) + +(info-lookup-maybe-add-help + :mode 'c-mode :topic 'file + :regexp "[_a-zA-Z0-9./+-]+" + :doc-spec '(("(libc)File Index"))) + +(info-lookup-maybe-add-help + :mode 'bison-mode + :regexp "[:;|]\\|%\\([%{}]\\|[_a-z]+\\)\\|YY[_A-Z]+\\|yy[_a-z]+" + :doc-spec '(("(bison)Index" nil + "`" "'")) + :parse-rule "[:;|]\\|%\\([%{}]\\|[_a-zA-Z][_a-zA-Z0-9]*\\)" + :other-modes '(c-mode)) + +(info-lookup-maybe-add-help + :mode 'makefile-mode + :regexp "\\$[^({]\\|\\.[_A-Z]*\\|[_a-zA-Z][_a-zA-Z0-9-]*" + :doc-spec '(("(make)Name Index" nil + "^[ \t]*`" "'")) + :parse-rule "\\$[^({]\\|\\.[_A-Z]*\\|[_a-zA-Z0-9-]+") + +(info-lookup-maybe-add-help + :mode 'texinfo-mode + :regexp "@\\([a-zA-Z]+\\|[^a-zA-Z]\\)" + :doc-spec '(("(texinfo)Command and Variable Index" + ;; Ignore Emacs commands and prepend a `@'. + (lambda (item) + (if (string-match "^\\([a-zA-Z]+\\|[^a-zA-Z]\\)\\( .*\\)?$" item) + (concat "@" (match-string 1 item)))) + "`" "'"))) + +(info-lookup-maybe-add-help + :mode 'm4-mode + :regexp "[_a-zA-Z][_a-zA-Z0-9]*" + :doc-spec '(("(m4)Macro index")) + :parse-rule "[_a-zA-Z0-9]+") + +(info-lookup-maybe-add-help + :mode 'autoconf-mode + :regexp "A[CM]_[_A-Z0-9]+" + :doc-spec '(("(autoconf)Macro Index" "AC_" + "^[ \t]+- \\(Macro\\|Variable\\): .*\\<" "\\>") + ("(automake)Index" nil + "^[ \t]*`" "'")) + ;; Autoconf symbols are M4 macros. Thus use M4's parser. + :parse-rule 'ignore + :other-modes '(m4-mode)) + +(info-lookup-maybe-add-help + :mode 'awk-mode + :regexp "[_a-zA-Z]+" + :doc-spec '(("(gawk)Index" + (lambda (item) + (let ((case-fold-search nil)) + (cond + ;; `BEGIN' and `END'. + ((string-match "^\\([A-Z]+\\) special pattern\\b" item) + (match-string 1 item)) + ;; `if', `while', `do', ... + ((string-match "^\\([a-z]+\\) statement\\b" item) + (if (not (string-equal (match-string 1 item) "control")) + (match-string 1 item))) + ;; `NR', `NF', ... + ((string-match "^[A-Z]+$" item) + item) + ;; Built-in functions (matches to many entries). + ((string-match "^[a-z]+$" item) + item)))) + "`" "\\([ \t]*([^)]*)\\)?'"))) + +(info-lookup-maybe-add-help + :mode 'perl-mode + :regexp "[$@%][^a-zA-Z]\\|\\$\\^[A-Z]\\|[$@%]?[a-zA-Z][_a-zA-Z0-9]*" + :doc-spec '(("(perl5)Function Index" + (lambda (item) + (if (string-match "^\\([a-zA-Z0-9]+\\)" item) + (match-string 1 item))) + "^" "\\b") + ("(perl5)Variable Index" + (lambda (item) + ;; Work around bad formatted array variables. + (let ((sym (cond ((or (string-match "^\\$\\(.\\|@@\\)$" item) + (string-match "^\\$\\^[A-Z]$" item)) + item) + ((string-match + "^\\([$%@]\\|@@\\)?[_a-zA-Z0-9]+" item) + (match-string 0 item)) + (t "")))) + (if (string-match "@@" sym) + (setq sym (concat (substring sym 0 (match-beginning 0)) + (substring sym (1- (match-end 0)))))) + (if (string-equal sym "") nil sym))) + "^" "\\b")) + :parse-rule "[$@%]?\\([_a-zA-Z0-9]+\\|[^a-zA-Z]\\)") + +(info-lookup-maybe-add-help + :mode 'latex-mode + :regexp "\\\\\\([a-zA-Z]+\\|[^a-zA-Z]\\)" + :doc-spec '(("(latex2e)Command Index" nil + "`" "\\({[^}]*}\\)?'"))) + +(info-lookup-maybe-add-help + :mode 'scheme-mode + :regexp ;; "\\(\\sw\\|\\s_\\)+" + "[^()' \t\n]+" + :ignore-case t + ;; Aubrey Jaffer's rendition from + :doc-spec '(("(r5rs)Index"))) + +(info-lookup-maybe-add-help + :mode 'emacs-lisp-mode + :regexp "[^()' \t\n]+" + :doc-spec '(("(emacs)Command Index") + ("(emacs)Variable Index") + ("(elisp)Index" + (lambda (item) + (let ((sym (intern-soft item))) + (cond ((null sym) + (if (string-equal item "nil") item)) + ((or (boundp sym) (fboundp sym)) + item)))) + "^[ \t]+- [^:]+:[ \t]*" "\\b"))) + +(info-lookup-maybe-add-help + :mode 'lisp-interaction-mode + :regexp "[^()' \t\n]+" + :parse-rule 'ignore + :other-modes '(emacs-lisp-mode)) + +(info-lookup-maybe-add-help + :mode 'lisp-mode + :regexp "[^()' \t\n]+" + :parse-rule 'ignore + :other-modes '(emacs-lisp-mode)) + +(info-lookup-maybe-add-help + :mode 'scheme-mode + :regexp "[^()' \t\n]+" + :ignore-case t + :doc-spec '(("(r5rs)Index" nil + "^[ \t]+- [^:]+:[ \t]*" "\\b"))) + + +(provide 'info-look) + +;;; info-look.el ends here diff --git a/python/init_python.el b/python/init_python.el index 9a6e117..86f8d11 100644 --- a/python/init_python.el +++ b/python/init_python.el @@ -1,17 +1,10 @@ -(autoload 'python-mode "python-mode" "Python Mode." t) -(add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode)) -(add-to-list 'interpreter-mode-alist '("python" . python-mode)) -(require 'python-mode) -(add-hook 'python-mode-hook - (lambda () - (set-variable 'py-indent-offset 4) - ;(set-variable 'py-smart-indentation nil) - (set-variable 'indent-tabs-mode nil) - (define-key py-mode-map (kbd "RET") 'newline-and-indent) - ;(define-key py-mode-map [tab] 'yas/expand) - ;(setq yas/after-exit-snippet-hook 'indent-according-to-mode) - ;(smart-operator-mode-on) - )) +;(autoload 'python-mode "python-mode" "Python Mode." t) +;(add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode)) +;(add-to-list 'interpreter-mode-alist '("python" . python-mode)) +;(require 'python-mode) +;(provide 'python) +;(provide 'python21) + ;; pymacs (autoload 'pymacs-apply "pymacs") (autoload 'pymacs-call "pymacs") @@ -31,6 +24,193 @@ (define-key ropemacs-local-keymap "\M-/" 'hippie-expand) +(defun write-file-py-cleanup-imports () + (save-excursion + (condition-case nil + (py-cleanup-imports t) + (error . nil))) + nil) + +(defun python-init-auto-cleanup-imports-on-save () + (add-hook 'write-file-functions 'write-file-py-cleanup-imports nil t)) + +(defun my-flymake-error-at-point () + (condition-case nil + (flymake-ler-text (car (nth 0 (flymake-find-err-info flymake-err-info + (flymake-current-line-no))))) + (error (error "no flymake error at point")))) + +(defun my-flymake-show-error () + (interactive) + (message (my-flymake-error-at-point))) + +(defun my-pyflymake-add-import-from-error () + (interactive) + (let ((err (my-flymake-error-at-point))) + (if (string-match "undefined name '\\(.*\\)'" err) + (py-add-import (match-string 1 err)) + (error "no missing symbol at point")))) + +(defun py-add-import (import) + (interactive "sModule to import: ") + (save-window-excursion + (save-excursion + (goto-char (car (py-imports-region))) + (insert "import " import "\n") + (py-cleanup-imports t) + (sit-for 2)))) + +(defun my-flymake-check-and-wait () + (if (boundp flymake-is-running) + (progn + (while flymake-is-running (sit-for .1)) + (flymake-start-syntax-check) + (while flymake-is-running (sit-for .1))))) + +(defun my-flymake-goto-next-error () + (interactive) + (my-flymake-check-and-wait) + (flymake-goto-next-error) + (my-flymake-show-error)) + +(defun py-find-file (errormark filename defaultdir) + (let ((fullname (expand-file-name filename defaultdir))) + (or (and (not (file-exists-p fullname)) + (let* ((name (loop for name = fullname then (directory-file-name + (file-name-directory name)) + if (file-exists-p name) return name)) + (fmt (and name (with-temp-buffer + (insert-file-contents name nil 0 1024 t) (archive-find-type)))) + (tail (and fmt (substring fullname (1+ (length name)))))) + (if fmt + (with-current-buffer (find-file-noselect name) + (goto-char (point-min)) + (re-search-forward (concat " " (regexp-quote tail) "$")) + (save-window-excursion + (archive-extract) + (current-buffer)))))) + (compilation-find-file errormark filename defaultdir)))) + +(require 'arc-mode) + +(defun py-eshell-goto-error (&optional back) + (interactive "P") + (display-buffer "*eshell*" t) + (let (here end start dir file line errmk example) + (with-current-buffer "*eshell*" + (save-excursion + ;; Find and validate last traceback + (goto-char (point-max)) + (re-search-backward "^\\(.*\\)Traceback \\|^Failed example:") + (beginning-of-line) + (if (looking-at "Failed example:") + (progn + (forward-line -2) + (setq example t))) + (if (or (not (and (boundp 'py-eshell-last-error) + (boundp 'py-eshell-last-point))) + (null py-eshell-last-error) + (null py-eshell-last-point) + (null py-eshell-last-dir) + (not (= py-eshell-last-error (point)))) + (progn + (set (make-local-variable 'py-eshell-last-error) (point)) + (set (make-local-variable 'py-eshell-prefix) (or (match-string 1) "")) + (if example + (forward-line 2) + (while (and (< (forward-line 1) 1) (looking-at (concat py-eshell-prefix " "))))) + (set (make-local-variable 'py-eshell-last-point) (point)) + (set (make-local-variable 'py-eshell-last-dir) default-directory) + (while + (and (< (forward-line 1) 1) + (not (if (looking-at ".*Leaving directory ") + (progn + (goto-char (match-end 0)) + (skip-chars-forward "'\"`") + (let ((dir (current-word))) + (and dir (setq py-eshell-last-dir + (file-name-as-directory dir))))))))))) + (goto-char py-eshell-last-point) + + ;; Nove to next / prev frame in traceback + (if back + (progn + (while (and (looking-at (concat py-eshell-prefix " ")) + (< (forward-line 1) 1) + (not (looking-at (concat py-eshell-prefix " File "))))) + (setq start (point)) + (while (and (looking-at (concat py-eshell-prefix " ")) + (< (forward-line 1) 1) + (not (looking-at (concat py-eshell-prefix " File "))))) + (setq end (point))) + (while (and (> (forward-line -1) -1) + (not (looking-at (concat py-eshell-prefix (if example "File " " File ")))) + (> (point) py-eshell-last-error))) + (setq end py-eshell-last-point start (point))) + + ;; Parse information and set overlay + (if (save-excursion (goto-char start) (setq errmk (point-marker)) + (looking-at (concat py-eshell-prefix (if example "File " " File ")))) + (let ((default-directory py-eshell-last-dir)) + (set (make-local-variable 'py-eshell-last-point) start) + (if (and (boundp 'py-eshell-overlay) py-eshell-overlay) + (move-overlay py-eshell-overlay start end) + (set (make-local-variable 'py-eshell-overlay) (make-overlay start end)) + (overlay-put py-eshell-overlay 'face 'highlight)) + (save-excursion + (goto-char start) + (forward-char (+ (length py-eshell-prefix) 7)) + (skip-chars-forward "\"") + (setq file (current-word)) + (search-forward " line ") + (skip-chars-forward " ") + (setq line (string-to-number + (buffer-substring-no-properties + (point) (progn (skip-chars-forward "0-9") (point))))) + (setq dir default-directory)) + (if (null file) + (error "File not found"))) + (py-eshell-error-reset) + (error "No further traceback line")))) + + ;; move to error locus + (if (and file line errmk) + (with-current-buffer (py-find-file errmk file dir) + (compilation-goto-locus errmk (save-excursion (goto-line line) (point-marker)) nil))))) + +(defun py-eshell-error-reset () + (interactive) + (save-excursion + (set-buffer "*eshell*") + (if (and (boundp 'py-eshell-overlay) py-eshell-overlay) + (delete-overlay py-eshell-overlay)) + (set (make-local-variable 'py-eshell-last-error) nil) + (set (make-local-variable 'py-eshell-last-point) nil) + (set (make-local-variable 'py-eshell-last-dir) nil) + (set (make-local-variable 'py-eshell-prefix) nil) + (set (make-local-variable 'py-eshell-overlay) nil))) + +(global-set-key "\C-xP" 'py-eshell-goto-error) +(global-set-key "\C-x\C-p" 'python-shell) + +(add-hook 'python-mode-hook 'python-init-auto-cleanup-imports-on-save) + +(defun py-setup-hook () + ;(set-variable 'py-indent-offset 4) + ;(set-variable 'py-smart-indentation nil) + (set-variable 'indent-tabs-mode nil) + ;(define-key py-mode-map (kbd "RET") 'newline-and-indent) + ;(define-key py-mode-map [tab] 'yas/expand) + ;(setq yas/after-exit-snippet-hook 'indent-according-to-mode) + ;(smart-operator-mode-on) + (define-key python-mode-map "\C-ci" 'my-pyflymake-add-import-from-error) + (define-key python-mode-map "\C-ce" 'my-flymake-show-error) + (define-key python-mode-map "\C-cn" 'my-flymake-goto-next-error) + (define-key python-mode-map "\C-cI" 'py-cleanup-imports) +) + +(add-hook 'python-mode-hook 'py-setup-hook) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Auto-completion ;;; Integrates: @@ -116,23 +296,29 @@ '("\\.py\\'" flymake-pyflakes-init))) (add-hook 'find-file-hook 'flymake-find-file-hook) +(defun py-imports-region () + (save-excursion + (goto-char (point-min)) + (while (and (re-search-forward "^\\(import\\s-+\\|from\\s-+\\)" nil t) + (looking-at "__future__"))) + (beginning-of-line) + (setq beg (point)) + (if (not (looking-at "\\(import\\s-+\\|from\\s-+\\)")) + (cons beg beg) + (while (looking-at "\\(import\\s-+\\|from\\s-+\\)") + (forward-line 1)) + (cons beg (point))))) + (defun py-cleanup-imports (&optional nowait) (interactive) (let (beg end) (if (region-active-p) (setq beg (region-beginning) end (region-end)) - (save-excursion - (goto-char (point-min)) - (while (and (re-search-forward "^\\(import\\s-+\\|from\\s-+\\)" nil t) - (looking-at "__future__"))) - (beginning-of-line) - (if (not (looking-at "\\(import\\s-+\\|from\\s-+\\)")) - (error "No imports found")) - (setq beg (point)) - (while (looking-at "\\(import\\s-+\\|from\\s-+\\)") - (forward-line 1)) - (setq end (point)))) + (setq reg (py-imports-region)) + (if (= (car reg) (cdr reg)) + (error "No imports found")) + (setq beg (car reg) end (cdr reg))) (sort-lines t beg end) (goto-char beg) (let ((end-marker (make-marker)) @@ -161,9 +347,7 @@ (sort-lines nil b (point)) (if (and (not nowait) (boundp flymake-is-running)) (progn - (while flymake-is-running (sit-for .1)) - (flymake-start-syntax-check) - (while flymake-is-running (sit-for .1)) + (my-flymake-check-and-wait) (goto-char beg) (while (< (point) end-marker) (if (and (loop for ov in (overlays-at (point)) diff --git a/python/setup.el b/python/setup.el index ffb1b4d..56275ee 100644 --- a/python/setup.el +++ b/python/setup.el @@ -6,15 +6,3 @@ (load-library "auto-completion") (require 'init_python) - -(defun write-file-py-cleanup-imports () - (save-excursion - (condition-case nil - (py-cleanup-imports) - (error . nil))) - nil) - -(defun python-init-auto-cleanup-imports-on-save () - (add-hook 'write-file-functions 'write-file-py-cleanup-imports nil t)) - -(add-hook 'python-mode-hook 'python-init-auto-cleanup-imports-on-save) diff --git a/setup/bindings.el b/setup/bindings.el index b3a1fa0..622bc61 100644 --- a/setup/bindings.el +++ b/setup/bindings.el @@ -3,6 +3,7 @@ (global-set-key "\C-c'h" 'highlight-changes-mode) (global-set-key "\C-c'f" 'auto-fill-mode) (global-set-key "\C-c'v" 'visual-line-mode) +(global-set-key "\C-c't" 'toggle-truncate-lines) (global-set-key "\C-c'd" 'toggle-debug-on-error) (global-set-key "\C-c'g" 'toggle-debug-on-quit) (global-set-key "\C-c'c" 'toggle-case-fold-search) diff --git a/setup/dired.el b/setup/dired.el new file mode 100644 index 0000000..d043528 --- /dev/null +++ b/setup/dired.el @@ -0,0 +1,42 @@ +(require 'dired-x) + +(defvar dired-omit-regexp-orig (symbol-function 'dired-omit-regexp)) + +(defun dired-omit-regexp () + (let ((file (expand-file-name ".git")) + parent-dir) + (while (and (not (file-exists-p file)) + (progn + (setq parent-dir + (file-name-directory + (directory-file-name + (file-name-directory file)))) + ;; Give up if we are already at the root dir. + (not (string= (file-name-directory file) + parent-dir)))) + ;; Move up to the parent dir and try again. + (setq file (expand-file-name ".git" parent-dir))) + ;; If we found a change log in a parent, use that. + (if (file-exists-p file) + (let ((regexp (funcall dired-omit-regexp-orig))) + (assert (stringp regexp)) + (concat + regexp + (if (> (length regexp) 0) + "\\|" "") + "\\(" + (mapconcat + #'(lambda (str) + (concat "^" + (regexp-quote + (substring str 13 + (if (= ?/ (aref str (1- (length str)))) + (1- (length str)) + nil))) + "$")) + (split-string (shell-command-to-string + "git clean -d -x -n") + "\n" t) + "\\|") + "\\)")) + (funcall dired-omit-regexp-orig)))) diff --git a/setup/eshell.el b/setup/eshell.el new file mode 100644 index 0000000..66fc6bc --- /dev/null +++ b/setup/eshell.el @@ -0,0 +1,11 @@ +(require 'esh-mode) + +; grrr ... eshell-mode-map is buffer-local ... +(defun my-setup-eshell () + (define-key eshell-mode-map (kbd "") 'previous-line) + (define-key eshell-mode-map (kbd "") 'next-line) + (define-key eshell-mode-map (kbd "C-") 'eshell-previous-matching-input-from-input) + (define-key eshell-mode-map (kbd "C-") 'eshell-next-matching-input-from-input) + (define-key eshell-mode-map (kbd "") 'eshell-bol)) + +(add-hook 'eshell-mode-hook 'my-setup-eshell) diff --git a/setup/gnuplot.el b/setup/gnuplot.el new file mode 100644 index 0000000..b0ed624 --- /dev/null +++ b/setup/gnuplot.el @@ -0,0 +1,14 @@ +(let ((dir (concat (file-name-directory + (directory-file-name + (file-name-directory (or load-file-name + (when (boundp 'bytecomp-filename) bytecomp-filename) + buffer-file-name)))) + (file-name-as-directory "gnuplot")))) + (add-to-list 'load-path dir) + (load (concat dir "autoload.el"))) + +(defun gnuplot () + (interactive) + (gnuplot-make-gnuplot-buffer) + (sit-for .1) + (switch-to-buffer "*gnuplot*")) \ No newline at end of file diff --git a/setup/magit.el b/setup/magit.el index c4405bb..b88f553 100644 --- a/setup/magit.el +++ b/setup/magit.el @@ -46,7 +46,12 @@ (let ((default-directory (magit-get-top-dir default-directory))) (if (not default-directory) (error "not a Git directory")) - (grep (format "git ls-files -z | xargs -r0 grep -nH -E %s | cat -" (shell-quote-argument regexp))))) + (grep (format "git ls-files -z | xargs -r0 grep -nH -E %s | cat -" + (shell-quote-argument regexp))))) + +(setenv "GIT_PAGER" "cat") +(setenv "GIT_MAN_VIEWER" "woman") +(setenv "GIT_EDITOR" "emacsclient") (defun find-file-maybe-git (&optional nogit) (interactive "P") @@ -57,13 +62,19 @@ (global-set-key "\C-x\C-f" 'find-file-maybe-git) (global-set-key "\C-cGG" 'grep-in-git-repo) -(defun git-files-find-symbol (&optional arg) - (interactive "P") - (let ((symbol (current-word)) - (dir (magit-get-top-dir default-directory))) +(defun git-files-find-symbol (symbol) + (interactive (list (read-string "Symbol: " (current-word)))) + (let ((dir (magit-get-top-dir default-directory))) (if (not dir) (error "No git repository")) - (if arg (setq symbol (read-string "Symbol: " nil nil symbol))) (let ((default-directory dir)) (grep (format "git ls-files -z | xargs -r0 grep -nwHF %s | cat -" symbol))))) (global-set-key "\C-cGF" 'git-files-find-symbol) + +(defun dired-git-files () + (interactive) + (let ((default-directory (magit-get-top-dir default-directory)) + (ls-lisp-use-insert-directory-program t)) + (dired (cons default-directory (split-string (shell-command-to-string "git ls-files") "\n"))))) + +(global-set-key "\C-cGD" 'dired-git-files) diff --git a/setup/mywin.el b/setup/mywin.el index 2d36460..63ab71d 100644 --- a/setup/mywin.el +++ b/setup/mywin.el @@ -54,10 +54,17 @@ window smaller than MIN-HEIGHT lines." (shrink-window (- (window-height) min-height)) (shrink-window n)))) +(defconst setup-my-windows-precious-buffers + '("*eshell*")) +(defconst setup-my-windows-junk-buffers + '("*scratch*" "*Messages*" "*Calculator" "*Calc Trail*" "*compilation*" "*fetchmail*")) + (defun setup-my-windows () (interactive) (let ((width 100) (min 100) (distribute t) - (currentwindow (selected-window)) topwindows newwindow newtopwindows) + (currentbuffer (current-buffer)) + (currentwindow (selected-window)) + topwindows firstwindow newwindow newtopwindows) (walk-windows (function (lambda (w) (let ((e (window-edges w))) (if (< (nth 1 e) window-min-height) @@ -70,29 +77,69 @@ window smaller than MIN-HEIGHT lines." topwindows)))))) 'nomini) (setq topwindows (sort topwindows (function (lambda (a b) (< (car a) (car b)))))) + (setq topwindows (loop for w in topwindows + for (pos win buf point start iscurrent) = w + if (not (member (buffer-name buf) setup-my-windows-junk-buffers)) + collect w)) (delete-other-windows (nth 1 (car topwindows))) - (setq topwindows (cdr topwindows)) (save-selected-window (select-window (split-window-vertically (- (window-height) (max 5 (/ (* (frame-height) 15) 100)) -1))) - (switch-to-buffer (get-buffer-create "*compilation*"))) - (setq newwindow (selected-window)) + (switch-to-buffer (get-buffer-create "*compilation*")) + (if (eq currentbuffer (current-buffer)) + (setq newwindow (selected-window)))) + (setq firstwindow (selected-window)) (setq newtopwindows (list (selected-window))) (while (> (window-width) (+ width 3 min 3)) (select-window (split-window-horizontally (+ width 3))) (setq newtopwindows (cons (selected-window) newtopwindows)) - (if topwindows - (progn - (switch-to-buffer (nth 2 (car topwindows))) - (set-window-start (selected-window) (nth 4 (car topwindows))) - (goto-char (nth 3 (car topwindows))) - (if (nth 5 (car topwindows)) - (setq newwindow (selected-window))) - (setq topwindows (cdr topwindows))) - (switch-to-buffer (get-buffer-create "*scratch*")))) - (select-window newwindow) + (switch-to-buffer (get-buffer-create "*scratch*"))) + (setq newtopwindows (reverse newtopwindows)) + (loop for w in newtopwindows + for (pos win buf point start iscurrent) in + (loop for w in topwindows + for (pos win buf point start iscurrent) = w + if (not (member (buffer-name buf) setup-my-windows-precious-buffers)) + collect w) + do (progn + (select-window w) + (set-window-buffer w buf) + (set-window-start w start) + (goto-char point) + (if iscurrent + (setq newwindow w)))) + (setq newtopwindows (reverse newtopwindows)) + (setq topwindows (reverse topwindows)) + (loop for w in newtopwindows + for (pos win buf point start iscurrent) in + (loop for w in topwindows + for (pos win buf point start iscurrent) = w + if (member (buffer-name buf) setup-my-windows-precious-buffers) + collect w) + do (progn + (select-window w) + (set-window-buffer w buf) + (set-window-start w start) + (goto-char point) + (if iscurrent + (setq newwindow w)))) + (setq newwindow + (or newwindow + (loop for w in newtopwindows + if (eq (window-buffer w) currentbuffer) return w) + (loop for w in newtopwindows + for name = (buffer-name (window-buffer w)) + if (string= name "*scratch*") return w) + (loop for w in newtopwindows + for name = (buffer-name (window-buffer w)) + if (and (= (aref name 0) ?*) + (not (member name setup-my-windows-precious-buffers))) return w) + firstwindow)) (if (and distribute (> (length newtopwindows) 1)) - (balance-windows newwindow)))) + (balance-windows firstwindow)) + (select-window newwindow) + (if (not (member (buffer-name currentbuffer) setup-my-windows-junk-buffers)) + (switch-to-buffer currentbuffer)))) (defun my-split-window-sensibly (window) (if (and (> (window-height window) (- (frame-height (window-frame window)) window-min-height)) @@ -107,8 +154,52 @@ window smaller than MIN-HEIGHT lines." (global-set-key "\C-xp" 'other-window-reverse) (global-set-key "\C-\M-_" (lambda () (interactive) (safe-shrink-window 5))) +(defun my-swap-window-to-right (&optional stay) + (interactive "P") + (let ((cb (current-buffer)) + (cw (selected-window))) + (windmove-right) + (set-window-buffer cw (current-buffer)) + (switch-to-buffer cb) + (if stay + (select-window cw)))) + +(defun my-swap-window-to-left (&optional stay) + (interactive "P") + (let ((cb (current-buffer)) + (cw (selected-window))) + (windmove-left) + (set-window-buffer cw (current-buffer)) + (switch-to-buffer cb) + (if stay + (select-window cw)))) + +(global-set-key "\C-x>" 'my-swap-window-to-right) +(global-set-key "\C-x<" 'my-swap-window-to-left) + (defun maximize-window-15 () (interactive) (maximize-window (max 5 (/ (* (frame-height) 15) 100)))) (global-set-key [(ctrl meta ?+)] 'maximize-window-15) + +(defun safe-max-window-horizontally () + (interactive) + (let ((found nil) + (width 0) + (count 0) + (current (selected-window))) + (walk-windows (function (lambda (w) + (let ((e (window-edges w))) + (if (< (nth 1 e) window-min-height) + (progn + (setq width (+ width (window-width w)) + count (1+ count)) + (if (equal w current) + (setq found t))))))) + 'nomini) + (if (not found) + (error "Current window is not a top window")) + (shrink-window-horizontally (- (- width (window-width) (* window-min-width (1- count))))))) + +(global-set-key "\C-x=" 'safe-max-window-horizontally) diff --git a/setup/nxml.el b/setup/nxml.el index 2ee07cf..b87997d 100644 --- a/setup/nxml.el +++ b/setup/nxml.el @@ -6,38 +6,49 @@ (defun nxml-where () "Display the hierarchy of XML elements the point is on as a path." (and (eq major-mode 'nxml-mode) - (let (path-to-id path-rest) - (save-excursion - (save-restriction - (widen) - (while (and (not (bobp)) - (condition-case nil (progn (nxml-backward-up-element) t) (error nil))) - (multiple-value-bind - (has-id step) - (loop with has-id = nil - with step = (xmltok-start-tag-local-name) - for att in xmltok-attributes - if (string= (xmltok-attribute-local-name att) "id") - return (values t (concat "\"" (xmltok-attribute-value att) "\"")) - else if (string= (xmltok-attribute-local-name att) "name") - do (setq has-id t step (concat "\"" (xmltok-attribute-value att) "\"")) - finally return (values has-id step )) - (if (or path-to-id has-id) - (setq path-to-id (cons step path-to-id)) - (setq path-rest (cons step path-rest))))))) - (let ((path-to-id-len (length path-to-id)) - (path-rest-len (length path-rest))) - (if (> path-to-id-len nxml-where-elements-to-id) - (progn - (setq path-to-id (nthcdr (- path-to-id-len nxml-where-elements-to-id -1) path-to-id)) - (setq path-to-id (cons "..." path-to-id)) - (setq path-to-id-len nxml-where-elements-to-id)) - (setq path-to-id (cons "" path-to-id))) - (when (> (+ path-to-id-len path-rest-len) nxml-where-max-elements) - (setq path-rest (nbutlast path-rest (- path-rest-len (- nxml-where-max-elements path-to-id-len) -1))) - (setq path-rest (nconc path-rest (list "..."))))) - (mapconcat 'identity (nconc path-to-id path-rest) "/")))) - + (let (path-to-id path-rest) + (save-excursion + (save-restriction + (widen) + (while (and (not (bobp)) + (condition-case nil (progn (nxml-backward-up-element) t) + (error nil))) + (multiple-value-bind + (has-id step) + (loop with has-id = nil + with step = (xmltok-start-tag-local-name) + for att in xmltok-attributes + if (string= (xmltok-attribute-local-name att) "id") + return (values t (concat "\"" + (xmltok-attribute-value att) + "\"")) + else if (string= (xmltok-attribute-local-name att) "name") + do (setq has-id t + step (concat "\"" + (xmltok-attribute-value att) + "\"")) + finally return (values has-id step )) + (if (or path-to-id has-id) + (setq path-to-id (cons step path-to-id)) + (setq path-rest (cons step path-rest))))))) + (let ((path-to-id-len (length path-to-id)) + (path-rest-len (length path-rest))) + (if (> path-to-id-len nxml-where-elements-to-id) + (progn + (setq path-to-id (nthcdr (- path-to-id-len + nxml-where-elements-to-id + -1) path-to-id)) + (setq path-to-id (cons "..." path-to-id)) + (setq path-to-id-len nxml-where-elements-to-id)) + (setq path-to-id (cons "" path-to-id))) + (when (> (+ path-to-id-len path-rest-len) nxml-where-max-elements) + (setq path-rest (nbutlast path-rest (- path-rest-len + (- nxml-where-max-elements + path-to-id-len) + -1))) + (setq path-rest (nconc path-rest (list "..."))))) + (mapconcat 'identity (nconc path-to-id path-rest) "/")))) + (require 'which-func) (which-func-mode) @@ -60,8 +71,8 @@ (require 'hideshow) -(add-to-list 'hs-special-modes-alist '(nxml-mode ("\\(<[^/>]*>\\)$" 1) - "]*>$")) +(add-to-list 'hs-special-modes-alist '(nxml-mode ("\\(<[^/>]*>\\)$" 1) "]*>$")) + (defun nxml-enable-hs () (setq nxml-sexp-element-flag t) (hs-minor-mode 1)) @@ -71,10 +82,10 @@ (defun hs-nxml-enter () (interactive) (when (hs-already-hidden-p) - (hs-show-block) - (hs-hide-level 1) - (nxml-forward-element) - (nxml-backward-element))) + (hs-show-block) + (hs-hide-level 1) + (nxml-forward-element) + (nxml-backward-element))) (defun hs-nxml-leave () (interactive) @@ -123,7 +134,8 @@ (define-key nxml-mode-map (kbd "\C-c\C-c") 'recompile) (defconst nxml-docbook-common-elements - '(("section" . ("para" "itemizedlist" "variablelist" "section" "bridgehead" "task" "procedure" "title")) + '(("section" . ("para" "itemizedlist" "variablelist" "section" "bridgehead" "task" "procedure" + "title")) ("para" . ("emphasis" "code" "replaceable")) ("emphasis" . ("code")) ("itemizedlist" . ("listitem")) @@ -156,9 +168,9 @@ (save-excursion (nxml-backward-up-element) (let ((tag (xmltok-start-tag-qname))) - (list (save-excursion - (skip-chars-forward "^>") - (forward-char 1) + (list (save-excursion + (skip-chars-forward "^>") + (forward-char 1) (point)) (progn (nxml-forward-balanced-item) @@ -172,8 +184,10 @@ (let ((start (set-marker (make-marker) (or start (point)))) (end (set-marker (make-marker) (or end (point))))) (when kill-tag - (delete-region (save-excursion (goto-char start) (skip-chars-backward "^<") (1- (point))) start) - (delete-region end (save-excursion (goto-char end) (skip-chars-forward "^>") (1+ (point))))) + (delete-region (save-excursion + (goto-char start) (skip-chars-backward "^<") (1- (point))) start) + (delete-region end (save-excursion + (goto-char end) (skip-chars-forward "^>") (1+ (point))))) (save-excursion (goto-char start) (let* ((token-end (nxml-token-before)) @@ -193,9 +207,9 @@ (context (xmltok-start-tag-qname)) (common-elements (cdr (assoc context nxml-docbook-common-elements))) (valid-elements (or valid - (let ((lt-pos (point))) - (rng-set-state-after lt-pos) - (loop for (ns . name) in (rng-match-possible-start-tag-names) + (let ((lt-pos (point))) + (rng-set-state-after lt-pos) + (loop for (ns . name) in (rng-match-possible-start-tag-names) if (not (member name elements)) collect name into elements finally return elements)))) (elements (loop for element in common-elements