Warning: this is a htmlized version!
The original is across this link.
;;; eev.el --- embed shell/tcl/perl code and elisp hyperlinks in plain text.

;; Copyright (C) 1999 Free Software Foundation, Inc.

;; Author:     Eduardo Ochs <edrx@mat.puc-rio.br>
;; Maintainer: Eduardo Ochs <edrx@mat.puc-rio.br>
;; Version:    1999jan20
;; Keywords:   escripts, hyperlinks, shell, tcl, perl, tex
;;
;; This file was copylefted to prevent against patent psychopaths; if
;; you want a version with any other license you'll have to write it
;; yourself. More formally,
;;
;; 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 of the
;; License, or (at your option) any later version.

;;; Commentary:

;; This package provides support for e-scripts in Emacs. Look in
;; <http://angg.twu.net/emacs.html> for more information and in
;; <http://angg.twu.net/escripts.html> for examples of e-scripts... an
;; e-script is typically a text file in which certain parts are meant
;; to be executed by the shell or by other programs and certain
;; comments are in fact Emacs Lisp code; executing one of these
;; comments with C-x C-e (i.e., eval-last-sexp) brings up a file or an
;; info node, and thus works as a hyperlink. Many of the comments in
;; this file can be executed in this way.

;; (find-elnode "Autoload" "magic autoload comment")
;; (find-elnode "Comment Tips")
;; (find-elnode "Library Headers")
;; (find-elnode "Documentation Tips")
;; (find-elfile "")

;;; Code:

;;;;
;;;;  «find-»
;;;; Basic "find-..." functions
;;;;

;;;###autoload
(defun goto-position (pos-spec)
  (if pos-spec (goto-char (point-min)))
  (if (numberp pos-spec)
      (forward-line (1- pos-spec)))
  (if (stringp pos-spec)
      (search-forward pos-spec)))

(autoload 'Info-goto-node "info")

;;;###autoload
(defun find-node (nodestr &optional line)
  (if (Info-goto-node nodestr)
      (if line (goto-position line))))

;;;###autoload
(defun find-fline (fname &optional line)
  (find-file (substitute-in-file-name fname))
  (goto-position line))



;;;;
;;;;  «eev_pre»
;;;; The "ee" family. Basic building blocks,
;;;;
;;
;; (find-elnode "Writing to Files" "If START is a string")
;; "s": "start of region", or "string";
;; "e": "end of region".

(defun se-to-string (s e)
  (cond ((numberp s) (buffer-substring s e))
	((stringp s) s)))

(defun octal-to-num (str)
  (let ((lastv (- (string-to-char (substring str -1)) ?0))
	(rest (substring str 0 -1)))
    (if (string= "" rest) lastv (+ lastv (* 8 (octal-to-num rest))))))

(setq ee-file "$EE")

(defun write-ee-string (str &optional other-ee-file fmode)
  (let ((fname (substitute-in-file-name (or other-ee-file ee-file))))
    (write-region str nil fname)	; a standard kludge
    (if fmode (set-file-modes fname (octal-to-num fmode)))))

(defun write-ee (s e pre post &optional other-ee-file fmode)
  (write-ee-string (concat pre (se-to-string s e) post) other-ee-file fmode))


;;;;
;;;;  «eev»
;;;; eev and friends.
;;;;
;;
;; "C-x eev" writes the "region" of the current buffer (i.e.,
;; everything between the cursor and the "mark") to a file, so that it
;; can be executed as a script. In fact it does better than that: the
;; region is saved surrounded by "set -v" and "set +v" and we source
;; it instead of running it as a script, to let it use and change the
;; environment, the directory and the pool of aliases and functions of
;; the current shell. Marking a block of text in emacs, typing "C-x
;; eev" and then going to a shell and running "ee" (which should be
;; aliased to `. $EE', where EE is usually set to ~/bin/emacs.ee, is
;; almost 100% equivalent to typing each line to the shell.
;;
;;  «eev-howto»
;; That was too technical... Here's the "quick eev how-to": put a line
;; like this in your .emacs:
;;
;;   (load-library "~/eev.el")
;;
;; and put these two lines in your .zshrc:
;;
;;   export EE=~/bin/emacs.ee
;;   alias ee='. $EE'
;;
;; Restart zsh if needed, and enter Emacs. Write some shell commands;
;; mark a block of text and run C-x eev. You should get a message like
;; "wrote ~/bin/emacs.ee" in the echo area at the bottom of the
;; screen. Switch to a zsh (e.g., in another virtual console or in
;; another window) and run "ee". Voila`, your commands will be
;; executed, and each of them will be displayed (without pause) before
;; being executed.
;;
;;  «eev-bash»
;; If you use bash instead of zsh you'll have to put the
;; "export/alias" lines in your .bashrc instead; all the rest is the
;; same, except that the last line ("set +v") won't be overwritten by
;; the next shell prompt and will remain on the screen. (Ugly. I need
;; to fix this.)
;;
;;  «eev-tcsh»
;; If you use tcsh then things are a bit worse. This is what you
;; should put in your .cshrc:
;;
;;   setenv EE ~/bin/emacs.ee
;;   alias ee 'source $EE'
;;
;; and as the commands to put the shell in verbose mode are different
;; in tcsh you should either use eevt instead of eev or, better, make
;; the definition of eevt overwrite the definition of eev, by dropping
;; the "t" in eevt's defun or by loading eev.el like this:
;;
;;   (load-library "~/eev.el")
;;   (defun eev (s e &optional other-ee-file) (interactive "r")
;;     (write-ee s e "set verbose\n" "\nunset verbose" other-ee-file))
;;
;; See:
;; (find-node "(zsh)Shell Builtin Commands" "`source'")
;; (find-node "(zsh)Shell Builtin Commands" "`set ")
;; (find-node "(zsh)Shell Builtin Commands" "`.")
;; (find-node "(zsh)Description of Options" "-v")
;; (find-node "(bash)Bourne Shell Builtins" "`.'")
;; (find-node "(bash)The Set Builtin" "  `-v'")
;; (find-elnode "Markers")

;;;###autoload
(defun eev (s e &optional other-ee-file) (interactive "r")
  (write-ee s e "set -v\n" "\nset +v" other-ee-file))             ; zsh/bash
;;;###autoload
(defun eevt (s e &optional other-ee-file) (interactive "r")
  (write-ee s e "set verbose\n" "\nunset verbose" other-ee-file)) ; tcsh

;; eev to some remote machines, using ange-ftp:
;;
(defun eevb (s e) (interactive "r")
  (eev s e "/edrx@$SACI:bin/emacs.ee"))
(defun eevp (s e) (interactive "r")
  (eev s e "/patna:/home/root/bin/emacs.ee"))
(defun eevi (s e) (interactive "r")
  (eev s e "/ifigenia:/home/root/bin/emacs.ee"))

;; eex: uses "-x" instead of "-v"
;; ees: "silent", i.e., non-verbose
;;
(defun eex (s e) (interactive "r")
  (write-ee s e "set -x\n" "\nset +x"))
(defun ees (s e) (interactive "r")
  (write-ee s e "" "\n"))

;; eecd: change to the current buffer's directory
;; Try "M-x pwd" to see it...
;;
;;;###autoload
(defun eecd () (interactive)
  (eev (concat "cd " default-directory) nil))

'(defun eel (s e) (interactive "r")
  (write-ee s e "lynx " "\n"))

