'(
shell
cd /tmp/
ls
)
***
(defun ee-bol () (point-at-bol))
(defun ee-eol () (point-at-eol))
(defun ee-read (str) (read (concat "(progn\n" str "\n)")))
(defun ee-eval (sexp) (let ((debug-on-error nil)) (eval sexp)))
(defun ee-eval-string (str)
"Wrap STR in a progn then read it and eval it.
Examples: (ee-eval-string \"(+ 1 2) (* 3 4) ;; this returns 12=3*4\")
(ee-eval-string \";; this returns nil\")"
(ee-eval (ee-read str)))
(defun ee-eval-string-print (str)
"Wrap STR in a progn then read it, eval it, and print it."
(prin1 (ee-eval-string str)))
(defun ee-next-line (&optional arg try-vscroll)
(interactive "p")
"Line `next-line', but ignoring visual line mode.
This function is used by `eepitch-this-line'."
(let ((line-move-visual nil))
(next-line arg try-vscroll)))
(defvar eepitch-regexp "^*\\(.*\\)"
"The regexp used by `eepitch-this-line' to determine what is a red-star line.
Red star lines are evaluated as lisp, normal lines are pitched to
the target buffer.")
(defvar eepitch-comment-regexp "^**\\(.*\\)"
"The regexp used by `eepitch-this-line' to test if a line is a comment.
Comment lines are neither evaluated nor sent to the target buffer.
The test that ignores comment lines is applied before the test that decides
between red-star lines (that are eval'ed) and normal lines (that are sent).")
(defvar eepitch-buffer-name ""
"The name of the target buffer for eepitch.
Set this to \"\" to force running `eepitch-buffer-create' again.
Note that `eepitch-buffer-create' sets this variable!")
(defvar eepitch-code '(error "eepitch not set up")
"The code to create and switch to the target buffer.")
(defvar eepitch-window-show '(eepitch-window-show)) (defvar eepitch-kill '(eepitch-kill-buffer)) (defvar eepitch-kill-windows 'nil) (defun eepitch-buffer-exists () (get-buffer eepitch-buffer-name))
(defun eepitch-window-exists () (get-buffer-window eepitch-buffer-name))
(defun eepitch-target-buffer () (get-buffer eepitch-buffer-name))
(defun eepitch-target-window () (get-buffer-window eepitch-buffer-name))
(defun eepitch-target-here () (eq (current-buffer) (eepitch-target-buffer)))
(defun eepitch-buffer-create ()
"Eval the sexp in `eepitch-code' and set `eepitch-buffer-name'.
This is done without disturbing the current window configuration.\n
Remember that we say that \"the system is (at least) half-prepared\" when:
1) `eepitch-buffer-name' holds the target buffer name of the sexp
in `eepitch-code',
2) a buffer with name `eepitch-buffer-name' exists.\n
This function makes sure that the system is at least half-prepared.
See `eepitch' and `eepitch-prepare'."
(save-window-excursion
(eval eepitch-code)
(setq eepitch-buffer-name
(buffer-name (current-buffer)))))
(defun eepitch-window-show ()
"Display the buffer `eepitch-buffer-name' in another window.
This is just the default way of making sure that the \"target
window\" is visible; note that `eepitch' sets the variable
`eepitch-window-show' to `(eepitch-window-show)', and that
`eepitch-prepare' evaluates the sexp in the variable
`eepitch-window-show'. Alternative eepitch settings - like the
ones for GUD or Slime, that use multiple windows - put calls to
other functions instead of this one in the variable
`eepitch-window-show'.\n
This function uses `display-buffer', which calls
`split-window-sensibly'."
(let ((pop-up-windows t)
(same-window-buffer-names nil))
(display-buffer eepitch-buffer-name)))
(defun eepitch-prepare ()
"If the eepitch buffer does not exist, create it; if it is not shown, show it.
In eepitch's terminology we say that the system is \"prepared\" when:
1) the variable `eepitch-buffer-name' holds the target buffer
name of the sexp in `eepitch-code',
2) a buffer with name `eepitch-buffer-name' exists,
3) the current buffer's name is not `eepitch-buffer-name', and
4) there is a window - that we will call the \"target window\" -
showing the buffer `eepitch-buffer-name'.
This function makes sure that the system is prepared. Note that
this function is called from both `eepitch' and
`eepitch-this-line'."
(if (not (eepitch-buffer-exists))
(eepitch-buffer-create))
(if (eq (current-buffer) (eepitch-target-buffer))
(error "Can't pitch to the current buffer"))
(if (not (eepitch-window-exists))
(eval eepitch-window-show)))
(defun eepitch (code)
"Set up a target for eepitch and make sure it is displayed in another window.
The argument CODE must be a \"shell-like sexp\", i.e., one that
when evaluated always switches to a buffer with a fixed name, and
when that buffer does not exists it creates it.\n
This function sets `eepitch-code' to CODE and sets the variables
`eepitch-window-show' and `eepitch-kill' to defaults that are
good for two-window settings, and then calls `eepitch-prepare',
which does all the hard work."
(setq eepitch-code code)
(setq eepitch-buffer-name "") (setq eepitch-window-show '(eepitch-window-show)) (setq eepitch-kill '(eepitch-kill-buffer)) (eepitch-prepare)
(list 'Target: eepitch-buffer-name))
(defun eepitch-eval-at-target-window (code)
"Run CODE at the eepitch-target-window."
(eepitch-prepare)
(save-selected-window
(select-window (eepitch-target-window))
(eval code)))
(defun eepitch-line (line)
"Send LINE to the target window and run the key binding for RET there.
This is a low-level function used by `eepitch-this-line'."
(eepitch-eval-at-target-window
'(progn (goto-char (point-max)) (insert line) (call-interactively (key-binding "\r")))))
(defun eepitch-this-line ()
"Pitch this line to the target buffer, or eval it as lisp if it starts with `*'.
Also, if it starts with `**', skip it.
See: (find-eepitch-intro)
and: `eepitch', `eepitch-regexp', `eepitch-comment-regexp'."
(interactive)
(let ((line (buffer-substring (ee-bol) (ee-eol)))) (cond ((string-match eepitch-comment-regexp line) (message "Comment: %s" line)) ((string-match eepitch-regexp line) (ee-eval-string-print (match-string 1 line))) (t (eepitch-prepare) (eepitch-line line)))) (ee-next-line 1))
(defun ee-kill-buffer (buffer)
"Kill BUFFER if it exists, asking for fewer confirmations than usual."
(if (get-buffer buffer)
(let ((kill-buffer-query-functions nil))
(kill-buffer buffer))))
(defun eepitch-kill-buffer ()
"Kill the eepitch target buffer if it exists, avoiding most warnings.
This function does not change the current window configuration,
and is the default behavior for `eepitch-kill' in two-window
settings. See `eepitch' and `eepitch-kill'."
(if (eepitch-buffer-exists)
(if (eepitch-target-here)
(error "Can't kill this")
(ee-kill-buffer eepitch-buffer-name) )))
(defun eepitch-kill ()
"Kill the current eepitch target buffer in the default way.
The default is always the one stored in the variable
`eepitch-kill', and is usually `eepitch-kill-buffer'.
A common idiom - called an \"eepitch block\"; see `eewrap-eepitch'
for a quick way to create eepitch blocks - is to use three
red-star lines in sequence to \"recreate the target\", like this:
* (eepitch-shell)
* (eepitch-kill)
* (eepitch-shell)
When we run the first `(eepitch-shell)' the eepitch target buffer
becomes the buffer \"*shell*\"; then we run the `(eepitch-kill)'
and we are sure that it will kill the buffer \"*shell*\", not
something else; then we run the last `(eepitch-shell)', and as
the eepitch target buffer does not exist it is recreated from
scratch."
(eval eepitch-kill))
(defun eepitch-shell ()
"Same as (eepitch '(shell)). See `eepitch' and `eewrap-eepitch'."
(interactive)
(eepitch '(shell)))
(defun eepitch-shell2 () (interactive) (eepitch '(shell "*shell 2*")))
(defun eepitch-eshell () (interactive) (eepitch '(eshell)))
(defun ee-expand (fname)
"Expand \"~\"s and \"$ENVVAR\"s in file names, but only at the beginning."
(cond ((string-match "^\\$\\([A-Za-z_][0-9A-Za-z_]*\\)\\(.*\\)" fname)
(concat (getenv (match-string 1 fname))
(match-string 2 fname)))
((string-match "^\\(~\\([a-z][0-9a-z_]*\\)?\\)\\(/.*\\)?$" fname)
(concat (expand-file-name (match-string 1 fname))
(match-string 3 fname)))
(t fname)))
(defun ee-split (str) (if (stringp str) (split-string str "[ \t\n]+") str))
(defun ee-split-and-expand (str)
"Convert STR to a list (if it's a string) and apply `ee-expand' to each element.
This function is used by `find-comintprocess', `find-bgprocess'
and `find-callprocess'."
(mapcar 'ee-expand (ee-split str)))
(defun find-comintprocess-ne (name program-and-args)
"Switch to the buffer named *NAME* and run the command PROGRAM-AND-ARGS there.
This function does not run `ee-expand' on the elements of PROGRAM-AND-ARGS."
(let ((argv (ee-split program-and-args)))
(apply 'make-comint name (car argv) nil (cdr argv))
(switch-to-buffer (format "*%s*" name))))
(defun find-comintprocess (name program-and-args)
"Switch to the buffer named *NAME* and run the command PROGRAM-AND-ARGS there.
If PROGRAM-AND-ARGS is a string, split it at whitespace to make it a list.
Each element of PROGRAM-AND-ARGS is expanded with `ee-expand'.
See: (find-eepitch-intro)"
(find-comintprocess-ne name (ee-split-and-expand program-and-args)))
(defun eepitch-comint (name program-and-args)
"Set `eepitch' to run PROGRAM-AND-ARGS in comint mode, in the buffer \"*NAME*\"."
(eepitch `(find-comintprocess ,name ',program-and-args)))
(defface eepitch-star-face
'((t (:foreground "red")))
"Face used for the red star glyph (char 15).")
(defun eepitch-set-glyph (pos &optional char face)
(aset standard-display-table pos
(if char (vector (make-glyph-code char face)))))
(defun ee-no-properties (str)
(setq str (copy-sequence str))
(set-text-properties 0 (length str) nil str)
str)
(defun ee-this-line-extract ()
"Delete the contents of the current line and return it as a string."
(delete-and-extract-region (ee-bol) (ee-eol)))
(defun eewrap-eepitch () (interactive)
(let* ((fmt "* (eepitch-%s)\n* (eepitch-kill)\n* (eepitch-%s)")
(li (ee-this-line-extract))
(newli (format fmt li li)))
(insert newli))
(ee-next-line 1))
(if (not standard-display-table)
(setq standard-display-table (make-display-table)))
(eepitch-set-glyph ?\^O ?* 'eepitch-star-face)
(provide 'eepitch)
(defun at-eepitch-target (code)
(eepitch-prepare)
(save-selected-window
(select-window (eepitch-target-window))
(eval code)))
(defun del-echo (flag)
"A hack to help determining whether a program echoes its commands or not.
An example of use:\n
* (eepitch-zsh)
* (eepitch-kill)
* (eepitch-zsh)
cd /tmp/
* (del-echo t)
cd /tmp/
* (del-echo nil)
cd /tmp/\n"
(at-eepitch-target `(setq comint-process-echoes ,flag))
(message "At %s: %S" eepitch-buffer-name
`(setq comint-process-echoes ,flag)))
(defun eepitch-de (code)
"Like `eepitch', but deletes the echoed commands.
Use this to control programs that echo the commands that they receive."
(eepitch `(progn ,code (setq comint-process-echoes t))))
(defun eepitch-comint-de (name program-and-args)
"Like `eepitch-comint', but deletes the echoed commands.
Use this to control programs that echo the commands that they receive."
(eepitch-de `(find-comintprocess ,name ',program-and-args)))
(defun ee-at0 (dir code)
"Eval CODE at DIR.
If DIR does not end with a slash then weird things might happen.
Note the DIR is `ee-expand'-ed."
(let ((default-directory (ee-expand dir)))
(if (not (file-accessible-directory-p dir))
(error "Can't chdir to %s" dir))
(eval code)))
(defun eepitch-comint-at (dir name program-and-args)
"Like `eepitch-comint', but executes `eepitch-buffer-create' at DIR."
(ee-at0 dir `(eepitch-comint ,name ,program-and-args)))
(defun with-pager-cat (code)
"Run CODE with the environment variable PAGER set to \"cat\".
This is useful for for running processes that use pagers like
\"more\" by default."
(let ((process-environment (cons "PAGER=cat" process-environment)))
(eval code)))
(defun eepitch-to-buffer (name)
(interactive "beepitch to buffer: ")
(eepitch `(switch-to-buffer ,name)))
(defun at-nth-window (n code)
"Run `other-window' N times, run CODE there, and go back."
(save-selected-window
(other-window n)
(eval code)))
(defun eepitch-shell () (interactive) (eepitch '(shell)))
(defun eepitch-shell2 () (interactive) (eepitch '(shell "*shell 2*")))
(defun eepitch-eshell () (interactive) (eepitch '(eshell)))
(defun eepitch-bash () (interactive) (eepitch-comint "bash" "bash"))
(defun eepitch-dash () (interactive) (eepitch-comint "dash" "dash"))
(defun eepitch-ksh () (interactive) (eepitch-comint "ksh" "ksh"))
(defun eepitch-tcsh () (interactive) (eepitch-comint "tcsh" "tcsh"))
(defun eepitch-zsh () (interactive) (eepitch-comint-de "zsh" "zsh"))
(defun eepitch-scsh () (interactive) (eepitch-comint "scsh" "scsh"))
(defun eepitch-lua51 () (interactive) (eepitch-comint "lua51" "lua5.1"))
(defun eepitch-python () (interactive) (eepitch-comint "python" "python"))
(defun eepitch-ruby () (interactive) (eepitch-comint "ruby" "irb1.8"))
(defun eepitch-perl () (interactive) (eepitch-comint "perl" "perl -d -e 42"))
(defun eepitch-tcl () (interactive) (eepitch-comint "tclsh" "tclsh"))
(defun eepitch-tclsh () (interactive) (eepitch-comint "tclsh" "tclsh"))
(defun eepitch-wish () (interactive) (eepitch-comint "wish" "wish"))
(defun eepitch-expect () (interactive) (eepitch-comint "expect" "expect"))
(defun eepitch-sbcl () (interactive) (eepitch-comint "sbcl" "sbcl"))
(defun eepitch-gcl () (interactive) (eepitch-comint "gcl" "gcl"))
(defun eepitch-guile () (interactive) (eepitch-comint "guile" "guile"))
(defun eepitch-mitscheme () (interactive)
(eepitch-comint "mit-scheme" "mit-scheme"))
(defun eepitch-tinyscheme () (interactive)
(eepitch-comint "tinyscheme" "tinyscheme"))
(defun eepitch-hugs () (interactive) (eepitch-comint "hugs" "hugs"))
(defun eepitch-hugs98 () (interactive) (eepitch-comint "hugs" "hugs -98"))
(defun eepitch-ghci () (interactive) (eepitch-comint "ghci" "ghci"))
(defun eepitch-ocaml () (interactive) (eepitch-comint "ocaml" "ocaml"))
(defun eepitch-labltk () (interactive) (eepitch-comint "labltk" "labltk"))
(defun eepitch-polyml () (interactive) (eepitch-comint "polyml" "poly"))
(defun eepitch-erl () (interactive) (eepitch-comint "erl" "erl"))
(defun eepitch-coqtop () (interactive) (eepitch-comint "coqtop" "coqtop"))
(defun eepitch-gforth () (interactive) (eepitch '(run-forth "gforth")))
(defun eepitch-gforth () (interactive) (eepitch-comint "gforth" "gforth"))
(defun eepitch-pforth () (interactive) (eepitch-comint "pforth" "pforth"))
(defun eepitch-yforth () (interactive) (eepitch-comint "yforth" "yforth"))
(defun eepitch-maxima () (interactive) (eepitch-comint "maxima" "maxima"))
(defun eepitch-octave () (interactive) (eepitch-comint "octave" "octave"))
(defun eepitch-R () (interactive)
(eepitch '(with-pager-cat (find-comintprocess "R" "R"))))
(defun eepitch-gs () (interactive) (eepitch-comint "gs" "gs -r45"))
(defun eepitch-gs () (interactive) (eepitch-comint "gs" "gs -r60"))
(defun eepitch-gnuplot () (interactive) (eepitch-comint "gnuplot" "gnuplot"))
(defun eepitch-bsh () (interactive)
(eepitch-de '(find-comintprocess "bsh" "bsh")))
(defun eepitch-scala () (interactive)
(eepitch '(find-comintprocess "scala" "scala")))
(defun eepitch-clojure () (interactive)
(eepitch '(find-comintprocess "clojure" "clojure -r")))
(defun eepitch-mysql () (interactive)
(eepitch '(with-pager-cat '(find-comintprocess "mysql" "mysql -u root"))))
(defun eepitch-gst () (interactive)
(eepitch '(find-comintprocess "gst" "gst")))
(defun eepitch-smjs () (interactive) (eepitch-comint "smjs" "smjs"))
(defun eepitch-mozrepl () (interactive)
(eepitch-comint "mozrepl" "telnet localhost 4242"))
(defun eepitch-luatex () (interactive)
(eepitch-comint-at "/tmp/" "luatex" "luatex"))
(defun eepitch-lualatex () (interactive)
(eepitch-comint-at "/tmp/" "lualatex" "lualatex"))
(defun eepitch-latex () (interactive)
(eepitch-comint-at "/tmp/" "latex" "latex"))
(defun eepitch-tex () (interactive)
(eepitch-comint-at "/tmp/" "tex" "tex"))
(defun eepitch-mf () (interactive)
(eepitch-comint-at "/tmp/" "mf" "mf"))
(defun eepitch-mpost () (interactive)
(eepitch-comint-at "/tmp/" "mpost" "mpost"))
(defun eepitch-pacmd () (interactive) (eepitch-comint "pacmd" "pacmd"))
(defun ee-rcirc-serverbuf (server) (format "*%s*" server))
(defun ee-rcirc-channelbuf (server channel) (format "%s@%s" channel server))
(defun ee-rcirc-connected (server)
(and (get-buffer (ee-rcirc-serverbuf server))
(rcirc-buffer-process (ee-rcirc-serverbuf server))))
(defun ee-rcirc-connect (server channels)
"Connect to an irc server (if not already connected).
TODO: if we are already connected to SERVER, just connect to CHANNELS."
(if (not (ee-rcirc-connected server))
(rcirc-connect server nil nil nil nil channels))
(switch-to-buffer (ee-rcirc-serverbuf server)))
(defun ee-rcirc-sexp (server channel)
`(find-ebuffer ,(ee-rcirc-channelbuf server channel)))
(defun eepitch-kill-rcirc (server)
(message "Not killing: %S" (ee-rcirc-serverbuf server)))
(defun eepitch-rcirc-server (server channels)
"Connect to the irc server SERVER if not already connected, and to CHANNELS."
(interactive)
(eepitch `(ee-rcirc-connect ,server ',channels))
(setq eepitch-kill `(eepitch-kill-rcirc ,server))
(ee-rcirc-sexp server (car channels)))
(defun eepitch-freenode (&optional channels) (interactive)
(eepitch-rcirc-server "irc.freenode.net" (or channels '("#eev"))))
(defun eepitch-ircgnome (&optional channels) (interactive)
(eepitch-rcirc-server "irc.gnome.org" (or channels '("#docs"))))