;;  «gdb»
;; Hey, you: use "ee" inside gdb to invoke the saved block.
;; You need to have something like
;;   define ee
;;     source ~/GDB/emacs.eeg
;;   end
;; inside your .gdbinit.
;; (find-fline "~/.gdbinit")
;; (find-angg ".emacs" "gdb")
;;
(defun eeg (s e) (interactive "r")
  (write-ee s e "" "" "~/GDB/emacs.eeg"))

;; perl, tcl/tk, expect
;;
(defun eep (s e) (interactive "r")
  (write-ee s e "#!/usr/bin/perl\n" "" "~/bin/eep" "0777"))
(defun eew (s e) (interactive "r")
  (write-ee s e "#!/usr/bin/wish\n" "" "$EET" "0777"))
(defun eet (s e) (interactive "r")
  (write-ee s e "#!/usr/bin/tclsh\n" "" "$EET" "0777"))
(defun eex (s e) (interactive "r")
  (write-ee s e "#!/usr/bin/expect\n" "" "$EET" "0777"))
(defun eextk (s e) (interactive "r")
  (write-ee s e "#!/usr/bin/expectk\n" "" "$EET" "0777"))

;; (find-es "page" "latte")
'(defun eel (s e) (interactive "r")
  (write-ee s e "latte-html -f - <<'--%%--'
                 {\\include /home/root/latte/sty.latte}\n"
	    "\n--%%--\n"))

;; eed, for dosemu. Aaargh!!
;;
(defun crlfify (s)
  (if (string-match "\\([^\n]*\\)\n\\(\\)" s)
      (concat (match-string 1 s) "\r\n"
	      (crlfify (substring s (match-beginning 2))))
    s))
(defun eed (s e) (interactive "r")
  (write-region (crlfify (se-to-string s e)) nil "/D/ee.bat"))


;;;;
;;;;  «eeman»
;;;; eeman: linking to specific points on manpages
;;;;
;;
;; This function is a hybrid between the find-xxx's and the
;; code-c-d's; it works as a link to a specific point on a manpage,
;; but you need to go to a shell and type "ee" to let it call man.
;;
;; Examples of usage:
;;
;; (eeman "man"  "  -P")
;; (eeman "less" "  \\+cmd")
;; (eeman "expect" 972)
;;
;;;###autoload
(defun eeman (str &optional line)
  (cond ((numberp line)
	 (write-ee-string (format "man -P 'less +%d' %s\n" line str)))
	((stringp line)
	 (write-ee-string (format "man -P \"less '+/%s'\" %s\n" line str)))
	(t
	 (write-ee-string (format "man %s\n" str)))))


;;;;
;;;;  «eelatex»
;;;; Things to run LaTeX on a block of text.
;;;;
;;
;; Run this on a block of text and then do a "ee" on a shell; a file
;; ~/LATEX/tmp.tex will be written and "make" will be called to
;; generate a tmp.dvi from it.
;;
;; (find-fline "~/LATEX/tese2.sty")
;;
(defun eelatex (s e) (interactive "r")
  (write-ee s e "cat > ~/LATEX/tmp.tex <<'--%%--'
                 \\input tese2.sty
                 \\begin{document}
                 % \\input mar99a.dnt
                 % \\input mar99b.dnt\n"
	    "\n\\end{document}\n--%%--
             cd ~/LATEX
             rm tmp.dvi
             make tmp.dvi\n"))

;;;;
;;;;  «bounded»
;;;; "Bounded" versions for some eev commands; instead of working
;;;; with the region these functions select the text around point
;;;; until some fixed delimiter strings.
;;;;
;;
;; Some support functions, 
;; (find-elnode "String Search")
;;
(defun ee-search-backward (str)
  (+ (save-excursion (search-backward str))
     (length str)))
(defun ee-search-forward (str)
  (- (save-excursion (search-forward str))
     (length str)))
(defun ee-strbounded (fun sstr estr &rest rest)
  (apply fun
	 (ee-search-backward sstr)
	 (ee-search-forward estr)
	 rest))
(defun write-ee-bounded (sstr estr &rest rest)
  (apply 'ee-strbounded 'write-ee sstr estr rest))

;; and the bounded ee's themselves:
;;
(defun eelatex-bounded () (interactive)
  (ee-strbounded 'eelatex "\n%*\n" "\n%*\n"))
(defun eegdb-bounded () (interactive)
  (ee-strbounded 'write-ee "\n%*\n" "\n%*\n" "" "" "~/GDB/emacs.eeg"))
(defun eepf-bounded () (interactive)
  (ee-strbounded 'write-ee "%*" "%*" "" "" "/usr/src/pforth/ee.fth"))

'(global-set-key [f3] 'eegdb-bounded)
'(global-set-key [f3] 'eepf-bounded)
'(global-set-key [f3] 'eelatex-bounded)


;;;;
;;;;  «code-c-d»
;;;; code-c-d, a factory of hypertext functions
;;;;
;;
;; (find-efile "etags.el")
(load-library "etags")
(setq tags-add-tables nil)		; for find-___tags

(defun format-and-eval (formatstr &rest rest)
  (eval (read (apply 'format (concat "(progn " formatstr ")") rest))))

(defun find-node2 (ifile nodename &optional line  code)
  (if code (setq ee-code-now code ee-ifile-now ifile))
  (find-node (concat "(" ifile ")" nodename) line))

;;;###autoload
(defun code-c-d (c d &optional ifile)
  (format-and-eval "
    (setq %sdir \"%s\")
    (setq %stagsfile \"%sTAGS\")
    (defun %sfile (str) (concat %sdir str))
    (defun set-%s-tags () (setq tags-file-name %stagsfile))
    (defun find-%sfile (str &optional line) (set-%s-tags)
      (find-fline (%sfile str) line))
    (defun find-%stag (str) (set-%s-tags) (find-tag str))
    (defun find-%sw3 (furl) (w3-open-local (concat %sdir furl)))
    (setq ee-code-now %S ee-ifile-now %S)
    " c d  c d  c c  c c  c c c  c c  c c  c ifile)
  (if ifile
     (format-and-eval "
       (defun find-%snode (nodename &optional line)
          (find-node2 %S nodename line  %S))" c ifile  c)))

;;  «code-c-d-explan1»
;;
;; To understand exactly what a given "code-c-d" does, put an "i"
;; before the "code-c-d" and run it; the function "icode-c-d", defined
;; below, is a hack that will insert at point the block of code that
;; code-c-d would eval. For example,
;;
;;   (icode-c-d "awk" "/usr/src/gawk-3.0.3/" "gawk")
;;
;; gives, modulo indentation,
;;
;;   (progn
;;     (setq awkdir "/usr/src/gawk-3.0.3/")
;;     (setq awktagsfile "/usr/src/gawk-3.0.3/TAGS")
;;     (defun awkfile (str) (concat awkdir str))
;;     (defun set-awk-tags () (setq tags-file-name awktagsfile))
;;     (defun find-awkfile (str &optional line) (set-awk-tags)
;;       (find-fline (awkfile str) line))
;;     (defun find-awktag (str) (set-awk-tags) (find-tag str))
;;     (defun find-awkw3 (furl) (w3-open-local (concat awkdir furl))))
;;     (setq ee-code-now "awk" ee-ifile-now "awk")
;; 
;;   (progn
;;     (defun find-awknode (nodename &optional line)
;;       (find-node2 "gawk" nodename line)))
;;
;; where the second progn block would not have been generated if the
;; third argument to code-c-d (the name of an info file) had been
;; suppressed.
;;
;;  «code-c-d-explan2»
;;
;; That is, the first argument to a code-c-d is the "prefix", the
;; second if the "path", the third is the "info file". A call to
;; code-c-d with a prefix of "xxx" defines xxxdir, xxxtagsfile,
;; xxxfile, set-xxx-tags, find-xxxfile, find-xxxtag, find-xxxw3 and
;; maybe find-xxxnode; there are lots of examples of usage of these
;; functions in this file and in my e-scripts directory, which is at
;; <http://angg.twu.net/escripts.html>.

;; This is quite ridiculous but works.
;;
(defun icode-c-d (&rest args)
  (defun format-and-eval (formatstr &rest rest)
    (insert (apply 'format (concat "\n(progn " formatstr ")\n") rest)))
  (apply 'code-c-d args)
  (defun format-and-eval (formatstr &rest rest)
    (eval (read (apply 'format (concat "(progn " formatstr ")") rest)))))



;;  «ccd-exs»
;; Some sample code-c-d's.
;; A typical .emacs (e.g., mine:-) has over 150 calls to code-c-d:
;; (find-angg ".emacs" "code-c-ds")

(code-c-d "knuth" "$SCTAN/systems/knuth/")
(code-c-d "vldi" "/var/lib/dpkg/info/")
(code-c-d "k2" "/usr/src/linux-2.0/")
(code-c-d "k22" "/usr/src/linux-2.2/")

(code-c-d "e" "/usr/share/emacs/19.34/lisp/" "emacs-19/emacs")
(code-c-d "el" "/usr/share/emacs/19.34/lisp/" "elisp")
(code-c-d "eli" "/usr/src/emacs-lisp-intro-1.05/" "emacs-lisp-intro")



;; Some little hacks...

(defun find-pl5pod (radix &optional line)
  (find-pl5file (concat "pod/perl" radix ".pod") line))

;; Find strings enclosed in angle quotation marks.
;; Some characters may look wrong on your screen...
;;
(defun find-tagh (fname &optional tag)
  (if tag (find-fline fname (format " «%s»" tag))
    (find-fline fname)))
(defun find-es (file &optional tag)
  (find-tagh (esfile (concat file ".e")) tag))
(defun find-angg (file &optional tag)
  (find-tagh (concat "~/" file) tag))

(defun find-slink (s) (deb-view (concat "/home/root/SLINK/" s)))



;;;;
;;;; Two extra functions for hypertext
;;;;
;;
;; (find-elnode "Buffer File Name")
;; (find-elnode "Interactive Examples")
;; (find-efile "info.el")
;; (find-etag "Info-set-mode-line")
;;
(defun bfn (buffername)
  "Insert the full file name for a buffer."
  (interactive "bBuffer: ")
  (insert (buffer-file-name (get-buffer buffername))))
;;
;;  «inn»
(defun inn (arg)
  "Insert an hyperlink to the current info node.  With an argument
try to use the short form, like `# (find-elnode \"Top\")'.  Without
an argument always write something like `(find-node \"(elisp)Top\")'."
  (interactive "P")
  (let (f node ee code s)
    (save-excursion
      (set-buffer "*info*")
      (string-match "info/\\(.*\\)$" Info-current-file)
      (setq f (match-string 1 Info-current-file))
      (setq node Info-current-node))
    (insert (if (and arg (string= f ee-ifile-now))
		(format "# (find-%snode \"%s\")\n" ee-code-now node)
	      (format "# (find-node \"(%s)%s\")\n" f node)))))


;;;;
;;;;  «dff»
;;;; dff - a macro to create find-xxx
;;;; commands for debian packages
;;;;
;;
;; (find-node "(elisp)Keyboard Macros")
;;
(defun dff (N)
  "Convert N lines with a name of a debian package in each to N
``# (find-vldifile \"/xxx.list\")
  # (find-fline \"/usr/doc/xxx/\")''
pairs."
  (interactive "p")
  (execute-kbd-macro
   (read-kbd-macro "C-a # SPC (find-vldifile SPC \" NUL C-e ESC w .list\")
		    C-a <down> RET <up> # SPC (find-fline SPC \"/usr/doc/
		    C-y /\") C-a <down>")
   N))



;;; eev.el ends here