eev-20141011/eejump.el 0000644 0001750 0001750 00000007240 12213016431 013015 0 ustar edrx edrx ;;; eejump.el -- jump quickly to predefined places.
;; Copyright (C) 2012 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2013sep08
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;;
;; (find-eev-intro)
;; (find-eejump-intro)
;;; Commentary:
;; See: (find-eejump-intro)
;; and: (find-eev "eev-wrap.el" "eewrap-eejump")
;; This module installs a key binding into eev-mode-keymap, so:
(require 'eev-mode) ; (find-eev "eev-mode.el")
(define-key eev-mode-map "\M-j" 'eejump)
(defun eejump (arg)
"See: (find-eejump-intro)"
(interactive "P")
(if (null arg)
(eejump-*)
(if (fboundp (intern (format "eejump-%d" arg)))
(funcall (intern (format "eejump-%d" arg)))
(eejump-str* (format "%d" arg)))))
(defun eejump-str* (str)
"An internal, recursive function used by `eejump'.
See: (find-eejump-intro \"\\neejump\\n\")"
(if (fboundp (intern (format "eejump-%s*" str)))
(funcall (intern (format "eejump-%s*" str)))
(eejump-str* (substring str 0 -1))))
;; This is an "eejump block", as described in:
;; (find-eejump-intro "eejump blocks")
;; You should probably copy this to your .emacs - and
;; then start modifying it.
;;
;; Note that with eev-mode you can use:
;; M-e to follow elisp hyperlinks, see: (find-eval-intro "`M-e'")
;; M-k to go back, see: (find-eval-intro "`M-k'")
;; M-j to jump to predefined places, see: (find-eejump-intro "Families")
;; in particular: M-j --> (find-efunction 'eejump-*)
;; M-2j --> (find-emacs-intro)
;; M-5j --> (find-eev-intro)
;; M-50j --> (find-eev "eev-readme.el")
;;
(defun eejump-* () (find-efunction 'eejump-*))
(defun eejump-1 () (find-fline "~/TODO"))
(defun eejump-10 () (set-frame-font "5x7" t))
(defun eejump-11 () (set-frame-font "6x13" t))
(defun eejump-2 () (find-emacs-intro))
(defun eejump-5* () (find-efunction 'eejump-5*))
(defun eejump-5 () (find-eev-intro))
(defun eejump-50 () (find-eev "eev-readme.el"))
(defun eejump-59 () (find-eev-update-links))
(defun eejump-6 () (find-freenode "#eev"))
(defun eejump-66 () (find-freenode-3a "#eev"))
(defun eejump-55 () (find-fline "~/.emacs"))
(defun eejump-552 () (find-eev "eev2-all.el"))
(defun eejump-555 () (find-eev ""))
(provide 'eejump)
;; To see all current targets, run:
;; (find-eejumps)
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "defun %s "
;; no-byte-compile: t
;; End:
eev-20141011/eepitch.el 0000644 0001750 0001750 00000077752 12207661105 013177 0 ustar edrx edrx ;; eepitch.el - record interactions with shells as readable notes, redo tasks.
;; Copyright (C) 2012 Free Software Foundation, Inc.
;;
;; This file is part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2013aug29
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;;
;; (find-eev-intro)
;; (find-eepitch-intro)
;;; Commentary:
;; This implements a much simpler way to interact with external
;; programs than the one shown in:
;;
;;
;;
;; Quick start guide (note: old!)
;; ==============================
;; Read the first sections of
;;
;; then load this file, with something like:
;; (load-file "eepitch.el")
;; Then in the '( ... ) block below type M-T on the `shell' line to
;; convert it to an "eepitch block", then use `F8's to execute the
;; three red-star lines, then use more `F8's to send the "cd /tmp/"
;; and the "ls" to the shell buffer.
'(
shell
cd /tmp/
ls
)
;; Note that as eepitch.el is still a bit prototype-ish we set two
;; keybindings and a glyph GLOBALLY - search for "set-glyph" and
;; "global-set-key" below.
;;
;;
;; If you are interested in eev
;; ============================
;; The current recommended way to install eev is through the Debian
;; package - see:
;;
;; But this version can be used independently of the rest of eev.
;;
;;
;; My TODO list for eepitch (short and medium term)
;; ================================================
;; The current priorities for eepitch are:
;; 1) Debian packages. There's a quick-and-dirty package, called
;; "eev-puro", that depends on the Debian package for eev and
;; that installs some extra demo scripts; a bunch of students
;; from my university are using that to learn Lua (and *NIX). Its
;; docs are mostly in Portuguese, and they can be found at:
;;
;;
;; The package itself is here:
;;
;; The important thing is that new versions of that .deb are
;; built and uploaded to angg.twu.net by templates similar to the
;; ones in:
;;
;; These templates need to cleaned up and adapted to generate the
;; Debian packages for eev too (and for dednat5, and for
;; blogme4).
;; 2) The support for GUD, SLIME and multi-window settings in
;; general is quite primitive at the moment. Note also that here
;; I do not use any of the "inferior mode" modes of Emacs.
;; That's just because I never learn hot to use them. 8-(
;; 3) The docs in plain text format for eepitch, that are at
;;
;; are ok for the basic ideas but horribly incomplete on
;; everything more advanced.
;; 4) I haven't touched this in years:
;;
;; It has several good parts, I would like to salvage it.
;; 5) All these docs should be converted to texinfo, possibly
;; using blogme4, as in (but this is just a prototype):
;;
;; 6) Understand packages with similar goals and write comparisons:
;; eepitch with org-babel and org-babel-screen, and eev-puro with
;; emacs-starter-kit.
;; 7) Produce short videos about eepitch, like:
;;
;; note that Org has lots of videos, e.g.:
;; Carsten Dominik
;; \ Kurt Schwehr on
;; / org-babel
;;
;;
;; The innards
;; ===========
;; In order to understand precisely how eepitch works (consider this a
;; preliminary hacker's guide!), let's make some definitions and
;; follow a low-level example. I will suppose that you have read
;; enough of
;;
;; to understand how to use eepitch in the most basic cases.
;;
;; Some sexps, like `(shell)', always switch to a buffer with a
;; certain name when executed, and they create a buffer with that name
;; when it does not exist. We call that name the "target buffer name"
;; of the sexp, and, by convention, the cases in which the sexp raises
;; an error do not count. So, for example,
;;
;; sexp target buffer name
;; ---------- ------------------
;; (shell) "*shell*"
;; (shell "foo") "foo"
;; (info "(emacs)") "*info*"
;; (+ 1 2) none/undefined
;; (error) none/undefined
;;
;; A "shell-like sexp" is one that has a target buffer name. So
;; `(shell)' and `(info "(emacs)")' are shell-like sexps, but `(+ 1
;; 2)' is not.
;;
;; Now consider the two Emacs frames below: we start with
;; ___
;; ______________emacs_________|-|X|
;; | | \
;; | (eepitch '(shell))_ | | We will call this the
;; | cd /tmp/ | | "e-script window".
;; | ls | | The point is at the "_".
;; | | | We will type F8 three times.
;; | | |
;; | | |
;; | | |
;; | | /
;; |--:** NOTES (Fundamental) ------| <-- Its modeline.
;; |_________________________________| <-- The minibuffer.
;;
;; then we type F8 three times, and we get:
;; ___
;; ______________emacs_________|-|X|
;; | | \
;; | (eepitch '(shell)) | | Let's call this the
;; | cd /tmp/ | | "e-script window".
;; | ls | | The point is at the "_".
;; | _ | | We just typed F8 three times.
;; | | /
;; |--:** NOTES (Fundamental) ------| <-- Its modeline.
;; | | \
;; | /home/edrx# cd /tmp/ | | Let's call this the
;; | /tmp# ls | | "target window".
;; | ./ ../ foo.txt | |
;; | /tmp# | |
;; | | /
;; |--:** *shell* (Shell:run) ------| <-- Its modeline.
;; |_________________________________| <-- The minibuffer.
;;
;; When we typed F8 on the line " (eepitch '(shell))" the system
;; became "prepared". More precisely:
;; a) `eepitch-code' was set to `(shell)',
;; b) `eepitch-buffer-name' was set to the string "*shell*",
;; c) the buffer "*shell*" was displayed in another window.
;; The actions (b) and (c) were performed by the function
;; `eepitch-prepare'.
;;
;; When we typed F8 on the line "cd /tmp/" the string "cd /tmp/" was
;; "pitched" to the target window, by `(eepitch-line "cd /tmp/")'.
;; Same for the "ls" in the next line. But before pitching each line
;; `eepitch-prepare' was run to make sure that a target window exists.
;;
;; We need more definitions. 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,
;; and we say that the system is "prepared" when (1) and (2) hold,
;; and, besides that,
;; 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'.
;;
;; In the code below,
;; `eepitch-buffer-create' takes care of conditions 1 and 2.
;; `eepitch-assert-not-target', of condition 3.
;; `eepitch-window-show', of condition 4 (supposing 1, 2, 3 hold).
;; `eepitch-prepare', of all the conditions 1-4.
(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)) ; cheap indirection
(defvar eepitch-kill '(eepitch-kill-buffer)) ; cheap indirection
(defvar eepitch-kill-windows 'nil) ; cheap indirection
(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 "") ; so that `eepitch-buffer-exists' will fail
(setq eepitch-window-show ; set the way to set up windows to the
'(eepitch-window-show)) ; default two-window setting
(setq eepitch-kill ; set the behavior of `eepitch-kill'
'(eepitch-kill-buffer)) ; to just kill the target buffer
(eepitch-prepare)
(list 'Target: eepitch-buffer-name)) ; feedback (for and `M-e')
(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)) ; at the end of buffer
(insert line) ; "type" the line
(call-interactively (key-binding "\r"))))) ; then do a RET
(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)))) ; get line contents
(cond ((string-match eepitch-comment-regexp line) ; comment lines
(message "Comment: %s" line)) ; are message'd,
((string-match eepitch-regexp line) ; red star lines
(ee-eval-string-print ; are eval'ed and the
(match-string 1 line))) ; result is printed,
(t (eepitch-prepare) ; normal lines
(eepitch-line line)))) ; are sent
(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) ; kill with few warnings
)))
(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)))
;;; _ _ _ _
;;; ___ ___ _ __ (_) |_ ___| |__ __| | ___
;;; / _ \/ _ \ '_ \| | __/ __| '_ \ _____ / _` |/ _ \
;;; | __/ __/ |_) | | || (__| | | |_____| (_| | (_) |
;;; \___|\___| .__/|_|\__\___|_| |_| \__,_|\___/
;;; |_|
;;
(defun eepitch-make-suffix (arg)
(cond ((null arg) "")
((stringp arg) (format " %s" arg))
((numberp arg) (format " (%s)" arg))))
(defun eepitch-do (program-and-args &optional suffix)
(eepitch-comint (format "%s%s" (ee-unsplit program-and-args)
(eepitch-make-suffix suffix))
program-and-args))
;;; _ _
;;; __ _| |_ _ _ __ | |__ ___
;;; / _` | | | | | '_ \| '_ \/ __|
;;; | (_| | | |_| | |_) | | | \__ \
;;; \__, |_|\__, | .__/|_| |_|___/
;;; |___/ |___/|_|
;;;
;; More glyphs:
;; (find-eev "eev-anchors.el")
;; (find-anchors-intro)
;; More on glyphs:
;; http://angg.twu.net/glyphs.html
;; The `(<= 128 pos)' below is explained at:
;; http://angg.twu.net/glyphs.html#bug-report
(defface eepitch-star-face
'((t (:foreground "red")))
"Face used for the red star glyph (char 15).")
(defun eepitch-set-glyph0 (pos &optional char face)
"See: (find-eepitch-intro \"glyph\")"
(aset standard-display-table pos
(if char (vector (make-glyph-code char face)))))
(defun eepitch-set-glyph (pos &optional char face)
"See: (find-eepitch-intro \"glyph\")
and: (find-anchors-intro \"glyphs\")
This is the high-level version of `eepitch-set-glyph0', with a hack
to make it work similarly in unibyte and multibyte buffers."
(eepitch-set-glyph0 pos char face)
(if (<= 128 pos)
(eepitch-set-glyph0 (make-char 'eight-bit pos) char face)))
;;;
;;; __ ___ __ __ _ _ __
;;; \ \ /\ / / '__/ _` | '_ \
;;; \ V V /| | | (_| | |_) |
;;; \_/\_/ |_| \__,_| .__/
;;; |_|
;;
;; See: (find-wrap-intro)
(defun ee-no-properties (str)
(setq str (copy-sequence str))
(set-text-properties 0 (length str) nil str)
str)
;; (defun eepitch-delete-and-extract-line ()
;; (delete-and-extract-region (ee-bol) (ee-eol)))
(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)
;;; _ _
;;; ___ ___| |_ | | _____ _ _ ___
;;; / __|/ _ \ __| | |/ / _ \ | | / __|
;;; \__ \ __/ |_ | < __/ |_| \__ \
;;; |___/\___|\__| |_|\_\___|\__, |___/
;;; |___/
;; (global-set-key [f8] 'eepitch-this-line)
;; (global-set-key "\M-T" 'eewrap-eepitch)
(provide 'eepitch)
;;; _____ _ __ _ _
;;; | ____|_ __ __| | ___ / _| | |_| |__ ___ ___ ___ _ __ ___
;;; | _| | '_ \ / _` | / _ \| |_ | __| '_ \ / _ \ / __/ _ \| '__/ _ \
;;; | |___| | | | (_| | | (_) | _| | |_| | | | __/ | (_| (_) | | | __/
;;; |_____|_| |_|\__,_| \___/|_| \__|_| |_|\___| \___\___/|_| \___|
;;;
;;; ----------------------------------------------------------------------
;;; ----------------------------------------------------------------------
;;; ----------------------------------------------------------------------
;;; _ _ _
;;; ___ ___ _ __ ___ (_)_ __ | |_ ___ ___| |__ ___
;;; / __/ _ \| '_ ` _ \| | '_ \| __|____ / _ \/ __| '_ \ / _ \
;;; | (_| (_) | | | | | | | | | | ||_____| __/ (__| | | | (_) |
;;; \___\___/|_| |_| |_|_|_| |_|\__| \___|\___|_| |_|\___/
;;;
;; What is this: I am trying to find an elegant way to deal with
;; programs that echo their input (like zsh)... This is still a bit
;; experimental!
;; See: (find-variable 'comint-process-echoes)
;; To do: send an e-mail to Olin Shivers about echoing and stty.
(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)))
;;; ___ _ _ _ _
;;; / _ \| |_| |__ ___ _ __ | |_ ___ ___ | |___
;;; | | | | __| '_ \ / _ \ '__| | __/ _ \ / _ \| / __|
;;; | |_| | |_| | | | __/ | | || (_) | (_) | \__ \
;;; \___/ \__|_| |_|\___|_| \__\___/ \___/|_|___/
;;;
;; Useful for controlling certain external programs.
(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)))
;;; _
;;; | | __ _ _ __ __ _ _ _ __ _ __ _ ___ ___
;;; | | / _` | '_ \ / _` | | | |/ _` |/ _` |/ _ \/ __|
;;; | |__| (_| | | | | (_| | |_| | (_| | (_| | __/\__ \
;;; |_____\__,_|_| |_|\__, |\__,_|\__,_|\__, |\___||___/
;;; |___/ |___/
;; Shells
(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"))
;; Main interpreted languages
(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"))
;; Tcl
(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"))
;; Lisps and Schemes
;; It would be better to run them in Slime.
(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-racket () (interactive) (eepitch-comint "racket" "racket"))
(defun eepitch-mitscheme () (interactive)
(eepitch-comint "mit-scheme" "mit-scheme"))
(defun eepitch-tinyscheme () (interactive)
(eepitch-comint "tinyscheme" "tinyscheme"))
;; Haskell, ML, Erlang, Coq
(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"))
;; Forth
(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"))
;; Mathematics
(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"))))
;; Plotters.
;; We force GhostScript's resolution to make its window fit on the screen.
(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"))
;; Java-based languages
(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")))
;; SQL. To do: add postgres and sqlite
(defun eepitch-mysql () (interactive)
(eepitch '(with-pager-cat '(find-comintprocess "mysql" "mysql -u root"))))
;; SmallTalk
(defun eepitch-gst () (interactive)
(eepitch '(find-comintprocess "gst" "gst")))
;; JavaScript
;; MozRepl is a Javascript REPL in a running Mozilla browser.
;; See: https://github.com/bard/mozrepl/wiki/tutorial
(defun eepitch-smjs () (interactive) (eepitch-comint "smjs" "smjs"))
(defun eepitch-mozrepl () (interactive)
(eepitch-comint "mozrepl" "telnet localhost 4242"))
;; Programs from the TeX family.
;; They create logfiles in the current dir, so we run them in /tmp/.
(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"))
;; Pulseaudio (this is to interact with its daemon)
(defun eepitch-pacmd () (interactive) (eepitch-comint "pacmd" "pacmd"))
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "defun %s "
;; no-byte-compile: t
;; End:
eev-20141011/eev-anchors.el 0000644 0001750 0001750 00000012467 12067745420 013767 0 ustar edrx edrx ;;; eev-anchors.el -- hyperlinks to anchors.
;; Copyright (C) 2012 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2012nov02
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;;
;; (find-eev-intro)
;; (find-anchors-intro)
;;; Commentary:
(require 'eepitch) ; (find-eev "eepitch.el")
;;; _ _
;;; __ _| |_ _ _ __ | |__ ___
;;; / _` | | | | | '_ \| '_ \/ __|
;;; | (_| | | |_| | |_) | | | \__ \
;;; \__, |_|\__, | .__/|_| |_|___/
;;; |___/ |___/|_|
(defface eev-glyph-face-green
'((((class color) (background dark))
(:foreground "green"))
(((class color) (background light))
(:foreground "forest green"))
(t (:bold t)))
"Face used for the green glyphs (`<<' and `>>', chars 171 and 187).")
;; (eepitch-set-glyph ?« ?« 'eev-glyph-face-green)
;; (eepitch-set-glyph ?» ?» 'eev-glyph-face-green)
(eepitch-set-glyph 171 171 'eev-glyph-face-green)
(eepitch-set-glyph 187 187 'eev-glyph-face-green)
;;; _ __ _
;;; __ _ _ __ ___| |__ ___ _ __ / _| ___ _ __ _ __ ___ __ _| |_
;;; / _` | '_ \ / __| '_ \ / _ \| '__|____| |_ / _ \| '__| '_ ` _ \ / _` | __|
;;; | (_| | | | | (__| | | | (_) | | |_____| _| (_) | | | | | | | | (_| | |_
;;; \__,_|_| |_|\___|_| |_|\___/|_| |_| \___/|_| |_| |_| |_|\__,_|\__|
;;;
(defvar ee-anchor-format "«%s»" "See `ee-goto-anchor'.")
(put 'ee-anchor-format 'safe-local-variable 'stringp)
;; A paranoid setting would be:
;; (defvar ee-anchor-format nil "See `ee-goto-anchor'.")
(defun ee-format-as-anchor (tag)
"Convert TAG into an anchor using `ee-anchor-format'."
(if ee-anchor-format
(format ee-anchor-format tag)
(error "`ee-anchor-format' is nil - can't convert string to anchor")))
;;; __ _ _ _
;;; / _(_)_ __ __| | __ _ _ __ ___| |__ ___ _ __
;;; | |_| | '_ \ / _` |_____ / _` | '_ \ / __| '_ \ / _ \| '__|
;;; | _| | | | | (_| |_____| (_| | | | | (__| | | | (_) | |
;;; |_| |_|_| |_|\__,_| \__,_|_| |_|\___|_| |_|\___/|_|
;;;
;; See: (find-eval-intro "Anchors and pages")
(defun ee-goto-anchor (&optional tag &rest rest)
"Like `ee-goto-position', but TAG is converted to an anchor.
If the anchor obtained from TAG is not found then issue an error
but do not move point.
For example, if `ee-anchor-format' is \"<<%s>>\" then
(ee-goto-anchor \"foo\" \"bar\")
searches for the first occurrence of \"<>\" in the current
buffer, then for the first occurrence of \"bar\" after that. If
\"<>\" is not found then do not move point.
It is good style to set `ee-goto-anchor' globally to nil and only
use anchors in files where `ee-anchor-format' is declared in the
local variables section of the file; see:
(find-node \"(emacs)File Variables\")
(find-node \"(emacs)Specifying File Variables\")
a hint: one way of forcing reloading the local variables by hand
is by running `\\[normal-mode]'.
The glyphs defined in (find-eev \"eev-glyphs.el\") can be used to
make anchors using characters that stand out."
(if tag (goto-char
(save-excursion
(goto-char (point-min))
(search-forward (ee-format-as-anchor tag))
(point))))
(ee-goto-rest rest))
(defun find-anchor (fname &optional tag &rest pos-spec-list)
"Like `find-fline', but TAG is converted to an anchor if not nil.
See `ee-goto-anchor'."
(find-fline fname)
(apply 'ee-goto-anchor tag pos-spec-list))
;;; _
;;; | |_ ___
;;; | __/ _ \
;;; | || (_) |
;;; \__\___/
;;;
;; Warning: this function does not start with any of the
;; reserved prefixes!!! =(
;;
(defun to (tag &rest pos-spec-list)
"Like `find-anchor', but does not switch to another buffer or file."
(interactive "sAnchor: ")
(apply 'ee-goto-anchor tag pos-spec-list))
(provide 'eev-anchors)
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "«%s»"
;; ee-anchor-format: "defun %s "
;; no-byte-compile: t
;; End:
eev-20141011/eev-audiovideo.el 0000644 0001750 0001750 00000027423 12230300050 014432 0 ustar edrx edrx ;;; eev-audiovideo.el -- elisp hyperlinks to audio and video files.
;; Copyright (C) 2013 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2013oct18
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;;
;; (find-audiovideo-intro)
;;; Commentary:
(require 'eev-code)
(require 'eev-brxxx)
;; (find-efunction 'ee-stuff-around-point)
;; (find-elnode "Regexp Search")
;; (find-elnode "Regexp Backslash" "shy group")
;;
(defun ee-time-around-point ()
(let ((time (ee-no-properties (ee-stuff-around-point "0-9:"))))
(if (not (equal time ""))
time)))
;;; _ _ __ _ _
;;; | |_(_)_ __ ___ ___ / _|_ __ ___ _ __ ___ | |__ ___ | |
;;; | __| | '_ ` _ \ / _ \_____| |_| '__/ _ \| '_ ` _ \ _____| '_ \ / _ \| |
;;; | |_| | | | | | | __/_____| _| | | (_) | | | | | |_____| |_) | (_) | |
;;; \__|_|_| |_| |_|\___| |_| |_| \___/|_| |_| |_| |_.__/ \___/|_|
;;;
(defvar ee-time-regexp
"\\(?:\\([0-9]?[0-9]\\):\\)?\\([0-9]?[0-9]\\):\\([0-9][0-9]\\)")
(defun ee-re-search-from (pos regexp &optional limit repeat)
(save-excursion
(if pos (goto-char pos))
(if (re-search-forward regexp limit t repeat)
(match-string-no-properties 0))))
(defun ee-time-from-bol ()
"Try this: 98:76:54 3:21 (ee-time-from-bol)"
(ee-re-search-from (ee-bol) ee-time-regexp (ee-eol)))
(defun ee-time-from-bol-flash () (interactive)
"Try this: 98:76:54 3:21 (ee-time-from-bol-flash)"
(if (ee-time-from-bol)
(eeflash+ (match-beginning 0) (match-end 0) ee-highlight-spec))
(ee-time-from-bol))
;;; _ _ _ _ __ _
;;; | |_(_)_ __ ___ ___ ___| |__ (_)/ _| |_
;;; | __| | '_ ` _ \ / _ \_____/ __| '_ \| | |_| __|
;;; | |_| | | | | | | __/_____\__ \ | | | | _| |_
;;; \__|_|_| |_| |_|\___| |___/_| |_|_|_| \__|
;;;
(defun ee-time-to-seconds (time)
(save-match-data
(if (string-match ee-time-regexp time)
(+ (* 3600 (string-to-number (or (match-string 1 time) "0")))
(* 60 (string-to-number (match-string 2 time)))
(string-to-number (match-string 3 time))))))
(defun ee-seconds-to-time (seconds)
(if (> 3600 seconds)
(format-seconds "%m:%02s" seconds)
(format-seconds "%h:%02m:%02s" seconds)))
(defun ee-time+ (seconds time)
(save-match-data
(ee-seconds-to-time
(max 0 (+ seconds (ee-time-to-seconds time))))))
(defun ee-time-from-bol-shift (seconds)
(interactive "P")
(save-excursion
(let ((time (ee-time-from-bol)))
(if time
(replace-match (ee-time+ (or seconds 1) time) t t)
(error "No time (mm:ss or hh:mm:ss) in the current line")))))
(defun ee-time-from-bol-shift- (seconds)
(interactive "P")
(ee-time-from-bol-shift (- (or seconds 1))))
;;; _ _ _ _ __ _ _
;;; | | __ _ ___| |_ __ _ _ _ __| (_) ___ / /_ _(_) __| | ___ ___
;;; | |/ _` / __| __| / _` | | | |/ _` | |/ _ \ / /\ \ / / |/ _` |/ _ \/ _ \
;;; | | (_| \__ \ |_ | (_| | |_| | (_| | | (_) / / \ V /| | (_| | __/ (_) |
;;; |_|\__,_|___/\__| \__,_|\__,_|\__,_|_|\___/_/ \_/ |_|\__,_|\___|\___/
;;;
;;
(defvar ee-audiovideo-last nil
"See: (find-audiovideo-intro \"The current audio or video\")")
(defun ee-audiovideo-sexp (time)
(list ee-audiovideo-last time))
;;; _ _ _
;;; __ _ __ __ __ _ __| |(_) _ __ ___ ___ __| | ___
;;; / _` |____\ \ / /____ / _` |/ _` || |_____| '_ ` _ \ / _ \ / _` |/ _ \
;;; | (_| |_____\ V /_____| (_| | (_| || |_____| | | | | | (_) | (_| | __/
;;; \__,_| \_/ \__,_|\__,_|/ | |_| |_| |_|\___/ \__,_|\___|
;;; |__/
;;
(defun ee-time-from-bol-rerun (&optional arg)
"Play the current audio or video starting at '(ee-time-from-bol)'.
With a prefix of 0 just display what would be done. See:
(find-audiovideo-intro \"time-from-bol\")
(find-audiovideo-intro \"ee-audiovideo-last\")"
(interactive "P")
(cond ((eq arg 0)
(message "-> %S" (ee-audiovideo-sexp (ee-time-from-bol-flash))))
(t (let ((sexp (ee-audiovideo-sexp (ee-time-from-bol))))
(eval sexp)
(message "%S" sexp)))))
(setq eev-avadj-mode-map (make-sparse-keymap))
(define-key eev-avadj-mode-map "\M--" 'ee-time-from-bol-shift-)
(define-key eev-avadj-mode-map "\M-=" 'ee-time-from-bol-shift)
(define-key eev-avadj-mode-map "\M-+" 'ee-time-from-bol-shift)
(define-key eev-avadj-mode-map "\M-p" 'ee-time-from-bol-rerun)
(define-minor-mode eev-avadj-mode
"eev audio/video adjust mode: a mode for adjusting audio/video link lines.
See: (find-audiovideo-intro \"`eev-avadj-mode'\")"
:init-value nil
:global nil
:lighter " eev-avadj")
;; (eev-avadj-mode 0)
;; (eev-avadj-mode 1)
;; 1:15 foo
;; (find-eev "eev-mode.el")
;; (find-code-video "thecompanyofwolves" "/sda5/torrents/The_Company_of_Wolves/The_Company_Of_Wolves.avi")
;; (code-video "thecompanyofwolves" "/sda5/torrents/The_Company_of_Wolves/The_Company_Of_Wolves.avi")
;; 0:00 (ee-time-from-bol-shift -100)
;; 0:00 (ee-time-from-bol-shift -10)
;; 1:23 (if (ee-time-from-bol) (replace-match "abcd" t t))
;; 1:23 (if (ee-time-from-bol) (save-excursion (replace-match "abcd" t t)))
;; Ideally `M-1 M-x find-chomskyvideo' should use `ee-time-from-bol'...
;; (find-elnode "Index" "* replace-match:")
;;; _ _ _
;;; ___ ___ __| | ___ __ _(_) __| | ___ ___
;;; / __/ _ \ / _` |/ _ \____\ \ / / |/ _` |/ _ \/ _ \
;;; | (_| (_) | (_| | __/_____\ V /| | (_| | __/ (_) |
;;; \___\___/ \__,_|\___| \_/ |_|\__,_|\___|\___/
;;;
;; mplayer for video files
;;
(defun find-mplayer (fname &optional pos &rest rest)
"Open FNAME with mplayer, with a GUI (in fullscreen mode, for video files)."
(interactive "sFile name: ")
(find-bgprocess (ee-find-mplayer fname pos)))
(defvar ee-mplayer-options '("-fs" "-osdlevel" "2" "-zoom"))
(defun ee-mplayer-video-options () ee-mplayer-options)
(defun ee-find-mplayer (fname &optional pos &rest rest)
`("mplayer"
,fname
,@(if pos `("-ss" ,(ee-secs-to-mm:ss pos)))
,@(ee-mplayer-video-options)
))
(defun code-mplayer (c fname)
(eval (ee-read (ee-code-mplayer c fname))))
(defun find-code-mplayer (c fname)
(find-estring-elisp (ee-code-mplayer c fname)))
(defun ee-code-mplayer (c fname)
(ee-template0 "\
;; {(ee-S `(find-code-mplayer ,c ,fname))}
;;
(defun find-{c} (&optional time &rest rest)
(interactive (list (ee-time-around-point)))
(setq ee-audiovideo-last 'find-{c})
(if (eq time t)
\"Just setting the default video\"
(find-mplayer {(ee-S fname)} time)))
"))
(defalias 'find-video 'find-mplayer)
(defalias 'code-video 'code-mplayer)
(defalias 'find-code-video 'find-code-mplayer)
;; (find-code-brfile 'find-video :local 'brvideol :dired 'brvideod)
(code-brfile 'find-video :local 'brvideol :dired 'brvideod)
;;; _ _ _
;;; ___ ___ __| | ___ __ _ _ _ __| (_) ___
;;; / __/ _ \ / _` |/ _ \_____ / _` | | | |/ _` | |/ _ \
;;; | (_| (_) | (_| | __/_____| (_| | |_| | (_| | | (_) |
;;; \___\___/ \__,_|\___| \__,_|\__,_|\__,_|_|\___/
;; mplayer in an xterm, for audio files
;;
(defvar ee-termplayer-term-options '("xterm" "-geometry" "+200+100" "-e"))
(defvar ee-termplayer-options ())
(defun ee-mplayer-audio-options () ee-termplayer-options)
(defun ee-find-termplayer (fname &optional pos &rest rest)
`(,@ee-termplayer-term-options
"mplayer"
,fname
,@(if pos `("-ss" ,(ee-secs-to-mm:ss pos)))
,@(ee-mplayer-audio-options)
))
(defun find-termplayer (fname &optional pos &rest rest)
"Open FNAME with mplayer, without a GUI (in a terminal - for audio files)."
(interactive "sFile name: ")
(find-bgprocess (ee-find-termplayer fname pos)))
(defun code-termplayer (c fname)
(eval (ee-read (ee-code-termplayer c fname))))
(defun find-code-termplayer (c fname)
(find-estring-elisp (ee-code-termplayer c fname)))
(defun ee-code-termplayer (c fname)
(ee-template0 "\
;; {(ee-S `(find-code-termplayer ,c ,fname))}
;;
(defun find-{c} (&optional time &rest rest)
(interactive (list (ee-time-around-point)))
(setq ee-audiovideo-last 'find-{c})
(if (eq time t)
\"Just setting the default audio\"
(find-termplayer {(ee-S fname)} time)))
"))
(defalias 'find-audio 'find-termplayer)
(defalias 'code-audio 'code-termplayer)
(defalias 'find-code-audio 'find-code-termplayer)
;; (find-code-brfile 'find-audio :local 'braudiol :dired 'braudiod)
(code-brfile 'find-audio :local 'braudiol :dired 'braudiod)
(provide 'eev-audiovideo)
;; Garbage?
;;;
;;; _ __ ___ _ __ ___ _ ___ ___
;;; | '_ ` _ \| '_ ` _ \(_) __/ __|
;;; | | | | | | | | | | |_\__ \__ \
;;; |_| |_| |_|_| |_| |_(_)___/___/
;;;
;; Convert between a number of seconds (a number)
;; and a "minutes:seconds" thing (a string)
;;
(defun ee-secs-to-mm:ss (n)
"Force N - a number of seconds or an \"mm:ss\" string - to the mm:ss format"
(if (stringp n) n
(let* ((s (mod n 60))
(m (/ (- n s) 60)))
(format "%d:%02d" m s))))
(defun ee-mm:ss-to-secs (mm:ss)
"Force MM:SS - a string or a number of seconds - to a number of seconds"
(if (numberp mm:ss) mm:ss
(let* ((ms (mapcar 'string-to-number (split-string mm:ss ":"))))
(+ (* 60 (car ms)) (cadr ms)))))
;;; _ _
;;; | |_(_)_ __ ___ ___ _ __ ___ __ _ _____ ___ __
;;; | __| | '_ ` _ \ / _ \_____| '__/ _ \/ _` |/ _ \ \/ / '_ \
;;; | |_| | | | | | | __/_____| | | __/ (_| | __/> <| |_) |
;;; \__|_|_| |_| |_|\___| |_| \___|\__, |\___/_/\_\ .__/
;;; |___/ |_|
;;
;; (find-elnode "Time Parsing")
;; (seconds-to-time 4000)
;; (float-time '(0 4000 0))
;; (format-seconds "%h:%m:%s" 4000)
;; (format-seconds "%h:%02m:%02s" 4000)
;; (ee-seconds-to-time 260)
;; (ee-seconds-to-time 4000)
;; (ee-time-to-seconds "4:20")
;; (date-to-time "2:30")
;; (string-to-number "")
;; (ee-time+ 40 "4:20")
;; (ee-time+ -1000 "4:20")
;;
;; (defvar ee-time-regexp "[0-9]?[0-9]:[0-9][0-9]\\(:[0-9][0-9]\\)?")
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "«%s»"
;; ee-anchor-format: "defun %s "
;; no-byte-compile: t
;; End:
eev-20141011/eev-blinks.el 0000644 0001750 0001750 00000075343 12415657516 013623 0 ustar edrx edrx ;;; eev-blinks.el -- support for basic hyperlinks in Emacs.
;;; The basic hyperlinks are the ones that do not depend on templates,
;;; and that are not created by `code-c-d' and friends.
;; Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,
;; 2009,2010,2011,2012,2013,2014 Free Software Foundation, Inc.
;;
;; This file is (not yet) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2014oct10
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;; (find-eev-intro)
;;; Commentary:
;; «.eek» (to "eek")
;; «.ee-goto-position» (to "ee-goto-position")
;; «.ee-goto-rest» (to "ee-goto-rest")
;; «.find-fline» (to "find-fline")
;; «.find-wottb» (to "find-wottb")
;; «.find-ebufferandpos» (to "find-ebufferandpos")
;; «.find-ebuffer» (to "find-ebuffer")
;; «.find-eoutput» (to "find-eoutput")
;; «.find-estring» (to "find-estring")
;; «.find-sh» (to "find-sh")
;; «.find-man» (to "find-man")
;; «.find-w3m» (to "find-w3m")
;; «.find-Package» (to "find-Package")
;; «.find-epp» (to "find-epp")
;; «.find-einternals» (to "find-einternals")
(defvar ee-buffer-name nil) ; overridden by `let's
;; (find-efunction 'ee-find-tag)
;;; _ _ _
;;; __ _ _ _| |_ ___ | | ___ __ _ __| |___
;;; / _` | | | | __/ _ \| |/ _ \ / _` |/ _` / __|
;;; | (_| | |_| | || (_) | | (_) | (_| | (_| \__ \
;;; \__,_|\__,_|\__\___/|_|\___/ \__,_|\__,_|___/
;;;
;;; autoloads for external functions
;; (find-elnode "Autoload")
;;
(autoload 'find-function-read "find-func")
(autoload 'pp-to-string "pp")
(autoload 'Man-fontify-manpage "man" nil t)
(autoload 'word-at-point "thingatpt")
(autoload 'list-iso-charset-chars "mule-diag")
(autoload 'list-non-iso-charset-chars "mule-diag")
(autoload 'customize-read-group "cus-edit")
(autoload 'custom-unlispify-tag-name "cus-edit")
;;; _
;;; ___ ___| | __
;;; / _ \/ _ \ |/ /
;;; | __/ __/ <
;;; \___|\___|_|\_\
;;;
;; «eek» (to ".eek")
(defun eek (str) (interactive "sKeys: ")
"Execute STR as a keyboard macro. See `edmacro-mode' for the exact format.\n
An example: (eek \"C-x 4 C-h\")"
(execute-kbd-macro (read-kbd-macro str)))
;;; _ _ _
;;; _ __ ___ ___ ___ _ __ ___ ___ | (_)___| |_ ___
;;; | '_ \ / _ \/ __| ___ / __| '_ \ / _ \/ __|___| | / __| __/ __|
;;; | |_) | (_) \__ \|___|\__ \ |_) | __/ (__|___| | \__ \ |_\__ \
;;; | .__/ \___/|___/ |___/ .__/ \___|\___| |_|_|___/\__|___/
;;; |_| |_|
;;;
;; «ee-goto-position» (to ".ee-goto-position")
;; support for pos-spec-lists in hyperlinks
;; See: (find-eval-intro "Refining hyperlinks")
(defun ee-goto-position (&optional pos-spec &rest rest)
"Process the \"absolute pos-spec-lists\" arguments in hyperlink functions.
POS-SPEC, the first element of a pos-spec-list, is treated
specially; if it is a string then jump to the first occurrence of
that string in the buffer, and if it a number jump to the line
with that number in the buffer; if it is nil, do nothing.
The rest of the pos-spec-list, REST, is treated by
`ee-goto-rest'.
Many kinds of hyperlinks - for example,
(find-efunction 'ee-goto-position)
already jump to specific positions of a buffer; those hyperlink
functions support \"relative pos-spec-lists\", and they invoke
`ee-goto-rest' straight away to handle their pos-spec-lists -
they skip the first \"absolute\" pos-spec."
(when pos-spec
(cond ((numberp pos-spec)
(goto-char (point-min))
(forward-line (1- pos-spec)))
((stringp pos-spec)
(goto-char (save-excursion ; This used to be just:
(goto-char (point-min)) ; (goto-char (point-min))
(search-forward pos-spec) ; (search-forward pos-spec)
(point)))) ;
(t (error "This is not a valid pos-spec: %S" pos-spec)))
(if rest (ee-goto-rest rest))))
;; «ee-goto-rest» (to ".ee-goto-rest")
(defun ee-goto-rest (list)
"Process \"relative pos-spec-lists\".
For each element in LIST, if it is:
a string -> jump to the next occurrence of that string in the
current buffer
a number -> go down that many lines
a list -> evaluate the list (take care!)
anything else generates an error - but users are encouraged to
create their own extended versions of this function and override
the standard definition."
(cond ((null list))
((stringp (car list))
(search-forward (car list))
(ee-goto-rest (cdr list)))
((numberp (car list))
(forward-line (car list))
(ee-goto-rest (cdr list)))
((consp (car list))
(eval (car list))
(ee-goto-rest (cdr list)))
(t (error "Not a valid pos-spec item: %S" (car list)))))
;;; __ _ _ __ _ _
;;; / _(_)_ __ __| | / _| (_)_ __ ___
;;; | |_| | '_ \ / _` |_____| |_| | | '_ \ / _ \
;;; | _| | | | | (_| |_____| _| | | | | | __/
;;; |_| |_|_| |_|\__,_| |_| |_|_|_| |_|\___|
;;; __ _ _ _
;;; / _(_)_ __ __| | _ __ ___ __| | ___
;;; | |_| | '_ \ / _` |_____| '_ \ / _ \ / _` |/ _ \
;;; | _| | | | | (_| |_____| | | | (_) | (_| | __/
;;; |_| |_|_| |_|\__,_| |_| |_|\___/ \__,_|\___|
;;;
;; «find-fline» (to ".find-fline")
;;; Basic links: find-fline and find-node
;; Tests:
;; (find-fline "~/")
;; (find-node "(emacs)Top")
(defun find-fline (fname &rest pos-spec-list)
"Hyperlink to a file (or a directory).
This function is similar to `find-file' but it supports a
\"pos-spec-list\" - see `ee-goto-position'.
Examples:\n
(find-file \"~/.emacs\")
(find-fline \"~/.emacs\")
(find-fline \"~/.emacs\" \"Beginning of the eev block\")"
(find-file (ee-expand fname))
(apply 'ee-goto-position pos-spec-list))
(defun find-fline-gz (fname &rest pos-spec-list)
"Like `find-fline', but also tries \"FNAME.gz\" if \"FNAME\" does not exist."
(let* ((efname (ee-expand fname))
(efnamegz (concat efname ".gz")))
(if (and (not (file-exists-p efname))
(file-exists-p efnamegz))
(apply 'find-fline efnamegz pos-spec-list)
(apply 'find-fline efname pos-spec-list))))
(defun find-node (nodestr &rest pos-spec-list)
"Hyperlink to an info page.
This function is similar to `info' but it supports a
\"pos-spec-list\" - see `ee-goto-position'.
Examples:\n
(info \"(emacs)Lisp Eval\")
(find-node \"(emacs)Lisp Eval\" \"C-x C-e\")"
(info nodestr)
(apply 'ee-goto-position pos-spec-list))
;;; __ _ _ _ _ _
;;; / _(_)_ __ __| | __ _____ | |_| |_| |__
;;; | |_| | '_ \ / _` |____\ \ /\ / / _ \| __| __| '_ \
;;; | _| | | | | (_| |_____\ V V / (_) | |_| |_| |_) |
;;; |_| |_|_| |_|\__,_| \_/\_/ \___/ \__|\__|_.__/
;;;
;; «find-wottb» (to ".find-wottb")
;;; hyperlinks to the output of Emacs's help-like functions
;; Tests:
;; (find-efunctiondescr 'next-line "line-move-visual")
;; (find-ekeydescr [down] "line-move-visual")
;; (find-evariabledescr 'line-move-visual "visual lines")
;; (find-efunctiond 'next-line "next-line-add-newlines")
;; (find-eapropos "^find-.*-links" "find-intro-links")
;; (find-ecolors " white")
;; (find-efacedescr 'default "Foreground:")
;; (find-efaces "default")
(defun find-wottb-call (sexp bufname &rest pos-spec-list)
"Hyperlink to functions that call `with-output-to-temp-buffer'.
First evaluate SEXP with a trick to not let it split the current window,
then switch to the buffer that it created (it must be called BUFNAME),
then go to the position specified by POS-SPEC-LIST.\n
\(This is a horrible hack.)"
(let ((same-window-buffer-names
(cons bufname same-window-buffer-names)))
(eval sexp))
(set-buffer bufname) ; why is this needed?
(apply 'ee-goto-position pos-spec-list))
(defun find-eapropos (regexp &rest pos-spec-list)
"Hyperlink to the result of running `apropos' on REGEXP."
(interactive "sApropos symbol (regexp): ")
(apply 'find-wottb-call '(apropos regexp) "*Apropos*" pos-spec-list))
(defun find-efunctiondescr (symbol &rest pos-spec-list)
"Hyperlink to the result of running `describe-function' on SYMBOL."
(interactive (find-function-read))
(apply 'find-wottb-call '(describe-function symbol) "*Help*" pos-spec-list))
(defun find-evariabledescr (symbol &rest pos-spec-list)
"Hyperlink to the result of running `describe-variable' on SYMBOL."
(interactive (find-function-read 'variable))
(apply 'find-wottb-call '(describe-variable symbol) "*Help*" pos-spec-list))
(defalias 'find-evardescr 'find-evariabledescr)
(defun find-ekeydescr (key &rest pos-spec-list)
"Hyperlink to the result of running `describe-key' on KEY."
(interactive "kFind function on key: ")
(apply 'find-wottb-call '(describe-key key) "*Help*" pos-spec-list))
(defun find-echardescr (&optional pos &rest pos-spec-list)
"Hyperlink to the result of running `describe-char' at POS."
(interactive)
(setq pos (or pos (point)))
(apply 'find-wottb-call '(describe-char pos) "*Help*" pos-spec-list))
(defun find-etpat (&optional pos &rest pos-spec-list)
"Hyperlink to the result of running `describe-text-properties' at point.
See `find-etpat0' and `find-etpat00' for lower-level tools for
inspecting text proprties."
(interactive)
(setq pos (or pos (point)))
(apply 'find-wottb-call '(describe-text-properties pos)
"*Help*" pos-spec-list))
(defun find-efacedescr (&optional face &rest pos-spec-list)
"Hyperlink to the result of running `describe-face' on FACE."
;; (interactive (list (read-face-name "Describe face")))
(interactive (list (face-at-point)))
(apply 'find-wottb-call '(describe-face face) "*Help*" pos-spec-list))
(defun find-efaces (&rest pos-spec-list)
"Hyperlink to the result of running `list-faces-display'."
(interactive)
(apply 'find-wottb-call '(list-faces-display) "*Faces*" pos-spec-list))
(defun find-ecolors (&rest pos-spec-list)
"Hyperlink to the result of running `list-colors-display'."
(interactive)
(apply 'find-wottb-call '(list-colors-display) "*Colors*" pos-spec-list))
(defun find-efunctiond (function &rest pos-spec-list)
"Hyperlink to the result of running `disassemble' on FUNCTION."
(interactive (find-function-read))
(apply 'find-wottb-call '(disassemble function) "*Disassemble*"
pos-spec-list))
;; New, 2013sep21
;;
(defun find-etp (&rest pos-spec-list)
"Hyperlink to the output of `describe-text-properties'.
This is a high-level alternative to `find-etpat'."
(interactive)
(apply 'find-wottb-call '(describe-text-properties (point))
"*Help*" pos-spec-list))
(defun find-epackages (&optional no-fetch &rest pos-spec-list)
"Hyperlink to the output of `list-packages'."
(interactive "P")
(apply 'find-wottb-call '(list-packages no-fetch)
"*Packages*" pos-spec-list))
(defun find-epackage (&optional pkg-desc &rest pos-spec-list)
"Hyperlink to the output of `describe-package'."
(interactive "P")
(apply 'find-wottb-call '(describe-package pkg-desc)
"*Help*" pos-spec-list))
(defun find-customizegroup (group &rest pos-spec-list)
"Hyperlink to the result of running `customize-group' on GROUP."
(interactive (list (customize-read-group)))
(when (stringp group)
(if (string-equal "" group)
(setq group 'emacs)
(setq group (intern group))))
(apply 'find-wottb-call '(customize-group group)
(format "*Customize Group: %s*" (custom-unlispify-tag-name group))
pos-spec-list))
;;; __ _ _ __ _ _
;;; / _(_)_ __ __| | ___ / _|_ _ _ __ ___| |_(_) ___ _ __
;;; | |_| | '_ \ / _` |____ / _ \ |_| | | | '_ \ / __| __| |/ _ \| '_ \
;;; | _| | | | | (_| |____| __/ _| |_| | | | | (__| |_| | (_) | | | |
;;; |_| |_|_| |_|\__,_| \___|_| \__,_|_| |_|\___|\__|_|\___/|_| |_|
;;;
;; «find-ebufferandpos» (to ".find-ebufferandpos")
;;; hyperlinks to the source code of Emacs functions and variables
;; Tests:
;; (find-efunction 'next-line)
;; (find-evariable 'line-move-visual)
(defun find-ebufferandpos (buffer-and-pos &rest pos-spec-list)
"Internal use; hyperlink to a \"buffer and pos\" structure.
Emacs has some standard (i.e., non-eev) functions that can be
used as hyperlinks, like `find-function' and `find-variable';
they call internal functions like `find-function-noselect' and
`find-variable-noselect', that return structures of the form
BUFFER-AND-POS, that are conses like (# . 42). This
function jumps to the position described by a cons like that, and
then processes an optional relative POS-SPEC-LIST using
`ee-goto-rest'.
Functions like `find-efunction' and `find-evariable' (defined in
eev.el) are wrappers around `find-function' and `find-variable'
that add support for a relative pos-spec-list after the symbol."
(if (not (bufferp (car buffer-and-pos)))
(error "Bad (BUFFER . POS): %S" buffer-and-pos))
(switch-to-buffer (car buffer-and-pos))
(goto-char (cdr buffer-and-pos))
(ee-goto-rest pos-spec-list))
(defun find-efunction (symbol &rest pos-spec-list)
"Hyperlink to the result of running `find-function' on SYMBOL.
The `find-function' function of Emacs can be used as a hyperlink
- it finds the Elisp source code of SYMBOL -, but it doesn't
support a POS-SPEC-LIST like this function does."
(interactive (find-function-read))
(apply 'find-ebufferandpos (find-function-noselect symbol) pos-spec-list))
(defun find-evariable (symbol &rest pos-spec-list)
"Hyperlink to the result of running `find-variable' on SYMBOL."
(interactive (find-function-read 'variable))
(apply 'find-ebufferandpos (find-variable-noselect symbol) pos-spec-list))
;;; __ _ _ _ __ __
;;; / _(_)_ __ __| | ___| |__ _ _ / _|/ _| ___ _ __
;;; | |_| | '_ \ / _` |_____ / _ \ '_ \| | | | |_| |_ / _ \ '__|
;;; | _| | | | | (_| |_____| __/ |_) | |_| | _| _| __/ |
;;; |_| |_|_| |_|\__,_| \___|_.__/ \__,_|_| |_| \___|_|
;;;
;; «find-ebuffer» (to ".find-ebuffer")
;; Hyperlinks to buffers
;; Tests:
;; (find-ebuffer "*Messages*")
(defun find-ebuffer (buffer &rest pos-spec-list)
"Hyperlink to an Emacs buffer (existing or not)."
(interactive "bBuffer: ")
(switch-to-buffer buffer)
(apply 'ee-goto-position pos-spec-list))
;;; __ _ _ _ _
;;; / _(_)_ __ __| | ___ ___ _ _| |_ _ __ _ _| |_
;;; | |_| | '_ \ / _` |_____ / _ \/ _ \| | | | __| '_ \| | | | __|
;;; | _| | | | | (_| |_____| __/ (_) | |_| | |_| |_) | |_| | |_
;;; |_| |_|_| |_|\__,_| \___|\___/ \__,_|\__| .__/ \__,_|\__|
;;; |_|
;; «find-eoutput» (to ".find-eoutput")
;; Tests:
;; (find-estring "a\nb\nc\n")
;; (find-estring-elisp "(dotimes (i 10) (insert \"\\na\"))")
(defun find-eoutput-rerun (buffer-name code &rest pos-spec-list)
"Hyperlink to the effect of running CODE in Emacs.
If the buffer BUFFER-NAME does not exist then create it and run
CODE in it. If the buffer already exists, then \"run CODE
again\" (compare with `find-output-reuse'): delete the buffer,
recreate it, and run CODE in it.\n
For simplicity we are deleting the buffer and then recreating it,
but it could be better to just delete the buffer's contents. This
needs to be thought out."
(if (get-buffer buffer-name) ; if the buffer exists
(if (not (kill-buffer buffer-name)) ; try to kill it; confirm if needed
(error "Not killing the buffer %s" buffer-name)))
(switch-to-buffer buffer-name) ; create the buffer
(eval code) ; always run CODE on the empty buffer
(goto-char (point-min))
(apply 'ee-goto-position pos-spec-list))
(defun find-eoutput-reuse (buffer-name code &rest pos-spec-list)
"Hyperlink to the effect of running CODE in Emacs.
If the buffer BUFFER-NAME does not exist then create it and run
CODE in it. If the buffer already exists, then \"reuse
it\" (compare with `find-output-rerun'): switch to it, ignore the
CODE argument, and process the POS-SPEC-LIST."
(if (get-buffer buffer-name) ; if the buffer exists
(switch-to-buffer buffer-name) ; then just switch to it
(switch-to-buffer buffer-name) ; otherwise switch to it and
(eval code) ; run CODE to produce its contents
(goto-char (point-min)))
(apply 'ee-goto-position pos-spec-list))
;; «find-estring» (to ".find-estring")
;;
(defun find-estring (string &rest pos-spec-list)
"Visit a temporary buffer whose contents are given by STR.
The default name for the buffer is \"*string*\", but this can be
overriden by setting `ee-buffer-name' to another name with a `let'.
If the buffer already exists its contents are destroyed.
The buffer is not made read-only."
(apply 'find-eoutput-rerun (or ee-buffer-name "*string*")
`(insert ,string) pos-spec-list))
(defun find-estring-elisp (string &rest pos-spec-list)
"Visit a temporary buffer whose contents are given by STR.
This function is similar to `find-estring', but this one also
runs `emacs-lisp-mode' in the buffer."
(apply 'find-eoutput-rerun (or ee-buffer-name "*string*")
`(progn (insert ,string) (emacs-lisp-mode)) pos-spec-list))
;; For (find-anchors-intro)
;; Hacky.
(defun ee-raw-text-unix ()
"Set the current buffer to unibyte (for certain glyphs).
See: (find-anchors-intro \"WARNING: some glyphs need raw-text-unix\")"
(interactive)
(set-buffer-file-coding-system 'raw-text-unix 'force)
(set-buffer-multibyte nil))
(defun find-estring-lv (string &rest pos-spec-list)
"Visit a temporary buffer whose contents are given by STR.
The default name for the buffer is \"*string*\", but this can be
overriden by setting `ee-buffer-name' to another name with a `let'.
If the buffer already exists its contents are destroyed.
The buffer is not made read-only.
The \"Local variables:\" section in the buffer is processed."
(apply 'find-eoutput-rerun (or ee-buffer-name "*string*")
`(progn (ee-raw-text-unix)
(insert ,string)
(hack-local-variables))
pos-spec-list))
;;; __ _ _ _
;;; / _(_)_ __ __| | ___| |__
;;; | |_| | '_ \ / _` |_____/ __| '_ \
;;; | _| | | | | (_| |_____\__ \ | | |
;;; |_| |_|_| |_|\__,_| |___/_| |_|
;;;
;;; hyperlinks to the output of shell commands
;;;
;; «find-sh» (to ".find-sh")
;; Tests:
;; (find-sh "seq 2095 2100")
;; (find-sh0 "seq 2095 2100")
;; (find-sh00 "seq 2095 2100")
;; Note: we could have written this using `find-eoutput-reuse'...
;;
(defun find-sh (command &rest pos-spec-list)
"Hyperlink to the result of running the shell command COMMAND.
If a buffer named COMMAND does not exist then create it and put
there the output or running COMMAND; if a buffer named COMMAND
already exists then reuse it and do not run COMMAND again."
(interactive "sShell command: ")
(if (get-buffer command) ; if the buffer already exists
(switch-to-buffer command) ; then just switch to it
(switch-to-buffer command) ; otherwise create it
(insert (shell-command-to-string command)) ; prepare its contents
(goto-char (point-min))) ; and place point at its beginning
(apply 'ee-goto-position pos-spec-list))
(defalias 'find-sh00 'shell-command-to-string)
(defun find-sh0 (command)
"Hyperlink to the result of running the shell command COMMAND.
This function does not create a buffer like `find-sh' does;
instead, it just returns the output of COMMAND as string,
removing a trailing newline from the output if one is found.
Follow a `find-sh0' hyperlink just displays the output of the
COMMAND in the echo area."
(replace-regexp-in-string "\n\\'" "" (shell-command-to-string command)))
;;; __ _ _
;;; / _(_)_ __ __| | _ __ ___ __ _ _ __
;;; | |_| | '_ \ / _` |_____| '_ ` _ \ / _` | '_ \
;;; | _| | | | | (_| |_____| | | | | | (_| | | | |
;;; |_| |_|_| |_|\__,_| |_| |_| |_|\__,_|_| |_|
;;;
;; «find-man» (to ".find-man")
;; hyperlinks to manpages
;; Tests:
;; (find-man "1 cat")
(defvar ee-find-man-flag nil "See `find-man'.")
(defadvice Man-notify-when-ready (around find-man (man-buffer) activate)
"After rendering a manpage jump to `ee-find-man-pos-spec-list'."
(if (not ee-find-man-flag)
ad-do-it
(switch-to-buffer man-buffer)
(apply 'ee-goto-position ee-find-man-pos-spec-list)
(setq ee-find-man-flag nil)))
(defun find-man (manpage &rest pos-spec-list)
"Hyperlink to a manpage."
(interactive (list (ee-manpagename-ask)))
(setq ee-find-man-flag t
ee-find-man-pos-spec-list pos-spec-list)
(man manpage))
;; Missing: find-woman. (find-node "(woman)Top")
;;; __ _ _ _____
;;; / _(_)_ __ __| | __ _|___ / _ __ ___
;;; | |_| | '_ \ / _` |____\ \ /\ / / |_ \| '_ ` _ \
;;; | _| | | | | (_| |_____\ V V / ___) | | | | | |
;;; |_| |_|_| |_|\__,_| \_/\_/ |____/|_| |_| |_|
;;;
;; «find-w3m» (to ".find-w3m")
;; Hyperlinks to webpages and files in HTML
;; Tests:
;; (find-w3m "http://www.emacswiki.org/")
(defun find-w3m (url &rest pos-spec-list)
"Hyperlink to a page in HTML.
Use w3m to render the page as text in an Emacs buffer.
Apply `ee-expand' to URL; this changes URL when it starts with
\"~\" or \"$\". After that if URL starts with \"/\" prepend
\"file://\" to it.
These operations on URL keep \"real urls\" unchanged and convert
several kinds of filenames into urls that w3m can process - but
it doesn't convert relative filenames into urls. See
`expand-file-name'."
(interactive "Murl: ")
(require 'w3m)
(let ((enable-local-variables nil) ; workaround for a w3m-el bug
(w3m-async-exec nil)
;; See: http://emacs-w3m.namazu.org/ml/msg10374.html
(w3m-local-find-file-regexps '(nil . ""))
(w3m-content-type-alist
(append w3m-content-type-alist '(("text/html" "" nil nil)))))
(w3m (replace-regexp-in-string "^/" "file:///" (ee-expand url))))
(ee-goto-rest pos-spec-list))
;;; _ _ _
;;; __| | ___| |__ (_) __ _ _ __
;;; / _` |/ _ \ '_ \| |/ _` | '_ \
;;; | (_| | __/ |_) | | (_| | | | |
;;; \__,_|\___|_.__/|_|\__,_|_| |_|
;;;
;; «find-Package» (to ".find-Package")
;; Hyperlinks to information about Debian packages.
;; Tests:
;; (find-status "bash")
;; (find-available "bash")
;; (find-grep-status "bash")
;; (find-grep-available "bash")
(defun find-Package (fname &optional packagename &rest pos-spec-list)
"Hyperlink to \"Package: \" achors in Debian package control files.
See: `find-status', `find-available', (find-man \"grep-dctrl\")"
(find-fline fname)
(apply 'ee-goto-position
(if packagename (format "\nPackage: %s\n" packagename))
pos-spec-list))
(defun find-status (packagename &rest pos-spec-list)
"Hyperlink to the info about the package PACKAGENAME in /var/lib/dpkg/status.
This is Debian-specific. See `find-Package'."
(interactive (list (ee-debpkgname-ask)))
(apply 'find-Package "/var/lib/dpkg/status" packagename pos-spec-list))
(defun find-available (packagename &rest pos-spec-list)
"Hyperlink to the info about the package PACKAGENAME in /var/lib/dpkg/available.
This is Debian-specific. See `find-Package'."
(interactive (list (ee-debpkgname-ask)))
(apply 'find-Package "/var/lib/dpkg/available" packagename pos-spec-list))
(defun find-grep-status (grepargs &rest pos-spec-list)
(interactive "sgrep-status ")
(apply 'find-sh (concat "grep-status " grepargs) pos-spec-list))
(defun find-grep-available (grepargs &rest pos-spec-list)
(interactive "sgrep-available ")
(apply 'find-sh (concat "grep-available " grepargs) pos-spec-list))
;;; __ _ _
;;; / _(_)_ __ __| | ___ _ __ _ __
;;; | |_| | '_ \ / _` |____ / _ \ '_ \| '_ \
;;; | _| | | | | (_| |____| __/ |_) | |_) |
;;; |_| |_|_| |_|\__,_| \___| .__/| .__/
;;; |_| |_|
;; «find-epp» (to ".find-epp")
;; Pretty-priting sexps.
;; "pp0" -> "pretty-print a Lisp object in a very compact way".
;; Tests:
;; (find-epp '(apply (lambda (a) (* a a)) 5))
;; (find-functionpp 'find-efunction)
(defun find-epp0 (object)
"Display a pretty-printed version of OBJECT in the echo area.
This function uses `message' and so it only makes sense to call
it from commands bound to keys, not by sexps that are evaluated
explicitly. Try this: (progn (message \"foo\") \"bar\")"
(message (ee-pp0 object)))
(defun find-epp (object &rest pos-spec-list)
"Visit a temporary buffer containing a pretty-printed version of OBJECT."
(let ((ee-buffer-name (or ee-buffer-name "*pp*")))
(apply 'find-estring-elisp (pp-to-string object) pos-spec-list)))
(defun find-efunctionpp (symbol &rest pos-spec-list)
"Visit a temporary buffer containing the pretty-printed Lisp code for SYMBOL."
(interactive (find-function-read))
(let ((ee-buffer-name
(or ee-buffer-name (format "*function %S*" symbol))))
(apply 'find-epp
(symbol-function symbol)
;; Note: if instead of the above we use
;; `(fset ',symbol ',(symbol-function symbol))
;; the we get a buffer in which we can edit the code for SYMBOL.
pos-spec-list)))
;;; _ _ _
;;; ___ _ __ ___ __ _ ___ ___ (_)_ __ | |_ ___ _ __ _ __ __ _| |___
;;; / _ \ '_ ` _ \ / _` |/ __/ __| | | '_ \| __/ _ \ '__| '_ \ / _` | / __|
;;; | __/ | | | | | (_| | (__\__ \ | | | | | || __/ | | | | | (_| | \__ \
;;; \___|_| |_| |_|\__,_|\___|___/ |_|_| |_|\__\___|_| |_| |_|\__,_|_|___/
;;;
;; «find-einternals» (to ".find-einternals")
;; Hyperlinks to other things internal to Emacs
;; Tests:
;; (find-ekeymapdescr isearch-mode-map "toggle-regexp")
;; (find-eminorkeymapdescr 'eev-mode)
;; (find-einsert '((32 255) 10 (8592 9167)))
;; (find-etpat)
;; (find-etpat0)
(defun find-ekeymapdescr (keymap &rest pos-spec-list)
"Hyperlink to the list of bindings in KEYMAP.
Example: (find-ekeymapdescr isearch-mode-map \"toggle-regexp\")"
;; To do: add the buttons/link thing
(apply 'find-estring (substitute-command-keys "\\\\{keymap}")
pos-spec-list))
(defun find-eminorkeymapdescr (mode-symbol &rest pos-spec-list)
"Hyperlink to the list of bindings in the minor mode MODE-SYMBOL.
Example: (find-eminorkeymapdescr 'eev-mode)"
(apply 'find-ekeymapdescr (ee-minor-mode-keymap mode-symbol)
pos-spec-list))
(defalias 'find-eminormodekeymapdescr 'find-eminorkeymapdescr)
(defun ee-minor-mode-keymap (mode-symbol)
"An auxiliary function used by `find-eminorkeymapdescr'.
Example: (find-ekeymapdescr (ee-minor-mode-keymap 'eev-mode))"
(cdr (assq mode-symbol minor-mode-map-alist)))
(defun ee-insert (&rest rest)
"Insert characters, strings, or ranges of characters.
Example: (ee-insert '(?a ?z) 10 \"Foo!\")"
(while rest
(let ((o (car rest)))
(cond ((stringp o) (insert o))
((numberp o) (if (char-valid-p o) (insert o)))
((consp o) (mapc 'ee-insert (apply 'number-sequence o)))
(t (error "Not string/int/pair: %S" o))))
(setq rest (cdr rest))))
(defun find-einsert (what &rest rest)
"See `ee-insert'.
Example of use: (find-einsert '((32 1000) 10 (8000 12000)))"
(apply 'find-eoutput-reuse "*einsert*"
`(apply 'ee-insert ',what) rest))
(defun find-etpat0 (&rest pos-spec-list)
"Hyperlink to a pretty version of the result of (text-properties-at (point))."
(interactive)
(let* ((ee-buffer-name
(or ee-buffer-name "*(text-properties-at (point))*")))
(apply 'find-epp (text-properties-at (point)) pos-spec-list)))
(defun find-etpat00 ()
"Show the result of (text-properties-at (point)) in the echo area."
(interactive)
(find-epp0 (text-properties-at (point))))
;; Broken? See: (find-efile "international/ccl.el")
(defun find-eccldump (ccl-code &rest pos-spec-list)
"Hyperlink to the result of running `ccl-dump' on CCL-CODE.
Example: (find-eccldump ccl-decode-mule-utf-8)"
(apply 'find-eoutput-reuse "*ccl-dump*"
`(ccl-dump ,ccl-code) pos-spec-list))
;; Broken? `list-iso-charset-chars' and friends are not defined in the
;; Unicode-2 branch of Emacs... Does this still work?
;;
(defun find-echarsetchars (charset &rest pos-spec-list)
"See: (find-efunction 'list-charset-chars)
Examples: (find-echarsetchars 'mule-unicode-0100-24ff \"733x\")
(find-echarsetchars 'mule-unicode-2500-33ff)"
(interactive (list (read-charset "Character set: ")))
(apply 'find-eoutput-reuse "*charset*"
'(cond ((charsetp charset)
(list-iso-charset-chars charset))
((assq charset non-iso-charset-alist)
(list-non-iso-charset-chars charset))
(t (error "Invalid character set %s" charset)))
pos-spec-list))
;;; __ _ _ _
;;; / _(_)_ __ __| | ___ ___ (_)_ _ _ __ ___ _ __ ___
;;; | |_| | '_ \ / _` |_____ / _ \/ _ \| | | | | '_ ` _ \| '_ \/ __|
;;; | _| | | | | (_| |_____| __/ __/| | |_| | | | | | | |_) \__ \
;;; |_| |_|_| |_|\__,_| \___|\___|/ |\__,_|_| |_| |_| .__/|___/
;;; |__/ |_|
;;
;; A hack to diplay all the current eejump targets.
;; Should this be here? See: (find-eev "eejump.el")
;; Try: (find-eejumps)
(defun ee-defun-sexp-for (symbol)
`(defun ,symbol ,@(cdr (symbol-function symbol))))
(defun ee-defun-str-for (symbol)
(replace-regexp-in-string
"^(defun \\([^ ]+\\) nil " "(defun \\1 () "
(ee-S (ee-defun-sexp-for symbol))))
(defun eejump-symbols ()
(apropos-internal "^eejump-[0-9]*\\*?$"))
(defun find-eejumps (&rest pos-spec-list) (interactive)
(apply 'find-estring-elisp
(concat ";; (find-eejumps)\n\n"
(mapconcat 'ee-defun-str-for (eejump-symbols) "\n"))
pos-spec-list))
(provide 'eev-blinks)
;; was: ee-anchor-format: "defun %s "
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "«%s»"
;; no-byte-compile: t
;; End:
eev-20141011/eev-bounded.el 0000644 0001750 0001750 00000027607 12212545525 013750 0 ustar edrx edrx ;;; eev-bounded.el -- functions like `eev-bounded', `eelatex-bounded', etc.
;; Copyright (C) 2012 Free Software Foundation, Inc.
;;
;; This file is part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2012dec26
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;;
;; (find-eev-intro)
;; (find-bounded-intro)
;;; Commentary:
;;
;; This file adds support for "bounded functions" to eev. For example:
;; `M-x eev' saves the region between point and mark into the
;; temporary script file; `M-x eev-bounded' saves the region around
;; point, up to the first occurences of a certain delimiters before
;; and after point, into the temporary script file.
;;
;; Big letters courtesy of Figlet.
;; See: (find-bounded-intro)
;;; _ _ _ _ _
;;; __| | ___| (_)_ __ ___ (_) |_ ___ _ __ ___
;;; / _` |/ _ \ | | '_ ` _ \| | __/ _ \ '__/ __|
;;; | (_| | __/ | | | | | | | | || __/ | \__ \
;;; \__,_|\___|_|_|_| |_| |_|_|\__\___|_| |___/
;;;
(defvar ee-delimiter-hash "\n#\n" "See `eev-bounded'.")
(defvar ee-delimiter-percent "\n%\n" "See `eelatex-bounded'.")
(defvar ee-delimiter-semicolon "\n;;\n" "See `eeeval-boudned'.")
(put 'ee-delimiter-hash 'safe-local-variable 'stringp)
(put 'ee-delimiter-percent 'safe-local-variable 'stringp)
(put 'ee-delimiter-semicolon 'safe-local-variable 'stringp)
(defun ee-sdelim-to-s (sdelim)
"Search backwards for STR and return the position after STR.
This function does not move point."
(+ (save-excursion (search-backward sdelim))
(length sdelim)))
(defun ee-edelim-to-e (edelim)
"Search forward for STR and return the position before STR.
This function does not move point."
(+ (save-excursion (search-forward edelim))
(- (length edelim))))
;;; _ _ _ _
;;; ___ ___ __| | ___ | |__ ___ _ _ _ __ __| | ___ __| |
;;; / __/ _ \ / _` |/ _ \_____| '_ \ / _ \| | | | '_ \ / _` |/ _ \/ _` |
;;; | (_| (_) | (_| | __/_____| |_) | (_) | |_| | | | | (_| | __/ (_| |
;;; \___\___/ \__,_|\___| |_.__/ \___/ \__,_|_| |_|\__,_|\___|\__,_|
;;;
;; See: (find-bounded-intro "Defining new bounded functions")
(defun code-bounded (newf f delim &optional adjust face dur)
(eval (ee-read
(ee-code-bounded newf f delim adjust face dur))))
(defun find-code-bounded (newf f delim &optional adjust face dur)
(find-estring-elisp
(ee-code-bounded newf f delim adjust face dur)))
(defun ee-code-bounded (newf f delim &optional adjust face dur)
(setq adjust (or adjust 1))
(setq face (or face 'highlight))
(setq dur (or dur 0.75))
(ee-template0 "
\(defun {newf} ()
\"Run the function `{f}' on a delimited region around point.
See: (find-bounded-intro)\"
(interactive)
(setq ee-bounded-function '{newf})
(let* ((s (ee-sdelim-to-s {(ee-S delim)}))
(e (ee-edelim-to-e {(ee-S delim)})))
(ee-flash s (+ e {adjust})
'{(ee-S face)} {dur})
({f} (ee-se-to-string s e))))
"))
(code-bounded 'eev-bounded 'eev 'ee-delimiter-hash)
(code-bounded 'eeg-bounded 'eeg 'ee-delimiter-hash)
(code-bounded 'eegdb-bounded 'eegdb 'ee-delimiter-hash)
(code-bounded 'eelatex-bounded 'eelatex 'ee-delimiter-percent)
(code-bounded 'eeeval-bounded 'eeeval 'ee-delimiter-semicolon)
(code-bounded 'eeb-eval 'eeeval 'ee-delimiter-semicolon)
;; Tests:
;; (find-code-bounded 'eev-bounded 'eev "\n#\n")
;; (find-code-bounded 'eev-bounded 'eev 'ee-delimiter-hash)
;;; _ __ _ _
;;; __| | ___ / _| __ _ _ _| | |_
;;; / _` |/ _ \ |_ / _` | | | | | __|
;;; | (_| | __/ _| (_| | |_| | | |_
;;; \__,_|\___|_| \__,_|\__,_|_|\__|
;;;
;; See: (find-bounded-intro "The default bounded function")
(defvar ee-bounded-function
'(lambda () (error "ee-bounded-function not set"))
"See: (find-bounded-intro)")
(defun ee-bounded-function ()
"See: (find-bounded-intro)"
(interactive)
(funcall ee-bounded-function))
;; (define-key eev-mode-map [f3] 'ee-bounded-function)
(provide 'eev-bounded)
;;; _ _ _
;;; ___ | |__ ___ ___ | | ___| |_ ___
;;; / _ \| '_ \/ __|/ _ \| |/ _ \ __/ _ \
;;; | (_) | |_) \__ \ (_) | | __/ || __/
;;; \___/|_.__/|___/\___/|_|\___|\__\___|
;;;
;; Obsolete code that I don't want to delete yet
;; (mainly because the docstrings have some good ideas in them)
' (progn
(defun ee-add-quote (obj)
"Return OBJ is OBJ is constant; else return 'OBJ."
(if (or (numberp obj) (stringp obj)
(eq obj nil) (eq obj t) (keywordp obj))
obj
(list 'quote obj)))
(defun ee-pp0q (obj)
"Like (ee-pp0 OBJ), but add a \"'\" in front if needed."
(ee-pp0 (ee-add-quote obj)))
(defun ee-eeb-define-docstring
(eeb-fun fun sdelim edelim flash-spec adjust extra-docs)
"Used internally by `ee-eeb-define' to generate the docstring."
(let ((args `(,eeb-fun ,fun ,sdelim ,edelim ,flash-spec ,adjust
,@(if extra-docs (list extra-docs)))))
(format "Run `%S' on a delimited region around point.
This is a wrapper function created by a sexp equivalent to first
one below (see `eeb-define'). To inspect the code that it
generates run the second sexp; and for an explanation of the
parameters, and a for a way of experimenting with them, see
`eeb-define-try'.\n
(eeb-define %s)
(find-eeb-define %s)%s"
fun
(mapconcat 'ee-pp0q args " ")
(mapconcat 'ee-pp0q args " ")
(if extra-docs (concat "\n\n" extra-docs) ""))))
(defun ee-eeb-define
(eeb-fun fun sdelim &optional edelim flash-spec adjust extra-docs)
"See `eeb-define' and `eeb-define-try'.
This function generates the code for defining EEB-FUN, as a string,
and returns it without `read'ing or `eval'ing it. An example:\n
(find-estring (ee-eeb-define 'eev-bounded 'eev 'ee-delimiter-hash nil t t))"
(format
"(defun %S ()
%S
(interactive)
(setq eeb-defaults '%s)
(eeb-default-new))"
eeb-fun
(ee-eeb-define-docstring
eeb-fun fun sdelim edelim flash-spec adjust extra-docs)
(ee-pp0 (list fun sdelim edelim flash-spec adjust))))
;; Tests:
;; (find-eeb-define 'eev-bounded 'eev "\n#\n" nil t t)
;; (find-eeb-define 'eev-bounded 'eev "\n#\n" nil t t "Example\nHere")
;; (eeb-define 'eev-bounded 'eev "\n#\n" nil t t)
;; (eeb-define 'eev-bounded 'eev "\n#\n" nil t t "Example\nHere")
;; (eeb-define 'eev-bounded 'eev 'ee-delimiter-hash nil t t "Example\nHere")
;; (find-efunctiondescr 'eev-bounded)
;; Note: the sexps in the docstring might come out wrong if they
;; contain nasty unibyte characters (this is a known possible bug).
(defun eeb-define
(eeb-fun fun sdelim &optional edelim flash-spec adjust extra-docs)
"Define EEB-FUN as a wrapper around FUN.
Use the delimiters SDELIM and EDELIM to find the region around
point where where FUN will operate; highlight the region using
FLASH-SPEC and ADJUST. If you want to add an example or extra
explanations to the docstring of EEB-FUN use EXTRA-DOCS.
See `eeb-define-try' for a detailed explanation of the parameters
and for a way of experimenting with them; see `find-eeb-define'
for a way to inspect to wrapper code."
(eval (read (ee-eeb-define
eeb-fun
fun sdelim edelim
flash-spec adjust extra-docs))))
(defun find-eeb-define (&rest rest)
(find-estring (apply 'ee-eeb-define rest))
(emacs-lisp-mode))
(defun eeb-define-try
(eeb-fun fun sdelim &optional edelim flash-spec adjust extra-docs)
"This is similar to `eeb-define', but instead of defining EEB-FUN run it now.
The \"default action over bounded regions\" is determined by the
five entries in the list stored in the variable `eeb-defaults'
\(described below). All the \"bounded functions\", like
`eev-bounded', work by setting the variable `eeb-defaults' and
then calling the function `eeb-default-new', that interprets the
entries in `eeb-defaults' in a certain way and acts accordingly.
eeb-define
==========
Bounded functions like `eev-bounded' are defined by calling the
function `eeb-define' with the name of the function to define and
the five entries for the associated value for `eeb-defaults',
like this:
(eeb-define 'eev-bounded 'eev 'ee-delimiter-hash nil t t)
`eeb-define-try' provides a nice way to test how functions
defined by `eeb-define' would behave after they are defined.
`eeb-define-try' expects the same arguments as `eeb-define', but
it ignores the first one - EEB-FUN -, and instead of defining a
function EEB-FUN that would set `eeb-defaults' and run
`eeb-default', it sets `eeb-defaults' immediately (temporarily,
using `let') and runs `eeb-default' on that.
eeb-defaults and eeb-default
============================
The variable `eeb-defaults' always holds a list of this form:
(FUN SDELIM EDELIM FLASH-SPEC ADJUST)
where:
FUN is a function taking arguments \"s\" and \"e\", like `eev',
SDELIM is the starting delimiter (see `ee-edelim-adjust'),
EDELIM is the ending delimiter (default: same as sdelim),
FLASH-SPEC tells how to highlight the region (see `eeflash-new'),
ADJUST should usually be t; see `ee-edelim-adjust'.
The \"default action on a delimited region\" is always something
composed of two \"standard actions\": first, highlight the region
temporarily, as described below; second, and most important, run
\"(FUN s e)\" on the region. FLASH-SPEC and ADJUST are only used
for the highlighting part; FUN is only used for the \"run (FUN s
e)\" part.
A nil at EDELIM means to use EDELIM := SDELIM; after
replacing the possible nil at EDELIM both SDELIM and
EDELIM are \"expanded\" with `ee-symbol-value' if their
values are symbols, and the results must be strings. Those
resulting strings are used as region delimiters by
`ee-sdelim-to-s' and `ee-edelim-to-e' to produce the \"s\" and
\"e\" arguments for the \"(FUN s e)\" call; see the documentation
for `ee-edelim-adjust' for an example that also shows how
ADJUST affects the highlighting.
A t at FLASH-SPEC means to use `eeflash-default' as FLASH-SPEC;
after treating the `t' case the value of FLASH-SPEC is
\"expanded\" with `ee-symbol-value' if it's a symbol, and the
result - that should be either nil or a list of the form \"(face
duration)\" - becomes temporarily the value of `ee-flash-spec',
and we invoke `eeflash-new' to highlight the region.
Examples
========
Here are some demos:\n
#.
# (eeb-define-try nil 'list \"\\n#.\\n\" nil t t)
# (eeb-define-try nil 'ee-se-to-string \"\\n#.\\n\" nil t t)
# (eeb-define-try nil 'eeflash-new \"\\n#.\\n\" nil t t)
# (eeb-define-try nil 'eev \"\\n#.\\n\" nil t t)
echo $[1+2]
#.\n"
(let ((eeb-defaults (list fun sdelim edelim flash-spec adjust)))
(eeb-default-new)))
)
;; Local Variables:
;; coding: raw-text-unix
;; no-byte-compile: t
;; End:
eev-20141011/eev-brxxx.el 0000644 0001750 0001750 00000025271 12212547317 013477 0 ustar edrx edrx ;;; eev-brxxx.el -- define families of browse-url-like functions.
;; Copyright (C) 2012 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2013sep07
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;;
;;
;; (find-eev-intro)
;; (find-psne-intro)
;; (find-brxxx-intro)
;;; Commentary:
(require 'eev-code) ; (find-eev "eev-code.el")
(autoload 'browse-url-interactive-arg "browse-url")
;;; _
;;; ___ ___ _ ____ _____ _ __ ___(_) ___ _ __ ___
;;; / __/ _ \| '_ \ \ / / _ \ '__/ __| |/ _ \| '_ \/ __|
;;; | (_| (_) | | | \ V / __/ | \__ \ | (_) | | | \__ \
;;; \___\___/|_| |_|\_/ \___|_| |___/_|\___/|_| |_|___/
;;;
;; See: (find-brxxx-intro)
;; Here we define some conversion functions that are used by
;; `code-brurl' and `code-brfile'.
;;
;; The `brxxx' functions call the conversion functions defined below,
;; that convert between four kinds of strings: "dired", "url",
;; "fname", and "local-url". The table below explains which function
;; does what; note that "<$S>" means the expansion of "$S", and that
;; if the point is on the file name "b" in a dired buffer visiting the
;; directory "/foo/bar" then `(ee-dired-to-fname)' returns
;; "/foo/bar/b", not something that starts with "$S".
;;
;; dired url fname local-url
;; "b" "/foo/bar/b" "file:///foo/bar/b"
;; "http://a/b" "$S/http/a/b" "file:///<$S>/http/a/b"
;; ==========================================================
;; * (code-brurl _ :remote _)
;; * |-----------------------------> * (code-brurl _ :local _)
;; * |--------------------------------------> * (code-brurl _ :dired _)
;;
;; * |----------> * (code-brfile _ :local _)
;; * |-------------------> * (code-brfile _ :dired _)
;;
;; * |----------> * ee-url-to-fname
;; * |--------------> * ee-fname-to-url
;; * |-----------------------------> * ee-url-to-local-url
;; * |-------------------> * ee-dired-to-fname
;; * |--------------------------------------> * ee-dired-to-url
(defun ee-url-to-fname0 (url)
"Convert an url like http://foo/bar to a filename like $S/http/foo/bar."
(replace-regexp-in-string "^\\(https?\\|ftp\\)://" "$S/\\1/" url))
(defun ee-url-to-fname (url)
"Convert an url like http://foo/bar to a filename like <$S>/http/foo/bar.
\(The \"<$S>\" above means the expansion of \"$S\"; see `ee-expand')."
(ee-expand (ee-url-to-fname0 url)))
(defun ee-fname-to-url (fname)
"Convert a filename to a \"file://\" url (after running `ee-expand' on it)."
(concat "file://" (expand-file-name (ee-expand fname))))
(defun ee-url-to-local-url (url)
"Convert a url like http://foo/bar to a url like file://<$S>/http/foo/bar.
This should be made smarter - file:// urls should be returned unchanged."
;; Add comments about psne and the snarf directory
(ee-fname-to-url (ee-url-to-fname url)))
(defun ee-dired-to-fname (&optional no-error-if-not-filep)
"Convert the file name at point (in dired mode) to an absolute file name."
(if (eq major-mode 'dired-mode)
(file-name-sans-versions (dired-get-filename nil no-error-if-not-filep) t)
(error "Not in dired mode")))
(defun ee-dired-to-url (&optional no-error-if-not-filep)
"Convert the file name at point (in dired mode) to a url like file://<$S>/___."
(ee-fname-to-url (ee-dired-to-fname no-error-if-not-filep)))
;;; _ _ _
;;; ___ ___ __| | ___ | |__ _ __ _ _ _ __| |
;;; / __/ _ \ / _` |/ _ \_____| '_ \| '__| | | | '__| |
;;; | (_| (_) | (_| | __/_____| |_) | | | |_| | | | |
;;; \___\___/ \__,_|\___| |_.__/|_| \__,_|_| |_|
;;;
;; (find-tail-call-links "brurl" "f")
;; code-brurl: top-level functions
;;
(defun code-brurl (f &rest rest)
"Define a family of brxxx functions from a function that operates on URLs"
(eval (ee-read (apply 'ee-code-brurl f rest))))
(defun find-code-brurl (f &rest rest)
(find-estring-elisp (apply 'ee-code-brurl f rest)))
(defun ee-code-brurl (f &rest rest)
"Generate code for a family of functions from a function that operates on URLs"
(concat (ee-template0 "\
;; {(ee-S `(find-code-brurl ',f ,@(mapcar 'ee-add-quote rest)))}
") (ee-code-brurl-rest rest)))
;; Support for extra arguments
;;
(defun ee-code-brurl-rest (rest)
(ee-tail-call "ee-code-brurl-%S" rest))
(defun ee-code-brurl-:remote (brxxx &rest rest)
(concat (ee-template0 "
\(defun {brxxx} (url &rest ignore)
\"Apply `{f}' on URL.\"
(interactive (browse-url-interactive-arg \"URL: \"))
(setq browse-url-browser-function '{brxxx})
(message \"(%S %S) -> %S\" '{f} url
({f} url)))
") (ee-code-brurl-rest rest)))
(defun ee-code-brurl-:local (brxxxl &rest rest)
(concat (ee-template0 "
\(defun {brxxxl} (url &rest ignore)
\"Apply `{f}' on the local url associated to URL.\"
(interactive (browse-url-interactive-arg \"URL: \"))
(setq browse-url-browser-function '{brxxxl})
(setq url (ee-url-to-local-url url))
(message \"(%S %S) -> %S\" '{f} url
({f} url)))
") (ee-code-brurl-rest rest)))
(defun ee-code-brurl-:dired (brxxxd &rest rest)
(concat (ee-template0 "
\(defun {brxxxd} (&rest ignore)
\"Apply `{f}' on the url of the dired file at point.\"
(interactive)
(let ((url (ee-dired-to-url)))
(message \"(%S %S) -> %S\" '{f} url
({f} url))))
") (ee-code-brurl-rest rest)))
;; Test:
;; (find-code-brurl 'pluc :remote 'brpluc :local 'brplucl :dired 'brplucd)
;; (code-brurl 'pluc :remote 'brpluc :local 'brplucl :dired 'brplucd)
;;
;; (find-efunction 'find-brxxx-intro)
;; (find-brxxx-intro "M-x brpluc")
;;; _ _ __ _ _
;;; ___ ___ __| | ___ | |__ _ __ / _(_) | ___
;;; / __/ _ \ / _` |/ _ \_____| '_ \| '__| |_| | |/ _ \
;;; | (_| (_) | (_| | __/_____| |_) | | | _| | | __/
;;; \___\___/ \__,_|\___| |_.__/|_| |_| |_|_|\___|
;;;
;; (find-tail-call-links "brfile" "f")
;; code-brfile: top-level functions
;;
(defun code-brfile (f &rest rest)
"Define a family of brxxx functions from a function that operates on files"
(eval (ee-read (apply 'ee-code-brfile f rest))))
(defun find-code-brfile (f &rest rest)
(find-estring-elisp (apply 'ee-code-brfile f rest)))
(defun ee-code-brfile (f &rest rest)
"Generate code for a family of functions from a function that operates on files"
(concat (ee-template0 "\
;; {(ee-S `(find-code-brfile ',f ,@(mapcar 'ee-add-quote rest)))}
") (ee-code-brfile-rest rest)))
;; Support for extra arguments
;;
(defun ee-code-brfile-rest (rest)
(ee-tail-call "ee-code-brfile-%S" rest))
(defun ee-code-brfile-:local (brxxxl &rest rest)
(concat (ee-template0 "
\(defun {brxxxl} (url &rest ignore)
\"Apply `{f}' on the local file name associated to URL.\"
(interactive (browse-url-interactive-arg \"URL: \"))
(setq browse-url-browser-function '{brxxxl})
(let ((fname (ee-url-to-fname url)))
(message \"(%S %S) -> %S\" '{f} fname
({f} fname))))
") (ee-code-brfile-rest rest)))
(defun ee-code-brfile-:dired (brxxxd &rest rest)
(concat (ee-template0 "
\(defun {brxxxd} (&rest ignore)
\"Apply `{f}' on the dired file at point.\"
(interactive)
(let ((fname (ee-dired-to-fname)))
(message \"(%S %S) -> %S\" '{f} fname
({f} fname))))
") (ee-code-brfile-rest rest)))
;; Tests:
;; (find-code-brurl 'pluc :remote 'brpluc :local 'brplucl :dired 'brplucd)
;; (find-code-brfile 'plic :local 'brplicl :dired 'brplicd)
;; See:
;; (find-eev "eev-blinks.el" "find-w3m")
;; (find-efile "net/browse-url.el")
(code-brurl 'find-psne-links
:remote 'brep)
(code-brurl 'browse-url-firefox
:remote 'brm :local 'brml :dired 'brmd)
(code-brurl 'find-googlechrome
:remote 'brg :local 'brgl :dired 'brgd)
(code-brurl 'find-w3m
:remote 'brw :local 'brwl :dired 'brwd)
(code-brfile 'find-fline :local 'brfl)
(defun find-googlechrome (url) (find-bgprocess `("google-chrome" ,url)))
;; These are defined elsewhere.
;; (code-brfile 'find-xpdf-page :local 'brxpdfl :dired 'brxpdfd)
;; (code-brfile 'find-evince-page :local 'brevincel :dired 'brevinced)
;; (code-brfile 'find-xdvi-page :local 'brxdvil :dired 'brxdvid)
;; (code-brfile 'find-pdf-text :local 'brpdftextl :dired 'brpdftextd)
;; (code-brfile 'find-djvu-text :local 'brdjvutextl :dired 'brdjvutextd)
;; See: (find-eev "eev-pdflike.el")
;; These too...
;; (code-brfile 'find-video :local 'brvideol :dired 'brvideod)
;; (code-brfile 'find-audio :local 'braudiol :dired 'braudiod)
;; See: (find-eev "eev-audiovideo.el")
;; Some obsolete definitions (with the old syntax):
;; (eeurl-define-from :fname->action: 'eecd :local: 'brcdl)
;; (eeurl-define-from :url->action: 'eepsne :remote: 'brp)
;; (eeurl-define-from :url->action: 'eetmpwget :remote: 'brtmpwget)
;; (find-eevgrep "grep -nH -e brg *.el")
(provide 'eev-brxxx)
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "«%s»"
;; ee-anchor-format: "defun %s "
;; no-byte-compile: t
;; End:
eev-20141011/eev-channels.el 0000644 0001750 0001750 00000021011 12067057214 014103 0 ustar edrx edrx ;;; eev-channels.el -- control external processes usign signals,
;;; temporary files, and Expect scripts.
;; Copyright (C) 2012 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2012dec27
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;; (find-eev-intro)
;;; Commentary:
;; TODO: import code from:
;; (find-eevgrep "grep -nH -e channel *.el")
;; (find-eev "anim/channels.anim")
;; (find-eev "eechannel.el")
(defun ee-read-file (fname)
(with-temp-buffer
(insert-file-contents fname)
(buffer-string)))
;;; _ _
;;; ___ ___ ___| |__ __ _ _ __ _ __ ___| |
;;; / _ \/ _ \/ __| '_ \ / _` | '_ \| '_ \ / _ \ |
;;; | __/ __/ (__| | | | (_| | | | | | | | __/ |
;;; \___|\___|\___|_| |_|\__,_|_| |_|_| |_|\___|_|
;;;
;; (find-man "xterm" "-T string")
;; (find-man "xterm" "-e program [ arguments ... ]")
;; (find-eev "eegchannel")
;; (find-eev "eegchannel" "pidfile")
;; (find-eev "eegchannel" "strfile")
;;
;; There is a big diagram explaining how this works at:
;;
;; (find-eev "anim/channels.anim")
;;
;; Note that this is a "communication diagram" - it shows which
;; programs start which other programs, and how they communicate.
;; Here is a call diagram for the lisp functions (and some
;; variables):
;;
;; ---> eechannel-this-line
;; | \ (on "" lines)
;; (on non-"" | v
;; lines) | ee-eval-string
;; v
;; eechannel-send
;; | | |
;; | | v (sets)
;; | v eechannel-default <------ eechannel
;; v eechannel-strfile
;; /---> eechannel-pid ----------> eechannel-pidfile
;; |
;; eechannel-kill
(defvar eechannel-default nil)
(defun eechannel-strfile (channel)
(ee-expand (format "$EEVTMPDIR/eeg.%s.str" channel)))
(defun eechannel-pidfile (channel)
(ee-expand (format "$EEVTMPDIR/eeg.%s.pid" channel)))
(defun eechannel-pid (channel)
"Return the pid stored in the eeg.CHANNEL.pid file, as a string (or nil on error)."
(let ((pidfile (eechannel-pidfile channel)))
(if (file-exists-p pidfile)
(ee-no-trailing-nl (ee-read-file pidfile)))))
(defun eechannel-kill (channel sig)
"Send the signal SIG to the process listening on the channel CHANNEL."
;; We call "kill" to send the signal.
(find-callprocess0 (format "kill %s %s" sig (eechannel-pid channel))))
(defun eechannel-send (channel str)
"Send STR through channel CHANNEL (or through channel `eechannel-default')."
(setq channel (or channel eechannel-default))
(write-region str nil (eechannel-strfile channel))
(find-callprocess0 (format "kill -USR1 %s" (eechannel-pid channel))))
(defun eechannel-this-line () (interactive)
"Send the current line through the channel `eechannel-default', and go down.
If the line starts with a `' then evaluate it as lisp instead of sending it."
(let ((line (buffer-substring (ee-bol) (ee-eol)))) ; contents of this line
(if (string-match "^\\(.*\\)" line) ; lines with a red star
(ee-eval-string (match-string 1 line)) ; are eval'ed
(eechannel-send nil (concat line "\n"))) ; other lines are sent
(ee-next-line 1))) ; go down
(defun eechannel (channel)
"Set the default channel to CHANNEL."
(interactive "sDefault channel: ")
(setq eechannel-default channel))
;;; _ _
;;; ___ ___ ___| |__ __ _ ___ ___ ___ _ __| |_
;;; / _ \/ _ \/ __| '_ \ _____ / _` / __/ __|/ _ \ '__| __|
;;; | __/ __/ (__| | | |_____| (_| \__ \__ \ __/ | | |_
;;; \___|\___|\___|_| |_| \__,_|___/___/\___|_| \__|
;;;
(defun eechannel-pid-running-p (pid)
"Return t if a process with pid PID is running. This is linux-specific."
;; I've heard the on BSDs "/proc" is optional and often disabled...
;; Calling "ps" every time sounds expensive, what should I do?
(file-exists-p (format "/proc/%s" pid)))
;; The six functions below are for when we want to use eegchannel
;; directly, without calling it from an xterm (as in eexterm)...
(defun eechannel-args-ne (channel prog-and-args)
`(,(ee-expand "$EEVDIR/eegchannel") ,channel
,@(ee-split prog-and-args)))
(defun eechannel-create-ne (channel prog-and-args)
(find-bgprocess-ne (eechannel-args-ne channel prog-and-args)))
(defun eechannel-assert-ne (channel prog-and-args)
(let ((pid (eechannel-pid channel)))
(if (eechannel-pid-running-p (eechannel-pid channel))
(message "Channel %s (pid %s) looks alive, reusing" channel pid)
(eechannel-create-ne channel prog-and-args))))
(defun eechannel-args (channel prog-and-args)
(eechannel-args-ne channel (ee-split-and-expand prog-and-args)))
(defun eechannel-create (channel prog-and-args)
(eechannel-create-ne channel (ee-split-and-expand prog-and-args)))
(defun eechannel-assert (channel prog-and-args)
(eechannel-assert-ne channel (ee-split-and-expand prog-and-args)))
;;; _
;;; ___ _____ _| |_ ___ _ __ _ __ ___
;;; / _ \/ _ \ \/ / __/ _ \ '__| '_ ` _ \
;;; | __/ __/> <| || __/ | | | | | | |
;;; \___|\___/_/\_\\__\___|_| |_| |_| |_|
;;;
;; A call diagram:
;;
;; eexterm ---------> eexterm-ne
;; | |
;; | v
;; | eechannel-pid-running-p
;; v
;; eexterm-create --> eexterm-create-ne
;; |
;; v
;; eexterm-args ----> eexterm-args-ne
;;
;; eexterm-kill -----> eechannel-kill
(defun eexterm-args-ne (channel prog-and-args xterm-args)
"Return a list of arguments for running a xterm listening on CHANNEL.
Try these examples:
(eexterm-args-ne \"A\" nil nil)
(eexterm-args-ne \"A\" '(\"ssh\" \"foo@bar\") \"-geometry 80x20\")"
`("xterm"
"-T" ,(format "channel %s" channel)
,@(ee-split xterm-args)
"-e" ,(ee-expand "$EEVDIR/eegchannel") ,channel
,@(ee-split (or prog-and-args (ee-expand "$SHELL")))))
(defun eexterm-create-ne (channel prog-and-args xterm-args)
"Start a xterm listening on CHANNEL. See `eexterm-args-ne'."
(find-bgprocess-ne (eexterm-args-ne channel prog-and-args xterm-args)))
(defun eexterm-ne (channel prog-and-args xterm-args)
"Set the default channel to CHANNEL; create an xterm listening on CHANNEL if needed."
(interactive "sDefault channel: ")
(setq eechannel-default channel)
(if (eechannel-pid-running-p (eechannel-pid channel))
(message "Reusing xterm at channel %s" channel)
(eexterm-create-ne channel prog-and-args xterm-args)))
(defun eexterm-args (channel &optional prog-and-args xterm-args)
(eexterm-args-ne channel (ee-split-and-expand prog-and-args) xterm-args))
(defun eexterm-create (channel &optional prog-and-args xterm-args)
"Create an xterm listening on CHANNEL."
(eexterm-create-ne channel (ee-split-and-expand prog-and-args) xterm-args))
(defun eexterm (channel &optional prog-and-args xterm-args)
"Set the default channel to CHANNEL; create an xterm listening on CHANNEL if needed."
(interactive "sDefault channel: ")
(eexterm-ne channel (ee-split-and-expand prog-and-args) xterm-args))
(defalias 'eechannel-xterm 'eexterm)
(defun eexterm-kill (&optional channel sig)
(interactive)
(eechannel-kill (or channel eechannel-default) (or sig "")))
(provide 'eev-channels)
;; Local Variables:
;; coding: raw-text-unix
;; no-byte-compile: t
;; End:
eev-20141011/eev-code.el 0000644 0001750 0001750 00000025340 12203611337 013225 0 ustar edrx edrx ;;; eev-code.el -- `code-c-d', that generates and evaluates Lisp defuns.
;; Copyright (C) 2012 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2013jan07
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;;
;; (find-eev-intro)
;; (find-code-c-d-intro)
;;; Commentary:
;; A simple and flexible implementation of argument lists.
;; Inspired by: (find-node "(cl)Argument Lists")
;; (find-node "(cl)Argument Lists" "&body")
;; See also: (find-elnode "Symbol Type" "`:'")
;; (find-elnode "Constant Variables")
;; The name "tail call" is misleading - this is recursive,
;; but not a tail call in the usual sense.
;;
(defun ee-tail-call (fmt rest)
"An internal function used to support keyword-argument pairs."
(cond ((null rest) "")
((keywordp (car rest))
(apply (intern (format fmt (car rest)))
(cdr rest)))
(t (error "Wrong rest: %S" rest))))
;;; _ _ _
;;; __ _| (_)___| |_ ___
;;; / _` | | / __| __/ __|
;;; | (_| | | \__ \ |_\__ \
;;; \__,_|_|_|___/\__|___/
;;;
(defun ee-aref (alist idx)
"Like `aref', but for alists.
Example: (ee-aref '((1 . one) (2 . two) (3 . three)) 2)
-> two"
(cdr (assoc idx alist)))
(defun ee-adel (alist idx)
"Like `remq', but for alists. This is non-destructive, so wrap it in a setq.
Example: (ee-adel '((1 . one) (2 . two) (3 . three)) 2)
-> ((1 . one) (3 . three))"
(remq (assoc idx alist) alist))
(defun ee-aset (alist idx newelt)
"Like `aset', but for alists. This is non-destructive, so wrap it in a setq.
Example: (ee-aset '((1 . one) (2 . two) (3 . three)) 2 'foo)
-> ((2 . foo) (1 . one) (3 . three))"
(cons (cons idx newelt) (ee-adel alist idx)))
(defun ee-areplace (alist idx newelt)
"Like `ee-aset', but keeping the order.
Examples: (ee-areplace '((1 . one) (2 . two) (3 . three)) 2 'foo)
-> ((1 . one) (2 . foo) (3 . three))
(ee-areplace '((1 . one) (2 . two) (3 . three)) 0 'zero)
-> ((0 . zero) (1 . one) (2 . two) (3 . three))"
(if (ee-aref alist idx)
(progn (setcdr (assoc idx alist) newelt)
alist)
(cons (cons idx newelt) alist)))
;;; _ _ _
;;; ___ ___ __| | ___ ___ __| | _ __ __ _(_)_ __ ___
;;; / __/ _ \ / _` |/ _ \_____ / __|____ / _` |_____| '_ \ / _` | | '__/ __|
;;; | (_| (_) | (_| | __/_____| (_|_____| (_| |_____| |_) | (_| | | | \__ \
;;; \___\___/ \__,_|\___| \___| \__,_| | .__/ \__,_|_|_| |___/
;;; |_|
;; Old: (find-evardescr 'code-c-d-keywords)
;; (find-evariable 'code-c-d-keywords)
(defvar ee-code-c-d-pairs nil
"Each (code-c-d C D) call generates an entry (C (ee-expand D)) here.
A new entry with the same C as a previous one will replace the
previous one. This list is maintained by `ee-code-c-d-add-pair' and
is used by some functions in \"eev-insert.el\".")
(defun ee-code-c-d-add-pair (c d)
(setq ee-code-c-d-pairs (ee-areplace ee-code-c-d-pairs c (list d))))
;;; _ _
;;; ___ ___ __| | ___ ___ __| |
;;; / __/ _ \ / _` |/ _ \_____ / __|____ / _` |
;;; | (_| (_) | (_| | __/_____| (_|_____| (_| |
;;; \___\___/ \__,_|\___| \___| \__,_|
;;;
;; See: (find-code-c-d-intro)
;; code-c-d: top-level functions
;;
(defun code-c-d (c d &rest rest)
"See: (find-code-c-d-intro)
Try this: (find-code-c-d \"CODE\" \"/DIR/\" :info \"INFO\")"
(ee-code-c-d-add-pair c d)
(eval (ee-read (apply 'ee-code-c-d c d rest))))
(defun find-code-c-d (c d &rest rest)
(find-estring-elisp (apply 'ee-code-c-d c d rest)))
(defun ee-code-c-d (c d &rest rest)
(if (stringp (car rest))
(setq rest (cons :info rest)))
(concat (ee-code-c-d-base c d)
(ee-code-c-d-rest rest)))
;; Support for extra arguments
;;
(defun ee-code-c-d-rest (rest)
(ee-tail-call "ee-code-c-d-%S" rest))
(defun ee-code-c-d-base (c d)
(ee-template0 "\
;; {(ee-S `(find-code-c-d ,c ,d ,@rest))}
;; {(ee-S `(ee-code-c-d-base ,c ,d))}
(setq ee-{c}dir \"{d}\")
(setq ee-{c}tagsfile \"{d}TAGS\")
(defun ee-{c}file (str)
(concat (ee-expand ee-{c}dir) str))
(defun ee-use-{c}-tags ()
(setq tags-file-name ee-{c}tagsfile))
(defun find-{c}file (str &rest pos-spec-list)
(interactive (list \"\"))
(ee-use-{c}-tags)
(apply 'find-fline (ee-{c}file str) pos-spec-list))
(defun find-{c}tag (str &rest pos-spec-list)
(ee-use-{c}-tags)
(apply 'ee-find-tag str pos-spec-list))
(defun find-{c}sh (command &rest pos-spec-list)
(apply 'ee-find-xxxsh ee-{c}dir command pos-spec-list))
(defun find-{c}sh0 (command)
(funcall 'ee-find-xxxsh0 ee-{c}dir command))
(defun find-{c}sh00 (command)
(funcall 'ee-find-xxxsh00 ee-{c}dir command))
(defun find-{c}w3m (furl &rest pos-spec-list)
(apply 'find-w3m (ee-{c}file furl) pos-spec-list))
(defun find-{c}grep (grep-command-args &rest pos-spec-list)
(apply 'ee-find-grep ee-{c}dir grep-command-args pos-spec-list))
"))
(defun ee-code-c-d-:info (info &rest rest)
(concat (ee-template0 "
;; {(ee-S `(ee-code-c-d-:info ,info ,@rest))}
(defun find-{c}node (page &rest pos-spec-list)
(interactive (list \"\"))
(setq ee-info-code \"{c}\") ;; for M-h M-i
(setq ee-info-file \"{info}\") ;; for M-h M-i
(apply 'find-node (format \"({info})%s\" page) pos-spec-list))
") (ee-code-c-d-rest rest)))
(defun ee-code-c-d-:linfo (manual &rest rest)
(concat (ee-template0 "
;; {(ee-S `(ee-code-c-d-:linfo ,manual ,@rest))}
(defun find-{c}node (section &rest pos-spec-list)
(interactive (list \"\"))
(apply 'ee-find-node ee-{c}dir \"{manual}\" section pos-spec-list))
") (ee-code-c-d-rest rest)))
(defun ee-code-c-d-:gz (&rest rest)
(concat (ee-template0 "
;; {(ee-S `(ee-code-c-d-:gz ,@rest))}
(defun find-{c}file (str &rest pos-spec-list)
(interactive (list \"\"))
(ee-use-{c}-tags)
(apply 'find-fline-gz (ee-{c}file str) pos-spec-list))
") (ee-code-c-d-rest rest)))
(defun ee-code-c-d-:anchor (&rest rest)
(concat (ee-template0 "
;; {(ee-S `(ee-code-c-d-:anchor ,@rest))}
(defun find-{c} (str &rest pos-spec-list)
(apply 'find-anchor (ee-{c}file str) pos-spec-list))
") (ee-code-c-d-rest rest)))
(defun ee-code-c-d-:wget (url &rest rest)
(concat (ee-template0 "
;; {(ee-S `(ee-code-c-d-:wget ,url ,@rest))}
(defun ee-{c}url (semiurl) (concat \"{url}\" semiurl))
(defun find-{c}wget (semiurl &rest pos-spec-list)
(interactive (list \"\"))
(apply 'find-wget (ee-{c}url semiurl) pos-spec-list))
") (ee-code-c-d-rest rest)))
(defun ee-code-c-d-:grep (&rest rest) (ee-code-c-d-rest rest)) ; compat
;; support functions
;;
(defun ee-find-node (dir manual page &rest pos-spec-list)
(apply 'find-node (format "(%s%s)%s" dir manual page) pos-spec-list))
(defun ee-find-grep (dir grep-command-args &rest pos-spec-list)
"Example: (ee-find-grep ee-eetcdir \"grep -niH -e tetris *\")
Note: the POS-SPEC-LIST arguments are currently not used."
(let ((default-directory (ee-expand (or dir default-directory))))
(grep grep-command-args)))
(defun ee-find-xxxsh (dir command &rest pos-spec-list)
"Run COMMAND at DIR and display the result. See `code-c-d'."
(apply 'find-sh (format "cd %s\n%s" dir command) pos-spec-list))
(defun ee-find-xxxsh0 (dir command)
"Run COMMAND at DIR and return the result. See `code-c-d'."
(find-sh0 (format "cd %s\n%s" dir command)))
(defun ee-find-xxxsh00 (dir command)
"Run COMMAND at DIR and return the result. See `code-c-d'."
(find-sh00 (format "cd %s\n%s" dir command)))
(defun ee-find-tag (tag &rest pos-spec-list)
(let ((tags-add-tables nil))
(find-tag tag))
(ee-goto-rest pos-spec-list))
;; a test
;; (find-estring-elisp (ee-code-c-d-base "@@@" "!!!"))
;; (find-estring-elisp (ee-code-c-d "CCC" "DDD"))
;;; _ _
;;; ___ ___ __| | ___ ___ __| |___
;;; / __/ _ \ / _` |/ _ \_____ / __|____ / _` / __|
;;; | (_| (_) | (_| | __/_____| (_|_____| (_| \__ \
;;; \___\___/ \__,_|\___| \___| \__,_|___/
;;;
;; Some default `code-c-d's (debian-centric)
(defun ee-locate-library (fname)
(if (locate-library fname)
(file-name-directory (locate-library fname))))
(defvar ee-emacs-lisp-directory
(or (ee-locate-library "loadup.el")
(format "/usr/share/emacs/%d.%d/lisp/"
emacs-major-version emacs-minor-version)))
(defvar ee-emacs-leim-directory
(or (ee-locate-library "leim-list.el")
(format "/usr/share/emacs/%d.%d/leim/"
emacs-major-version emacs-minor-version)))
(code-c-d "e" ee-emacs-lisp-directory "emacs" :gz) ; (find-enode "Top")
(code-c-d "el" ee-emacs-lisp-directory "elisp" :gz) ; (find-elnode "Top")
(code-c-d "eli" ee-emacs-lisp-directory "eintr" :gz) ; (find-elinode "Top")
(code-c-d "eleim" ee-emacs-leim-directory :gz)
(code-c-d "equail" (ee-eleimfile "quail/") :gz)
(code-c-d "eetc" data-directory :gz)
(code-c-d "eev" (ee-locate-library "eev-code.el") :anchor) ; (find-eev "")
;; (find-efile "")
;; (find-equailfile "")
;; (find-equailfile "latin-ltx.el")
(code-c-d "ud" "/usr/share/doc/" :gz) ; (find-udfile "bash/")
(code-c-d "vldi" "/var/lib/dpkg/info/") ; (find-vldifile "bash.list")
(provide 'eev-code)
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "«%s»"
;; ee-anchor-format: "defun %s "
;; no-byte-compile: t
;; End:
eev-20141011/eev-edit.el 0000644 0001750 0001750 00000016674 12070745304 013256 0 ustar edrx edrx ;;; eev-edit.el -- tools for editing (mainly refining) elisp hyperlinks.
;; Copyright (C) 2012 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2012dec26
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;; (find-eev-intro)
;;; Commentary:
;; See:
;; (find-eev-intro)
;; (find-eval-intro)
;; (find-eval-intro "Refining hyperlinks")
;; (find-eevgrep "grep -niH -e m-- *.el")
;; (find-angg ".emacs" "ee-shrink-hyperlink-at-eol")
;; (find-eevfile "eev-mode.el" "Keys for editing hyperlinks:")
;; (find-eevfile "eev-insert.el" "defun ee-ill")
;; (find-eevgrep "grep -nH -e duplicate *.el")
;;; _ _ _ _
;;; __| |_ _ _ __ | (_) ___ __ _| |_ ___
;;; / _` | | | | '_ \| | |/ __/ _` | __/ _ \
;;; | (_| | |_| | |_) | | | (_| (_| | || __/
;;; \__,_|\__,_| .__/|_|_|\___\__,_|\__\___|
;;; |_|
(define-key eev-mode-map "\M-h\M-2" 'ee-duplicate-this-line)
(defun ee-duplicate-this-line ()
"Duplicate the current line (without any changes to the kill ring)."
(interactive)
(let ((line (buffer-substring (ee-bol) (ee-eol))))
(save-excursion (beginning-of-line) (insert-before-markers line "\n"))))
;;; _
;;; _ _ __ _ _ __ | | __
;;; | | | |/ _` | '_ \| |/ /
;;; | |_| | (_| | | | | <
;;; \__, |\__,_|_| |_|_|\_\
;;; |___/
(define-key eev-mode-map "\M-h\M-y" 'ee-yank-pos-spec)
(defun ee-yank-pos-spec ()
"Append the top of the kill ring to a hyperlink sexp, as a Lisp string.
This command is useful for \"refining elisp hyperlinks\" by adding a
pos-spec argument to them. Here's an example; if you are using the
default `eev-mode-map' keybindings then
`M-h M-i' runs `find-einfo-links',
`M-h M-2' runs `ee-duplicate-this-line', and
`M-h M-y' runs `ee-yank-pos-spec'.
Suppose that you are visiting the info node below,
(find-enode \"Lisp Eval\")
and you find some interesting information in that page, close to
an occurrence of the string \"`defvar'\". You mark that string,
add it to the kill-ring with `M-w', then type `M-h M-i', go to
the line that contains
# (find-enode \"Lisp Eval\")
and then you type `M-h M-2 M-h M-y'; it becomes these two lines:
# (find-enode \"Lisp Eval\")
# (find-enode \"Lisp Eval\" \"`defvar'\")
Now you check that the second line points to where you wanted,
and you copy that hyperlink to a more permanent place."
(interactive)
(goto-char (1- (point-at-eol))) ; put point before the ")"
(insert " " (ee-pp0 (ee-last-kill)))) ; insert pos-spec
;;; _ _ _
;;; ___| |__ _ __(_)_ __ | | __
;;; / __| '_ \| '__| | '_ \| |/ /
;;; \__ \ | | | | | | | | | <
;;; |___/_| |_|_| |_|_| |_|_|\_\
;;;
;; «ee-shrink-hyperlink-at-eol» (to ".ee-shrink-hyperlink-at-eol")
;;
(define-key eev-mode-map "\M-h\M--" 'ee-shrink-hyperlink-at-eol)
(defun ee-shrink-sexp (sexp)
"If the car of SEXP of the form `find-xxxfile', reduce it to `find-xxx'."
(if (eq (car sexp) 'find-esfile)
`(find-es ,(substring (nth 1 sexp) 0 -2) ,@(cddr sexp))
(let* ((headname (symbol-name (car sexp)))
(last4chars (substring headname -4))
(-last4chars (substring headname 0 -4)))
(if (equal last4chars "file")
`(,(intern -last4chars) ,@(cdr sexp))))))
(defun ee-shrink-hyperlink-at-eol ()
(interactive)
(end-of-line)
(let* ((beg (save-excursion (ee-backward-sexp)))
(sexp (read (buffer-substring beg (point))))
(shrunksexp (ee-shrink-sexp sexp)))
(when shrunksexp
(delete-region beg (point))
(insert (ee-pp0 shrunksexp)))))
;;; __ _ _
;;; / _| (_)_ __ _ __ ___ _ __ ___
;;; | |_| | | '_ \ _____| '_ \/ __| '_ \ / _ \
;;; | _| | | |_) |_____| |_) \__ \ | | | __/
;;; |_| |_|_| .__/ | .__/|___/_| |_|\___|
;;; |_| |_|
;; (find-efunctiondescr 'eemklinks-yank-pos-spec)
;; (find-eevfile "eev-insert.el" "defun ee-ill")
(define-key eev-mode-map "\M-s" 'ee-flip-psne-ness)
(defun ee-flip-psne-ness ()
(interactive)
(if (search-forward-regexp "\\$S/\\(https?\\|ftp\\)/\\|\\(https?\\|ftp\\)://")
(cond ((match-string 1) (replace-match "\\1://"))
((match-string 2) (replace-match "$S/\\2/")))))
;;; _ _ _ _ _ _ _ _
;;; __ _| | __| (_) | (_)___| |_ | (_)_ __ ___
;;; \ \ / / |/ _` | |_____| | / __| __|____| | | '_ \ / _ \
;;; \ V /| | (_| | |_____| | \__ \ ||_____| | | | | | __/
;;; \_/ |_|\__,_|_| |_|_|___/\__| |_|_|_| |_|\___|
;;;
;; This is a hack.
;;
;; In a Debian system, for each installed package named xxxx there is
;; an associated file, at /var/lib/dpkg/info/xxxx.list - let's call
;; that the "vldi list" associated to the package xxxx - that lists
;; all the files installed by that package...
;;
;; To convert a vldi list to hyperlinks, copy it to a read-write
;; buffer and run M-I on each of its lines. More details later - this
;; is a hack. =\
;;
;; (find-eev "eev-insert.el" "ee-ill")
;;
;; M-I: vldi-list-line
(define-key eev-mode-map "\M-I" 'eewrap-vldi-list-line)
(defun eewrap-vldi-list-line () (interactive)
"Convert a filename at the current line into a hyperlink, and go down.
Supports `find-man', `find-udfile', and `find-fline' hyperlinks.
This function recognizes lines containing directory names, and
handles them in the following way: if the current line contains a
directory name, say, /foo/bar, and the next line contains the
name of a file or a directory in /foo/bar, say, /foo/bar/plic,
then just delete the current line."
(beginning-of-line)
(if (looking-at "^\\(.*\\)\n\\1/") ; a directory
(delete-region (point) (progn (ee-next-line 1) (point)))
(ee-this-line-wrapn 1 'ee-wrap-vldi-list-line)))
(defun ee-wrap-vldi-list-line (line)
"An internal function used by `eewrap-vldi-list-line'."
(if (string-match "^.*/man./\\([^/]+\\)\\.\\([0-9A-Za-z]+\\)\\.gz$" line)
(format "%s(find-man \"%s %s\")"
ee-H (match-string 2 line) (match-string 1 line))
(if (string-match "^/usr/share/doc/\\(.*\\)$" line)
(format "%s(find-udfile \"%s\")" ee-H (match-string 1 line))
(format "%s(find-fline \"%s\")" ee-H line))))
;; (find-vldifile "bash.list")
(provide 'eev-edit)
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "«%s»"
;; ee-anchor-format: "defun %s "
;; no-byte-compile: t
;; End:
eev-20141011/eev-elinks.el 0000644 0001750 0001750 00000125351 12247136231 013606 0 ustar edrx edrx ;;; eev-elinks.el --- `find-efunction-links' and other `find-e*-links'
;; Copyright (C) 2012,2013 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2013nov18
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;;
;; (find-eev-intro)
;; (find-links-intro)
;;; Commentary:
;; See this for a (rough) classification of eev's hyperlink functions
;; into several classes:
;;
;; (find-links-intro "Basic and non-basic hyperlinks")
;;
;; In this file we define `find-elinks' and several functions based on
;; it which generate relatively simple elisp hyperlinks buffers -
;; buffers which are mostly composed of elisp hyperlinks.
;;
;; The "more complex" `find-elinks'-based functions are the ones which
;; use `ee-template0'. They are defined here:
;;
;; (find-eevfile "eev-tlinks.el")
;;
;; Here's one example of each function in this file:
;; [to be done]
;; «.find-elinks» (to "find-elinks")
;; «.find-efunction-links» (to "find-efunction-links")
;; «.find-evariable-links» (to "find-evariable-links")
;; «.find-ekey-links» (to "find-ekey-links")
;; «.find-elongkey-links» (to "find-elongkey-links")
;; «.find-einfo-links» (to "find-einfo-links")
;; «.ee-code-c-d-pairs-eval» (to "ee-code-c-d-pairs-eval")
;; «.ee-find-xxxfile-sexps» (to "ee-find-xxxfile-sexps")
;; «.find-file-links» (to "find-file-links")
;; «.find-grep-links» (to "find-grep-links")
;; «.find-ekbmacro-links» (to "find-ekbmacro-links")
;; «.find-pdflike-page-links» (to "find-pdflike-page-links")
;; «.ee-hyperlink-prefix» (to "ee-hyperlink-prefix")
;; «.find-eface-links» (to "find-eface-links")
;; «.find-color-links» (to "find-color-links")
;; «.find-here-links» (to "find-here-links")
;;; _ _ _
;;; __ _ _ __ ___ _ _ _ __ __| | _ __ ___ (_)_ __ | |_
;;; / _` | '__/ _ \| | | | '_ \ / _` |_____| '_ \ / _ \| | '_ \| __|
;;; | (_| | | | (_) | |_| | | | | (_| |_____| |_) | (_) | | | | | |_
;;; \__,_|_| \___/ \__,_|_| |_|\__,_| | .__/ \___/|_|_| |_|\__|
;;; |_|
;; (find-eapropos "around-point")
;; (find-elnode "Index" "* thing-at-point:")
;; (find-efunction 'thing-at-point)
;; (find-efile "thingatpt.el")
(defun ee-stuff-around-point0 (chars)
(interactive "MChars: \np") ; for tests
(save-excursion
(let* ((e (progn (skip-chars-forward chars) (point)))
(s (progn (skip-chars-backward chars) (point))))
(buffer-substring s e))))
(defun ee-stuff-around-point (chars)
(interactive "MChars: \np") ; for tests
(ee-no-properties (ee-stuff-around-point0 chars)))
(defun ee-debpkgname-around-point ()
"Return the name of the Debian package around point.
This function is not very smart."
(ee-stuff-around-point "a-z0-9-+."))
(defun ee-debpkgname-ask (&optional prompt)
"Ask for the name of a Debian package; the default is the debpkgname at point."
(read-string (or prompt "Debian package name: ")
(ee-debpkgname-around-point)))
(defun ee-manpagename-around-point ()
"Return the manpagename around point.
This function is not very smart - it doesn't understand section names."
(interactive)
(ee-stuff-around-point "A-Za-z0-9-+_:."))
(defun ee-manpagename-ask (&optional prompt)
"Ask for the name of a manpage; the default is the manpage name at point."
(interactive)
(read-string (or prompt "Manpage: ")
(ee-manpagename-around-point)))
;;; __ _ _ _ _ _
;;; / _(_)_ __ __| | ___| (_)_ __ | | _____
;;; | |_| | '_ \ / _` |_____ / _ \ | | '_ \| |/ / __|
;;; | _| | | | | (_| |_____| __/ | | | | | <\__ \
;;; |_| |_|_| |_|\__,_| \___|_|_|_| |_|_|\_\___/
;;;
;; «find-elinks» (to ".find-elinks")
;; A test:
;; (find-elinks '("a" nil (b c) (d "e")))
(defun ee-remove-nils (list)
"Return a list like LIST, but without the `nil's."
(let (newlist)
(mapc (lambda (e) (if e (setq newlist (cons e newlist))))
list)
(nreverse newlist)))
(defun ee-links-to-string0 (list)
"Convert a LIST of strings and sexps to a big string."
(mapconcat (lambda (o) (if (stringp o) o (ee-HS o)))
(ee-remove-nils list)
"\n"))
(defun ee-links-to-string (list)
"Convert a LIST of strings and sexps to a big string (newline-terminated)."
(concat (ee-links-to-string0 list)
"\n"))
(defun find-elinks (links &rest pos-spec-list)
"Visit a temporary buffer containing LINKS converted to hyperlink lines."
(let ((ee-buffer-name (or ee-buffer-name "*Elisp hyperlinks*")))
(apply 'find-estring (ee-links-to-string links) pos-spec-list)))
(defun find-elinks-elisp (links &rest pos-spec-list)
"Visit a temporary buffer containing LINKS converted to hyperlink lines.
The buffer is put in Emacs Lisp mode."
(let ((ee-buffer-name (or ee-buffer-name "*Elisp hyperlinks*"))
(ee-hyperlink-prefix ";; "))
(apply 'find-estring-elisp (ee-links-to-string links) pos-spec-list)))
;;; __ _ _ __ _ _
;;; / _(_)_ __ __| | ___ / _|_ _ _ __ ___| |_(_) ___ _ __
;;; | |_| | '_ \ / _` |_____ / _ \ |_| | | | '_ \ / __| __| |/ _ \| '_ \
;;; | _| | | | | (_| |_____| __/ _| |_| | | | | (__| |_| | (_) | | | |
;;; |_| |_|_| |_|\__,_| \___|_| \__,_|_| |_|\___|\__|_|\___/|_| |_|
;;;
;; «find-efunction-links» (to ".find-efunction-links")
;; (find-find-links-links "\\M-f" "efunction" "f")
;; A test: (find-efunction-links 'next-line)
;; (eek "M-h M-f next-line")
(define-key eev-mode-map "\M-h\M-f" 'find-efunction-links)
(defun find-efunction-links (&optional f &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks related to the function F."
(interactive (find-function-read))
(apply 'find-elinks
`((find-efunction-links ',f ,@pos-spec-list)
,@(ee-find-efunction-links f)
)
pos-spec-list))
(defun ee-find-efunction-links (f)
"Return a list of hyperlinks for F (a function symbol).
This is an internal function used by `find-efunction-links' and
`find-ekey-links'."
`((where-is ',f)
(describe-function ',f)
(find-efunctiondescr ',f)
(find-efunction ',f)
(find-efunctionpp ',f)
(find-efunctiond ',f)
;; (find-eCfunction ',f) ; obsolete
(find-estring (documentation ',f))
(find-estring (documentation ',f t))
(symbol-file ',f 'defun)
(find-fline (symbol-file ',f 'defun))
""
,@(if (commandp f)
`((Info-goto-emacs-command-node ',f)
(find-enode "Command Index" ,(format "* %S:" f))
))
(find-elnode "Index" ,(format "* %S:" f))
))
;;; __ _ _ _ _ _
;;; / _(_)_ __ __| | _____ ____ _ _ __(_) __ _| |__ | | ___
;;; | |_| | '_ \ / _` |_____ / _ \ \ / / _` | '__| |/ _` | '_ \| |/ _ \
;;; | _| | | | | (_| |_____| __/\ V / (_| | | | | (_| | |_) | | __/
;;; |_| |_|_| |_|\__,_| \___| \_/ \__,_|_| |_|\__,_|_.__/|_|\___|
;;;
;; «find-evariable-links» (to ".find-evariable-links")
;; (find-find-links-links "\\M-v" "evariable" "var")
;; A test: (find-evariable-links 'line-move-visual)
;; (eek "M-h M-v line-move-visual")
(define-key eev-mode-map "\M-h\M-v" 'find-evariable-links)
(defun find-evariable-links (var &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks for foo."
(interactive (find-function-read 'variable))
(apply 'find-elinks
`((find-evariable-links ',var ,@pos-spec-list)
;; Convention: the first sexp always regenerates the buffer.
,var
(describe-variable ',var)
(find-evardescr ',var)
(find-evariable ',var)
(find-epp ,var)
""
(find-enode "Variable Index" ,(format "* %S:" var))
(find-elnode "Index" ,(format "* %S:" var))
)
pos-spec-list))
;;; __ _ _ _
;;; / _(_)_ __ __| | ___| | _____ _ _
;;; | |_| | '_ \ / _` |_____ / _ \ |/ / _ \ | | |
;;; | _| | | | | (_| |_____| __/ < __/ |_| |
;;; |_| |_|_| |_|\__,_| \___|_|\_\___|\__, |
;;; |___/
;;
;; «find-ekey-links» (to ".find-ekey-links")
;; (find-find-links-links "\\M-k" "ekey" "key")
;; A test: (find-ekey-links "\C-x2")
;; (eek "M-h M-k C-x 2")
(define-key eev-mode-map "\M-h\M-k" 'find-ekey-links)
(defun ee-format-kbd-macro (key)
"Example: (ee-format-kbd-macro [down]) --> \" ;; next-line\""
(replace-regexp-in-string "[ \t][ \t]+" " " (format-kbd-macro key t)))
(defun find-ekey-links (key &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks related to the key sequence KEY."
(interactive "kElisp hyperlinks for key: ")
(let ((longkey (format-kbd-macro key))
(longkey+ (ee-format-kbd-macro key))
(f (key-binding key)))
(apply 'find-elinks
`((find-ekey-links ,key ,@pos-spec-list)
;; Convention: the first sexp always regenerates the buffer.
(find-ekey-links ,key)
(eek ,(format "M-h M-k %s" longkey))
(eek ,(format "M-h M-k %s" longkey+))
""
(find-elongkey-links ,longkey)
(find-elongkey-links ,longkey+)
(find-efunction-links ',f)
""
,@(ee-find-eboundkey-links key f)
)
pos-spec-list)))
;; «find-elongkey-links» (to ".find-elongkey-links")
;; A test: (find-elongkey-links "C-x 2")
;; (eek "M-h M-k C-x 2")
(defun find-elongkey-links (longkey &rest pos-spec-list)
"Like `find-ekey-links', but LONGKEY is a key sequence \"spelled out\".
Example: (find-elongkey-links \"M-h M-k\")
See `read-kbd-macro' and `edmacro-mode' for the format."
(interactive "sElisp hyperlinks for key (long format): ")
(let* ((key (read-kbd-macro longkey))
(f (key-binding key)))
(apply 'find-elinks
`((find-elongkey-links ,longkey)
(find-ekey-links ,key)
(find-efunction-links ',f)
""
,@(ee-find-eboundkey-links key f)
)
pos-spec-list)))
(defun ee-find-eboundkey-links (key f)
"From KEY and its binding, F, produce a list of hyperlinks.
This is an internal function used by `find-ekey-links' and
`find-elongkey-links'."
`((where-is ',f)
(describe-function ',f)
(find-efunctiondescr ',f)
(find-efunction ',f)
(find-efunctionpp ',f)
(find-efunctiond ',f)
(find-estring (documentation ',f))
(find-estring (documentation ',f t))
""
(describe-key ,key)
(describe-key-briefly ,key)
(find-ekeydescr ,key)
(Info-goto-emacs-key-command-node ,key)
(Info-goto-emacs-command-node ',f)
(find-enode "Command Index" ,(format "* %S:" f))
(find-elnode "Index" ,(format "* %S:" f))
""
(key-description ,key)
(format-kbd-macro ,key)
(format-kbd-macro ,key t)
(ee-format-kbd-macro ,key)
(key-binding ,key)
))
;;; __ _ _ _ __
;;; / _(_)_ __ __| | ___(_)_ __ / _| ___
;;; | |_| | '_ \ / _` |_____ / _ \ | '_ \| |_ / _ \
;;; | _| | | | | (_| |_____| __/ | | | | _| (_) |
;;; |_| |_|_| |_|\__,_| \___|_|_| |_|_| \___/
;;;
;; «find-einfo-links» (to ".find-einfo-links")
;; (find-find-links-links "\\M-i" "einfo" "")
;; A test: (progn (find-enode "Lisp Eval") (find-einfo-links))
;; (progn (find-enode "Lisp Eval") (eek "M-h M-i"))
(define-key eev-mode-map "\M-h\M-i" 'find-einfo-links)
(defvar ee-info-file "")
(defun ee-infop () (get-buffer "*info*"))
(defun ee-info-node () (with-current-buffer "*info*" Info-current-node))
(defun ee-info-book+ () (with-current-buffer "*info*" Info-current-file))
(defun ee-info-book- () (file-name-nondirectory (ee-info-book+)))
(defun ee-info-file- () (file-name-nondirectory ee-info-file))
(defun ee-info-shortp () (string= (ee-info-book-) (ee-info-file-)))
(defun ee-info-shortf () (ee-intern "find-%snode" ee-info-code))
(defun ee-info-fullnode () (format "(%s)%s" (ee-info-book-) (ee-info-node)))
(defun ee-find-info-links ()
`((info ,(ee-info-fullnode))
(find-node ,(ee-info-fullnode))
,(if (ee-info-shortp)
(list (ee-info-shortf) (ee-info-node)))))
(defun ee-intro-stem (&optional bufname)
(setq bufname (or bufname (buffer-name (current-buffer))))
(if (string-match "^\\*(find-\\(.*\\)-intro)\\*$" bufname)
(match-string 1 bufname)))
;; (defun ee-find-intro-links (&optional stem)
;; `((,(ee-intern "find-%s-intro" (or stem (ee-intro-stem))))))
(defun ee-find-intro-links (&optional stem)
(setq stem (or stem (ee-intro-stem)))
(let ((find-xxx-intro (ee-intern "find-%s-intro" stem))
(url (format "http://angg.twu.net/eev-intros/find-%s-intro.html" stem)))
`(,(ee-H url)
(,find-xxx-intro)
)))
;; A test: (ee-intro-stem "*(find-foo-intro)*")
(defun find-einfo-links (&optional intro &rest rest)
"Visit a temporary buffer containing hyperlinks to the current info page.
When possible, try to produce also a shorter hyperlink, like the last one in:
(info \"(bashref)Pipelines\")
(find-node \"(bashref)Pipelines\")
(find-bashnode \"Pipelines\")
The hack for generating the shorter hyperlink uses the global
variables `ee-info-code' and `ee-info-file' - see:
(progn
(find-code-c-d \"bash\" \"/usr/share/doc/bash/examples/\" \"bashref\")
(ee-goto-position \"ee-info-code\"))
As an extra hack, if this function is called from a \"*(find-???-intro)*\"
buffer, also generate a link to that buffer."
(interactive)
(setq intro (or intro (ee-intro-stem (buffer-name (current-buffer)))))
(apply 'find-elinks `(
;; Convention: the first sexp always regenerates the buffer.
(find-einfo-links ,intro ,@rest)
;; Body:
""
,@(if (ee-infop)
(ee-find-info-links)
'("[No \"*info*\" buffer]"))
""
,@(if intro
;; (list (ee-intern "find-%s-intro" intro))
(ee-find-intro-links)
;; else: "[Not invoked from a \"*find-xxx-intro*\" buffer]"
)
) rest))
;;; _ _ _
;;; ___ ___ __| | ___ ___ __| | _ __ __ _(_)_ __ ___
;;; / __/ _ \ / _` |/ _ \_____ / __|____ / _` |_____| '_ \ / _` | | '__/ __|
;;; | (_| (_) | (_| | __/_____| (_|_____| (_| |_____| |_) | (_| | | | \__ \
;;; \___\___/ \__,_|\___| \___| \__,_| | .__/ \__,_|_|_| |___/
;;; |_|
;;
;; «ee-code-c-d-pairs-eval» (to ".ee-code-c-d-pairs-eval")
(defun ee-filter (f list)
"Return the elements of LIST for which (F elt) is true.
Actually return a list of `(F elt)'s."
(ee-remove-nils (mapcar f list)))
(defun ee-prefixp (prefix str)
"Return t if STR begins with PREFIX."
(and (<= (length prefix) (length str))
(equal prefix (substring str 0 (length prefix)))))
(defun ee-remove-prefix (prefix str)
"Example: (ee-remove-prefix \"ab\" \"abcde\") --> \"cde\""
(substring str (length prefix)))
(defun ee-replace-prefix0 (prefix newprefix fname)
(if (ee-prefixp prefix fname)
(concat newprefix (ee-remove-prefix prefix fname))))
(defun ee-replace-prefix (prefix newprefix fname)
(ee-replace-prefix0 (ee-expand prefix) newprefix (ee-expand fname)))
(defun ee-intern (fmt &rest args)
(intern (apply 'format fmt args)))
(defun ee-code-c-d-pairs-eval (fname code)
"For each entry (C D) in `ee-code-c-d-pairs' for which D is a prefix of FNAME,
evaluate f in the context of a big `let', and return the result."
(let ((efname (ee-expand fname)))
(ee-filter (lambda (c-d)
(let* ((c (car c-d))
(d (cadr c-d))
(ed (ee-expand d)))
(if (ee-prefixp ed efname)
(let ((fname- (ee-remove-prefix ed efname)))
(eval code)))))
ee-code-c-d-pairs)))
;; «ee-find-xxxfile-sexps» (to ".ee-find-xxxfile-sexps")
(defun ee-find-xxxfile-sexps (fname)
(ee-code-c-d-pairs-eval
fname
'(list (ee-intern "find-%sfile" c) fname-)))
;;; __ _ _ __ _ _ _ _ _
;;; / _(_)_ __ __| | / _(_) | ___ | (_)_ __ | | _____
;;; | |_| | '_ \ / _` |_____| |_| | |/ _ \_____| | | '_ \| |/ / __|
;;; | _| | | | | (_| |_____| _| | | __/_____| | | | | | <\__ \
;;; |_| |_|_| |_|\__,_| |_| |_|_|\___| |_|_|_| |_|_|\_\___/
;;;
;; «find-file-links» (to ".find-file-links")
;; (find-find-links-links "f" "file" "fname")
;; A test: (find-file-links "~/tmp/foo")
(define-key eev-mode-map "\M-hf" 'find-file-links)
(defun ee-if-prefixp (d newd fname code)
"An internal function used by `find-file-links'."
(let* ((ed (ee-expand d))
(efname (ee-expand fname)))
(if (ee-prefixp ed efname)
(let* ((fname- (ee-remove-prefix ed efname))
(fname+ (concat newd fname-)))
(eval code)))))
(defun ee-find-file-links (&optional fname)
(setq fname (or fname (or (buffer-file-name) default-directory)))
`(,(ee-if-prefixp "~/" "~/" fname '`(find-fline ,fname+))
,(ee-if-prefixp "$S/http/" "http://" fname '(ee-H fname+))
,(ee-if-prefixp "$S/shttp/" "shttp://" fname '(ee-H fname+))
""
(find-file ,fname) ; non-refinable
(find-fline ,fname) ; refinable
,@(ee-find-xxxfile-sexps (ee-expand fname))
;;
,@(ee-find-file-extra-links fname) ; customizable by the user
))
(defun ee-find-file-extra-links (fname) ()) ; customize this
(defun find-file-links (fname &rest pos-spec-list)
(interactive (list (or (buffer-file-name) default-directory)))
(apply 'find-elinks
`((find-file-links ,fname ,@pos-spec-list)
,@(ee-find-file-links fname)
)
pos-spec-list))
;;; __ _ _ _ _ _
;;; / _(_)_ __ __| | __ _ _ __ ___ _ __ | (_)_ __ | | _____
;;; | |_| | '_ \ / _` |_____ / _` | '__/ _ \ '_ \ _____| | | '_ \| |/ / __|
;;; | _| | | | | (_| |_____| (_| | | | __/ |_) |_____| | | | | | <\__ \
;;; |_| |_|_| |_|\__,_| \__, |_| \___| .__/ |_|_|_| |_|_|\_\___/
;;; |___/ |_|
;;
;; «find-grep-links» (to ".find-grep-links")
;; (find-find-links-links "\\M-g" "grep" "")
;; Tests:
;; (ee-find-grep-commands)
;; (ee-find-grep-functions "~/eev-current/")
;; (ee-find-grep-links '(find-agrep find-bgrep) '("grep a *" "grep b *"))
;; (find-grep-links)
;;
(define-key eev-mode-map "\M-h\M-g" 'find-grep-links)
(defun ee-first-n-elements (n list)
"Example: (ee-first-n-elements 2 '(a b c d e f)) ==> (a b)"
(if (and (> n 0) list)
(cons (car list)
(ee-first-n-elements (1- n) (cdr list)))))
(defun ee-find-grep-functions (dir)
"An internal function used by `find-grep-links'."
(ee-code-c-d-pairs-eval dir '(ee-intern "find-%sgrep" c)))
(defun ee-find-grep-commands ()
"An internal function used by `find-grep-links'."
(cons "grep -nH -e _ *" (ee-first-n-elements 4 grep-history)))
(defun ee-find-grep-links0 (find-xxxgreps grep-commands)
"An internal function used by `find-grep-links'."
(let (result)
(dolist (head find-xxxgreps)
(dolist (command grep-commands)
(setq result (cons `(,head ,command) result))))
(nreverse result)))
(defun ee-find-grep-links ()
(ee-find-grep-links0
(ee-find-grep-functions default-directory)
(ee-find-grep-commands)))
(defun find-grep-links (&rest pos-spec-list)
"Visit a temporary buffer containing `find-xxxgrep' sexps."
(interactive)
(apply 'find-elinks
`((find-grep-links ,@pos-spec-list)
;; Convention: the first sexp always regenerates the buffer.
(find-efunction 'find-grep-links)
""
,@(ee-find-grep-links)
)
pos-spec-list))
;;; __ _ _
;;; / _(_)_ __ __| | _ __ ___ __ _ ___ _ __ ___
;;; | |_| | '_ \ / _` |_____| '_ ` _ \ / _` |/ __| '__/ _ \
;;; | _| | | | | (_| |_____| | | | | | (_| | (__| | | (_) |
;;; |_| |_|_| |_|\__,_| |_| |_| |_|\__,_|\___|_| \___/
;;;
;; «find-ekbmacro-links» (to ".find-ekbmacro-links")
;; (find-find-links-links "M" "macro" "")
;; (find-efunction 'find-ekbmacro-links)
(define-key eev-mode-map "\M-hM" 'find-ekbmacro-links)
(defun find-ekbmacro-links () (interactive)
(find-elinks `(
(find-ekbmacro-links)
""
(format-kbd-macro last-kbd-macro)
(setq last-kbd-macro (kbd ,(format-kbd-macro last-kbd-macro)))
""
(find-enode "Keyboard Macros")
(find-enode "Edit Keyboard Macro")
(eek "M-h M-k C-x C-k C-e ;; kmacro-edit-macro-repeat")
(eek " C-x C-k C-e ;; kmacro-edit-macro-repeat")
(eek "M-h M-k C-x C-k l ;; kmacro-edit-lossage")
(eek " C-x C-k l ;; kmacro-edit-lossage")
)))
;;; _ __ _ _ _
;;; _ __ __| |/ _| (_) | _____ _ __ __ _ __ _ ___
;;; | '_ \ / _` | |_| | | |/ / _ \_____| '_ \ / _` |/ _` |/ _ \
;;; | |_) | (_| | _| | | < __/_____| |_) | (_| | (_| | __/
;;; | .__/ \__,_|_| |_|_|_|\_\___| | .__/ \__,_|\__, |\___|
;;; |_| |_| |___/
;; «find-pdflike-page-links» (to ".find-pdflike-page-links")
;; (find-efunction 'count-lines)
;;
(defun ee-count-formfeeds (start end)
(save-excursion
(save-restriction
(narrow-to-region start end)
(goto-char (point-min))
(save-match-data
(let ((done 0))
(while (re-search-forward "[\f]" nil t 1)
(setq done (+ 1 done)))
done)))))
(defun ee-current-page ()
(+ 1 (ee-count-formfeeds (point-min) (point))))
(defun ee-last-kill ()
(if (stringp (car kill-ring))
(ee-no-properties (car kill-ring))))
(defun ee-region ()
(if (region-active-p)
(buffer-substring-no-properties (point) (mark))))
(defun ee-region-or-last-kill ()
(or (ee-region) (ee-last-kill)))
;; (find-find-links-links "\\M-p" "pdflike-page" "page bufname offset")
(define-key eev-mode-map "\M-h\M-p" 'find-pdflike-page-links)
(defun ee-pdflike-page-links (&optional page bufname offset)
(setq page (or page (ee-current-page)))
(setq bufname (or bufname (buffer-name)))
(setq offset (or offset ee-page-offset))
(let* ((c ee-page-c)
(fname ee-page-fname)
(find-cpage (ee-intern "find-%spage" c))
(find-ctext (ee-intern "find-%stext" c))
(kill (or (ee-region-or-last-kill) ""))
(page- (- page offset))
)
`((,find-cpage ,page)
(,find-ctext ,page)
(,find-cpage (+ ,offset ,page-))
(,find-ctext (+ ,offset ,page-))
""
(,find-cpage ,page ,kill)
(,find-ctext ,page ,kill)
(,find-cpage (+ ,offset ,page-) ,kill)
(,find-ctext (+ ,offset ,page-) ,kill)
""
(code-pdf ,c ,fname)
(code-pdf-text ,c ,fname ,offset)
,(ee-HS bufname)
)))
(defun find-pdflike-page-links (&optional page bufname offset &rest rest)
"Visit a temporary buffer containing hyperlinks to a pdf-like document.
See: (find-pdf-like-intro)
(find-pdf-like-intro \"refining hyperlinks to pages\")"
(interactive)
(setq page (or page (ee-current-page)))
(setq bufname (or bufname (buffer-name)))
(setq offset (or offset ee-page-offset))
(let* ((c ee-page-c)
(fname ee-page-fname)
(find-cpage (ee-intern "find-%spage" c))
(find-ctext (ee-intern "find-%stext" c))
(kill (or (ee-last-kill) ""))
(page- (- page offset))
)
;;
'(apply 'find-elinks `(
(find-pdflike-page-links ,page ,bufname ,offset ,@rest)
(find-efunction 'find-pdflike-page-links)
""
(,find-cpage ,page)
(,find-ctext ,page)
(,find-cpage (+ ,offset ,page-))
(,find-ctext (+ ,offset ,page-))
""
(,find-cpage ,page ,kill)
(,find-ctext ,page ,kill)
(,find-cpage (+ ,offset ,page-) ,kill)
(,find-ctext (+ ,offset ,page-) ,kill)
""
(code-pdf ,c ,fname)
(code-pdf-text ,c ,fname ,offset)
,(ee-HS bufname)
) rest)
;;
(apply 'find-elinks `(
(find-pdflike-page-links ,page ,bufname ,offset ,@rest)
(find-efunction 'find-pdflike-page-links)
""
,@(ee-pdflike-page-links page bufname offset)
) rest)
))
;; (find-pdflike-page-links)
;; (find-angg ".emacs.papers" "kopkadaly")
;; (code-pdftotext "kopkadaly4" "~/books/__comp/kopka_daly__a_guide_to_latex_4th_ed.pdf" 12)
;; (find-code-pdftotext "kopkadaly4" "~/books/__comp/kopka_daly__a_guide_to_latex_4th_ed.pdf" 12)
;; (ee-page-parameters "kopkadaly4" 12)
;; (find-kopkadaly4page (+ 12 287) "13.1 The picture environment")
;; (find-kopkadaly4text "13.1 The picture environment")
;; (find-kopkadaly4text)
;;; _ _ _ _ __ _
;;; | |__ _ _ _ __ ___ _ __| (_)_ __ | | __ _ __ _ __ ___ / _(_)_ __
;;; | '_ \| | | | '_ \ / _ \ '__| | | '_ \| |/ /____| '_ \| '__/ _ \ |_| \ \/ /
;;; | | | | |_| | |_) | __/ | | | | | | | <_____| |_) | | | __/ _| |> <
;;; |_| |_|\__, | .__/ \___|_| |_|_|_| |_|_|\_\ | .__/|_| \___|_| |_/_/\_\
;;; |___/|_| |_|
;;
;; «ee-hyperlink-prefix» (to ".ee-hyperlink-prefix")
(defun ee-hyperlink-prefix ()
"A lispish interface for customizing the variable `ee-hyperlink-prefix'.
See the comments in the source code."
(interactive)
(find-elinks
`((ee-hyperlink-prefix)
;; Convention: the first sexp always regenerates the buffer.
(setq ee-hyperlink-prefix ,ee-hyperlink-prefix) ; current value
""
(setq ee-hyperlink-prefix "# ") ; other common values
(setq ee-hyperlink-prefix ";; ")
(setq ee-hyperlink-prefix "-- ")
(setq ee-hyperlink-prefix "// ")
(setq ee-hyperlink-prefix "% ")
)))
;;; __ _ _ __ _ _ _
;;; / _(_)_ __ __| | ___ / _| __ _ ___ ___ | (_)_ __ | | _____
;;; | |_| | '_ \ / _` |_____ / _ \ |_ / _` |/ __/ _ \_____| | | '_ \| |/ / __|
;;; | _| | | | | (_| |_____| __/ _| (_| | (_| __/_____| | | | | | <\__ \
;;; |_| |_|_| |_|\__,_| \___|_| \__,_|\___\___| |_|_|_| |_|_|\_\___/
;;;
;; See: (find-links-intro)
;; (find-templates-intro)
;; «find-eface-links» (to ".find-eface-links")
;; (find-find-links-links "\\M-s" "eface" "face-symbol")
;; A test: (find-eface-links 'bold)
(define-key eev-mode-map "\M-h\M-s" 'find-eface-links)
(defun find-eface-links (face-symbol &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks about FACE-SYMBOL."
(interactive (list (or (face-at-point) 'default)))
;; (setq face-symbol (or face-symbol "{face-symbol}"))
;; (setq face-symbol (or face-symbol (face-at-point)))
(apply 'find-elinks
`((find-eface-links ',face-symbol ,@pos-spec-list)
;; Convention: the first sexp always regenerates the buffer.
(find-efunction 'find-eface-links)
""
(find-efacedescr ',face-symbol)
(find-eface ',face-symbol)
(customize-face ',face-symbol)
(set-face-foreground ',face-symbol ,(face-foreground face-symbol))
(set-face-background ',face-symbol ,(face-background face-symbol))
(face-id ',face-symbol)
(find-epp (mapcar (lambda (face) (cons (face-id face) face)) (face-list)))
(find-ecolors)
(find-efaces)
(find-efaces ,(symbol-name face-symbol))
)
pos-spec-list))
;; Test: (find-eface-links 'eepitch-star-face)
;; (find-eevfile "eev.el" "\\M-h\\M-s")
;;; __ _ _ _ _ _ _
;;; / _(_)_ __ __| | ___ ___ ___ | | ___ _ __ | (_)_ __ | | _____
;;; | |_| | '_ \ / _` |____ / _ \/ __/ _ \| |/ _ \| '__|___| | | '_ \| |/ / __|
;;; | _| | | | | (_| |____| __/ (_| (_) | | (_) | | |____| | | | | | <\__ \
;;; |_| |_|_| |_|\__,_| \___|\___\___/|_|\___/|_| |_|_|_| |_|_|\_\___/
;;;
;; «find-color-links» (to ".find-color-links")
;; (find-find-links-links "c" "color" "initialcolor")
;; Tests:
;; (find-ecolor-links)
;; (find-ecolor-links "sienna")
;;
(define-key eev-mode-map "\M-hc" 'find-ecolor-links)
(defun find-ecolor-links (&optional initialcolor &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks for the color INITIALCOLOR."
(interactive)
(setq initialcolor (or initialcolor "#123456"))
(apply 'find-elinks
`((find-ecolor-links ,initialcolor ,@pos-spec-list)
""
(find-ecolor-links (ee-color-choose-tk ,(or initialcolor "gray")))
(find-ecolor-links ,(or initialcolor "gray"))
(find-ecolors)
(find-ecolors ,initialcolor)
,`(insert (propertize " Sample " 'face '(:background ,initialcolor)))
,`(ee-color-values ,initialcolor)
(kill-new ,initialcolor)
(kill-new ,(ee-color-values initialcolor))
(find-efunction 'find-ecolor-links)
)
pos-spec-list))
(defun ee-color-values (color)
"Return the #RRGGBB representation for COLOR."
(apply 'format "#%02x%02x%02x"
(mapcar (lambda (c) (lsh c -8)) (color-values color))))
(defun ee-color-choose-tk (&optional initialcolor)
"Call Tcl/Tk to choose a color similar to INITIALCOLOR.
This needs a temporary directory; see: (find-prepared-intro)"
(eetcl (format "puts [tk_chooseColor -initialcolor %s]; exit"
(or initialcolor "gray")))
(find-sh0 (format "wish %s" ee-file-tcl)))
;;; __ _ _ _ _ _ _
;;; / _(_)_ __ __| | | |__ ___ _ __ ___ | (_)_ __ | | _____
;;; | |_| | '_ \ / _` |_____| '_ \ / _ \ '__/ _ \_____| | | '_ \| |/ / __|
;;; | _| | | | | (_| |_____| | | | __/ | | __/_____| | | | | | <\__ \
;;; |_| |_|_| |_|\__,_| |_| |_|\___|_| \___| |_|_|_| |_|_|\_\___/
;;;
;; «find-here-links» (to ".find-here-links")
;; TO DO: DOCUMENT THIS!
;; (find-efunction 'find-grep-links)
;; (find-efunction 'find-einfo-links)
;; (find-efunction 'find-file-links)
;; (find-find-links-links "\\M-h" "here" "")
;; (find-efunction 'find-ecolors)
(define-key eev-mode-map "\M-h\M-h" 'find-here-links)
;; Tools
;; (defun ee-buffer-re (re) (string-match re (buffer-name)))
(defun ee-buffer-re (re)
(if (string-match re (buffer-name))
(match-string 1 (buffer-name))))
(defun ee-buffer-eq (str) (string= str (buffer-name)))
(defun ee-buffer-help0 () (ee-buffer-eq "*Help*"))
(defun ee-buffer-help-re0 (re n)
(if (ee-buffer-help0)
(save-excursion
(goto-char (point-min))
(if (looking-at re) (match-string n)))))
(defun ee-buffer-help (re n) (intern (or (ee-buffer-help-re0 re n) "nil")))
;; By major mode
(defun ee-grep-bufferp () (eq major-mode 'grep-mode))
(defun ee-man-bufferp () (eq major-mode 'Man-mode))
(defun ee-rcirc-bufferp () (eq major-mode 'rcirc-mode))
(defun ee-info-bufferp () (eq major-mode 'Info-mode))
(defun ee-dired-bufferp () (eq major-mode 'dired-mode))
(defun ee-wdired-bufferp () (eq major-mode 'wdired-mode))
(defun ee-w3m-bufferp () (eq major-mode 'w3m-mode))
(defun ee-custom-bufferp () (eq major-mode 'Custom-mode))
(defun ee-epackages-bufferp () (eq major-mode 'package-menu-mode))
;; By buffer name
(defun ee-intro-bufferp () (ee-buffer-re "^\\*(find-\\(.*\\)-intro)\\*$"))
(defun ee-freenode-bufferp () (ee-buffer-re "^\\(.*\\).freenode\\.net"))
(defun ee-ecolors-bufferp () (ee-buffer-eq "*Colors*"))
(defun ee-efaces-bufferp () (ee-buffer-eq "*Faces*"))
(defun ee-pdftext-bufferp () (ee-buffer-re "^pdftotext"))
;; By buffer name (when it is "*Help*")
(defvar ee-efunctiondescr-re "^\\([^ \t\n]+\\) is a[^\t\n]*function")
(defun ee-efunctiondescr-bufferp () (ee-buffer-help ee-efunctiondescr-re 1))
(defun ee-find-efunctiondescr-links ()
(let ((f (ee-efunctiondescr-bufferp)))
`((find-efunction-links ',f)
(find-efunctiondescr ',f))))
(defvar ee-evardescr-re "^\\([^ \t\n]+\\) is a variable")
(defun ee-evardescr-bufferp () (ee-buffer-help ee-evardescr-re 1))
(defun ee-find-evardescr-links ()
(let ((v (ee-evardescr-bufferp)))
`((find-evariable-links ',v)
(find-evardescr ',v))))
(defvar ee-efacedescr-re "^Face: \\([^ \t\n]+\\)")
(defun ee-efacedescr-bufferp () (ee-buffer-help ee-efacedescr-re 1))
(defun ee-find-efacedescr-links ()
(let ((f (ee-efacedescr-bufferp)))
`((find-eface-links ',f)
(find-efacedescr ',f))))
(defvar ee-epackage-re "^\\([^ \t\n]+\\) is a[ -~]+ package")
(defun ee-epackage-bufferp () (ee-buffer-help ee-epackage-re 1))
(defun ee-find-epackage-links ()
(let ((p (ee-epackage-bufferp)))
`((find-epackages ,(format "\n %s " p) t)
(find-epackage ',p))))
;; By buffer name (when the mode is man)
(defvar ee-man-re "^\\*Man \\(.*\\)\\*$")
(defun ee-find-man-links ()
(let ((mp (ee-buffer-re ee-man-re)))
`((find-man ,mp))))
(defvar ee-custom-re "^\\*Customize Group: \\(.*\\)\\*$")
(defun ee-find-custom-links ()
(let* ((name (ee-buffer-re ee-custom-re))
(symbol (intern (downcase (replace-regexp-in-string " " "-" name)))))
`((find-customizegroup ',symbol))))
;; Other cases
(defun ee-file-bufferp () buffer-file-name)
(defun ee-find-efaces-links () `((find-efaces)))
(defun ee-find-ecolors-links () `((find-ecolors)))
(defun ee-find-epackages-links () `((find-epackages)))
(defun ee-find-pdftext-links () (ee-pdflike-page-links))
;; to to:
;; ee-find-w3m-links
;; ee-find-ecolor-links
;;
(defun ee-find-here-links ()
(cond ;; by major mode
((ee-info-bufferp) (cons "" (ee-find-info-links))) ; M-h M-i
((ee-man-bufferp) (cons "" (ee-find-man-links))) ; ?
((ee-grep-bufferp) (cons "" (ee-find-grep-links))) ; M-h M-g
((ee-w3m-bufferp) (cons "" (ee-find-w3m-links))) ; M-h M-w
((ee-dired-bufferp) (cons "" (ee-find-file-links))) ; M-h f
((ee-wdired-bufferp) (cons "" (ee-find-file-links))) ; M-h f
((ee-custom-bufferp) (cons "" (ee-find-custom-links))) ; ?
((ee-epackages-bufferp) (cons "" (ee-find-epackages-links))) ; ?
;; by buffer name
((ee-intro-bufferp) (cons "" (ee-find-intro-links))) ; M-h M-i
((ee-freenode-bufferp) (cons "" (ee-find-freenode-links))) ; ?
((ee-ecolors-bufferp) (cons "" (ee-find-ecolors-links))) ; ?
((ee-efaces-bufferp) (cons "" (ee-find-efaces-links))) ; ?
((ee-pdftext-bufferp) (cons "" (ee-find-pdftext-links))) ; ?
;; by buffer name, when it is "*Help*"
((ee-efunctiondescr-bufferp) (cons "" (ee-find-efunctiondescr-links)))
((ee-efacedescr-bufferp) (cons "" (ee-find-efacedescr-links)))
((ee-evardescr-bufferp) (cons "" (ee-find-evardescr-links)))
((ee-epackage-bufferp) (cons "" (ee-find-epackage-links)))
;; other cases
((ee-file-bufferp) (cons "" (ee-find-file-links))) ; M-h f
(t (list "" "Not implemented!" "See:"
'(find-efunction 'ee-find-here-links)))
))
(defun find-here-links-test (sexp)
"See: (find-links-intro \"`find-here-links'\")"
(find-wset "13o_2o_o" sexp '(find-here-links)))
;; (find-man "1 cat")
;; (progn (find-man "1 cat") (buffer-name))
;; (find-eevfile "eev-rcirc.el")
(defun ee-find-here-links0 ()
`(,(ee-H "See: ")
(find-links-intro "`find-here-links'")
(find-efunctiondescr 'eev-mode "M-h M-h")
))
;; (find-find-links-links "\\M-h" "here" "")
;;
(defun find-here-links (&rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks pointing to here."
(interactive)
(apply 'find-elinks
`(;; The first line of a find-here-links buffer DOES NOT
;; regenerates the buffer - instead the first lines point to
;; help pages.
,@(ee-find-here-links0)
,@(ee-find-here-links)
)
pos-spec-list))
;; Test: (find-here-links)
;; (progn (find-enode "Screen") (find-here-links))
;; ------------------------------------------------------------
;; Old stuff:
;; The rest of this block of comments was cut & pasted straight from
;; eev-insert.el, but most of what they say still hold...
;;
;; This is the ugliest part of eev's code. It's being rewritten. Even
;; if work on it may seem stalled, it _is_ being rewritten. In some
;; sense.
;;
;; I got tired of writing all my hyperlinks by hand, so I created
;; these functions. The "new way of creating hyperlinks" (the first
;; block of this file) adds the following key bindings to
;; eev-mode-map:
;;
;; M-h M-k find-ekey-links
;; M-h M-f find-efunction-links
;; M-h M-v find-evariable-links
;; M-h M-i find-einfo-links
;; M-h M-d find-debpkg-links
;; M-h f find-file-links
;; M-h m find-last-manpage-links
;; M-h M-m find-manpage-links
;;
;; All of them work similarly. For example: type M-h M-k RET, and
;; `find-ekey-links' will create and display a buffer called "*Elisp
;; hyperlinks*", like this:
;;
;; _____________________________________________________________
;; |(find-ekey-links "\r") |
;; |(find-elongkey-links "RET") |
;; |(find-elongkey-links "RET ;; newline") |
;; |"RET ;; newline" |
;; | |
;; |(where-is 'newline) |
;; |(describe-function 'newline) |
;; |(find-efunctiondescr 'newline) |
;; |(find-efunction 'newline) |
;; |(find-efunctionpp 'newline) |
;; |(find-efunctiond 'newline) |
;; |(find-eCfunction 'newline) |
;; |(find-estring (documentation 'newline)) |
;; |(find-estring (documentation 'newline t)) |
;; | |
;; |(describe-key "\r") |
;; |(describe-key-briefly "\r") |
;; |(find-ekeydescr "\r") |
;; |(Info-goto-emacs-key-command-node "\r") |
;; |(Info-goto-emacs-command-node 'newline) |
;; |(find-enode "Command Index" "* newline:") |
;; |(find-elnode "Index" "* newline:") |
;; | |
;; |(key-description "\r") |
;; |(format-kbd-macro "\r") |
;; |(format-kbd-macro "\r" t) |
;; |(key-binding "\r") |
;; | |
;; | |
;; | |
;; |--:** *Elisp hyperlinks* All L28 (Fundamental)--------|
;; |_____________________________________________________________|
;;
;;
;; That is, a lot of hyperlinks pointing to interesting pieces of
;; information about the key RET and the command (`newline') that is
;; bound to it. Then you may follow these hyperlinks by evaluating the
;; sexps or you may copy them to other files by copying their text.
;;
;; [To do: explain M-h M-y. There's an example in `eesteps' format in
;; the NEWS file.]
;; See:
;; and:
;; The second part of this file contains some older functions that
;; insert Elisp hyperlinks at the current buffer -- like `inn', that
;; inserts a hyperlink to the info node currently being visited -- or
;; transform text -- for example, a series of lines, each one
;; containing the name of a Debian package -- into hyperliks.
'(
(defun ee-buffer-manpage-name (&optional bufname)
"Return the name of the manpage in the buffer BUFNAME, or nil if none.
The default for BUFNAME is the name of the current buffer.
This function does a simple string matching and converts \"*Man
foo*\" to \"foo\"."
(if (null bufname)
(setq bufname (buffer-name)))
(and bufname
(string-match "^\\*\\(Wo\\)?Man \\(.*\\)\\*$" bufname)
(match-string 2 bufname)))
(defun find-last-manpage-links (manpagename &rest rest)
"Visit a temporary buffer containing hyperlinks related to a manpage.
Use this when you are in a manpage buffer and you want links to it."
(interactive (list (ee-buffer-manpage-name)))
(apply 'find-elinks
(list (ee-pph `(find-man-links ,manpagename))
""
(ee-pph `(find-man ,manpagename)))
rest))
(defun find-manpage-links (manpagename &rest rest)
"Visit a temporary buffer containing hyperlinks related to a manpage.
Use this when point is over a manpage name and you want links to that page."
(interactive (list (ee-manpagename-ask)))
(apply 'find-elinks
(list (ee-pph `(find-man-links ,manpagename))
""
(ee-pph `(find-man ,manpagename)))
rest))
)
;; Creating temporary buffers with lots of elisp hyperlinks is an idea
;; that I only had relatively recently - in 2004, I think... before
;; that I used some functions that either inserted hyperlinks into the
;; current buffer or modified the text in the current buffer to
;; produce hyperlinks. For example, `M-x inn' inserted a link to an
;; info node, and `M-x dff' converted a line with the name of a debian
;; package into three lines, each one with a hyperlink to something
;; related to that debian package...
;; TODO: move these functions to another file (eev-video.el?)
;; (find-angg ".emacs" "mm:ss")
;; (find-angg ".emacs" "find-mplayer")
;; (find-angg ".emacs" "code-mplayer")
;; (find-man "1 mplayer" " -ss ")
;; (find-man "1 mplayer" " -fs ")
;; (find-man "1 mplayer" " -osdlevel ")
;; Tests:
;; (find-upload-links "eev-current/eev-template.el")
;; (find-download-links "" "" "eev-current/eev-template.el")
;; (eevt-down "eev-current/" "emacs/eev/" "eev-template.el")
;
(provide 'eev-elinks)
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "«%s»"
;; no-byte-compile: t
;; End:
eev-20141011/eev-env.el 0000644 0001750 0001750 00000005450 12066616075 013116 0 ustar edrx edrx ;;; eev-env.el -- set some environment variables.
;; Copyright (C) 2012 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2012nov02
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;;
;;
;; (find-eev-intro)
;; (find-psne-intro)
;; (find-prepared-intro)
;;; Commentary:
;; Used by: (find-eev "eev-prepared.el")
;;
;; Related but obsolete files:
;;
;;
;;
;;; ___ _ ____ __ __ ____ _ _ __ ___
;;; / _ \ '_ \ \ / / \ \ / / _` | '__/ __|
;;; | __/ | | \ V / \ V / (_| | | \__ \
;;; \___|_| |_|\_/ \_/ \__,_|_| |___/
;;;
;;; Set some environment variables (for ee-expand, getenv,
;;; shell buffers, xterms started from Emacs, etc).
;; (find-eevrcfile ".bashrc")
;; (find-eevrcfile ".zshrc")
(defun ee-setenv (envvar value)
"In case the environment variable ENVVAR was not set set it to VALUE."
(if (null (getenv envvar))
(setenv envvar (ee-expand value))))
(ee-setenv "S" "~/snarf") ; for `find-psne-links'
;; Obsolete? See:
;; (find-eev "eev-bounded.el")
;; (find-eev "eev.el" "ee-setenv")
(ee-setenv "EEVDIR"
(let ((fname (locate-library "eev")))
(if fname (directory-file-name (file-name-directory fname))
"~/eev-current"))) ; eev.el, etc
(provide 'eev-env)
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "«%s»"
;; ee-anchor-format: "defun %s "
;; no-byte-compile: t
;; End:
eev-20141011/eev-eval.el 0000644 0001750 0001750 00000012741 12067453044 013252 0 ustar edrx edrx ;;; eev.el -- variants of eval-last-sexp.
;; Copyright (C) 2012 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2012dec29
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;;
;; (find-eev-intro)
;; (find-eval-intro)
;;; Commentary:
(require 'eev-flash) ; (find-eev "eev-flash.el")
;;; _ _
;;; _____ ____ _| | ___ _____ ___ __ ___ ___ | |
;;; / _ \ \ / / _` | |_____/ __|/ _ \ \/ / '_ \ _____ / _ \/ _ \| |
;;; | __/\ V / (_| | |_____\__ \ __/> <| |_) |_____| __/ (_) | |
;;; \___| \_/ \__,_|_| |___/\___/_/\_\ .__/ \___|\___/|_|
;;; |_|
;;;
;;; evaluating sexps (alternatives to eval-last-sexp)
;;;
;; ee-eval-sexp-eol may be obsolete
;; ee-arg is still used in eev-insert.el (ack!)
;; See (find-efunction 'eval-last-sexp-1)
(defun ee-backward-sexp ()
"An internal function used by `ee-eval-last-sexp'."
(interactive)
(with-syntax-table emacs-lisp-mode-syntax-table
(forward-sexp -1)
(when (eq (preceding-char) ?\\)
(forward-char -1)
(when (eq (preceding-char) ??)
(forward-char -1))))
(point))
(defun ee-forward-sexp ()
"An internal function used by `ee-eval-last-sexp'."
(interactive)
(with-syntax-table emacs-lisp-mode-syntax-table
(forward-sexp 1))
(point))
(defun ee-last-sexp ()
"An internal function used by `ee-eval-last-sexp'."
(save-excursion
(buffer-substring-no-properties
(ee-backward-sexp) (ee-forward-sexp))))
(defmacro ee-no-debug (&rest body)
`(let ((debug-on-error nil)) ,@body))
;; (defun ee-eval (sexp) (ee-no-debug (eval sexp)))
(defun ee-eval-last-sexp-0 ()
"Highlight the sexp before point."
(save-excursion
(eeflash+ (ee-backward-sexp) (ee-forward-sexp)
ee-highlight-spec)))
(defun ee-eval-last-sexp-2 ()
"Show the target of the sexp before point in another window."
(find-wset "1so_o" '(ee-eval-last-sexp)))
(defun ee-eval-last-sexp-3 ()
"Show the target of the sexp before point in another window, and switch to it."
(find-wset "1so_" '(ee-eval-last-sexp)))
(defun ee-eval-last-sexp-4 ()
"Evaluate the sexp before point in debug mode."
(let ((sexp (read (ee-last-sexp))))
(debug)
(eval sexp)))
(defun ee-eval-last-sexp-5 ()
"Evaluate the sexp before point with `debug-on-error' turned on."
(let ((sexp (read (ee-last-sexp)))
(debug-on-error t))
(eval sexp)))
(defun ee-eval-last-sexp (&optional arg)
"By default, evaluate sexp before point, and print value in minibuffer.
This is eev's variant of `eval-last-sexp', and it can behave in
several different ways depending on the prefix argument ARG.
If ARG is:
nil: evaluate the sexp with `debug-on-error' turned off
0: highlight the sexp temporarily
1: show the sexp as a string
2: show the target of the sexp in another window
3: same, but also switch to the new window
4: evaluate the sexp in debug mode
5: run the sexp with `debug-on-error' turned on
8: eval then pretty-print the result in another buffer
9: a hack for testing `call-interactively'"
(interactive "P")
(cond ((eq arg 0)
(save-excursion
(eeflash+ (ee-backward-sexp) (ee-forward-sexp)
ee-highlight-spec)))
((eq arg 1) (prin1 (ee-last-sexp)))
;; ((eq arg 2) (prin1 (read (ee-last-sexp))))
;; ((eq arg 3) (ee-eval (read (ee-last-sexp))))
((eq arg 2) (find-wset "1so_o" ' (ee-eval-last-sexp)))
((eq arg 3) (find-wset "1so_" ' (ee-eval-last-sexp)))
((eq arg 4) (let ((sexp (read (ee-last-sexp)))) (debug) (eval sexp)))
((eq arg 5) (let ((sexp (read (ee-last-sexp)))
(debug-on-error t))
(eval sexp)))
((eq arg 8) (find-epp (ee-eval (read (ee-last-sexp)))))
((eq arg 9) (let ((interactive-clause (read (ee-last-sexp))))
(let ((debug-on-error nil))
(call-interactively
`(lambda (&rest args) ,interactive-clause
(message "%S" args))))))
(t (prin1 (let ((ee-arg arg))
(ee-eval (read (ee-last-sexp))))))))
(defun ee-eval-sexp-eol (&optional arg)
"Go to the end of line, then run `ee-eval-last-sexp'.
See: (find-eval-intro)"
(interactive "P")
(end-of-line)
(ee-eval-last-sexp arg))
(provide 'eev-eval)
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "«%s»"
;; ee-anchor-format: "defun %s "
;; no-byte-compile: t
;; End:
eev-20141011/eev-flash.el 0000644 0001750 0001750 00000007127 12066601440 013414 0 ustar edrx edrx ;;; eev-flash.el -- functions to highlight a range of text temporarily.
;; Copyright (C) 2012 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2012dec26
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;;
;; (find-eev-intro)
;; (find-eval-intro "M-0 M-e")
;; These functions are used by some variants of `ee-eval-last-sexp'
;; (especially `M-0 M-e') and by `eev-bounded' and friends.
;; (find-eev "eev-eval.el")
;; (find-eev "eev-bounded.el")
;; New version - with a `-' because it is non-interactive, and
;; consequently an internal function.
(defun ee-flash (start end &optional face duration)
"Highlight the region between START and END using FACE, for time DURATION."
(let ((ovl (make-overlay start end)))
(overlay-put ovl 'face (or face 'region))
(run-at-time (or duration 1) nil 'delete-overlay ovl)))
;; The old code follows.
;; To do: delete most of this, use just `ee-flash' instead.
;; Drop the idea of flash-specs as lists.
;; (setq eeb-highlight-spec '(highlight 0.2))
(defvar ee-highlight-spec '(highlight 0.75)) ; to do: rename highlight->flash
(defvar eeb-highlight-spec '(highlight 0.5))
(defvar eek-highlight-spec '(region 0.75))
(defvar eeflash-default '(highlight 0.5))
;;; __ _ _
;;; ___ ___ / _| | __ _ ___| |__
;;; / _ \/ _ \ |_| |/ _` / __| '_ \
;;; | __/ __/ _| | (_| \__ \ | | |
;;; \___|\___|_| |_|\__,_|___/_| |_|
;;;
;;; temporary highlighting (flashing)
;;;
(defun eeflash (start end &optional face duration)
"Highlight the region between START and END using FACE, for time DURATION."
(let ((ovl (make-overlay start end)))
(overlay-put ovl 'face (or face 'region))
(run-at-time (or duration 1) nil 'delete-overlay ovl)))
(defun eeflash+ (s &optional e spec add-to-e)
"Highlight the region between S and E; face and duration are taken from SPEC.
This function only tries to do any work when S is a number and SPEC is non-nil.
When SPEC is non-nil it should be a pair of the form (FACE DURATION).
The argument ADD-TO-E is a hack for when we know that the region between S and
E+1 ends with a newline and it looks nicer to highlight the newline too; then
we set ADD-TO-E to 1."
(if (and (numberp s) spec)
(eeflash s (+ e (or add-to-e 0))
(car spec) (cadr spec)))
(list s e spec add-to-e))
(provide 'eev-flash)
;; Local Variables:
;; coding: raw-text-unix
;; no-byte-compile: t
;; End:
eev-20141011/eev-intro.el 0000644 0001750 0001750 00000550071 12413600605 013451 0 ustar edrx edrx ;;; eev-intro.el --- intro scripts for eev
;; Copyright (C) 2013,2014 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2014aug23
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;; (find-eev-intro)
;;; Commentary:
;;
;; To use this, simply execute any of the sexps below:
;; (find-eev-intro)
;; (find-eval-intro)
;; (find-eepitch-intro)
;; (find-wrap-intro)
;; (find-code-c-d-intro)
;;
;; Note (2013nov12):
;; I am using the code below to edit these intros...
;; Note that it is commented out - and HOW it is commented out!
'
(progn
(defun ee-sexp-at (re) (save-excursion (re-search-forward re) (ee-last-sexp)))
(setq ee-intro-end-re "\\(rest\\|pos-spec-list\\))))")
(defun ee-intro-here () (eval (read (ee-sexp-at ee-intro-end-re))))
(defun d0 () (funcall (ee-intro-here) (ee-last-kill)))
(defun d () (interactive) (find-2b nil '(d0)))
)
;; Quick index:
;; «.find-eev-intro» (to "find-eev-intro")
;; «.find-eval-intro» (to "find-eval-intro")
;; «.find-eepitch-intro» (to "find-eepitch-intro")
;; «.find-wrap-intro» (to "find-wrap-intro")
;; «.find-links-intro» (to "find-links-intro")
;; «.find-code-c-d-intro» (to "find-code-c-d-intro")
;; «.find-psne-intro» (to "find-psne-intro")
;; «.find-brxxx-intro» (to "find-brxxx-intro")
;; «.find-eejump-intro» (to "find-eejump-intro")
;; «.find-pdf-like-intro» (to "find-pdf-like-intro")
;; «.find-audiovideo-intro» (to "find-audiovideo-intro")
;; «.find-multiwindow-intro» (to "find-multiwindow-intro")
;; «.find-rcirc-intro» (to "find-rcirc-intro")
;; «.find-templates-intro» (to "find-templates-intro")
;; «.find-anchors-intro» (to "find-anchors-intro")
;; «.find-prepared-intro» (to "find-prepared-intro")
;; «.find-bounded-intro» (to "find-bounded-intro")
;; «.find-channels-intro» (to "find-channels-intro")
;; «.find-videos-intro» (to "find-videos-intro")
;; «.find-defun-intro» (to "find-defun-intro")
;; «.find-emacs-intro» (to "find-emacs-intro")
;; «.find-org-intro» (to "find-org-intro")
;; See: (find-anchors-intro)
;; Ignore this - this is a temporary hack to make the htmlization in
;; work better...
;; (find-angg "eev-intros/")
;; (find-angg "eev-intros/README")
' (fooi-re "Source code: (find-efunction '\\([!-~]*\\))"
"Source code: (find-eev \\\\\"eev-intro.el\\\\\" \\\\\"\\1\\\\\")")
;;; _ _
;;; ___ _____ __ (_)_ __ | |_ _ __ ___
;;; / _ \/ _ \ \ / /____| | '_ \| __| '__/ _ \
;;; | __/ __/\ V /_____| | | | | |_| | | (_) |
;;; \___|\___| \_/ |_|_| |_|\__|_| \___/
;;;
;; This works as an index.
;; (find-intro-links "eev")
;; «find-eev-intro» (to ".find-eev-intro")
(defun find-eev-intro (&rest rest) (interactive)
(let ((ee-buffer-name "*(find-eev-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-eev-intro)
Source code: (find-eev \"eev-intro.el\" \"find-eev-intro\")
Main intros: (find-eval-intro)
(find-eepitch-intro)
(find-wrap-intro)
Index to the source files: (find-eev \"eev2-all.el\")
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
The quickest way to reach this index is with `M-5 M-j'.
Here is a list of all the available sandbox-y tutorials that
explain parts and concepts of eev, listed in (a kind of)
recommended reading order:
0. (find-eev-intro)
1. (find-eval-intro)
2. (find-eepitch-intro)
3. (find-wrap-intro)
4. (find-links-intro)
5. (find-eejump-intro)
6. (find-code-c-d-intro)
7. (find-psne-intro)
9. (find-brxxx-intro)
10. (find-pdf-like-intro)
11. (find-audiovideo-intro)
12. (find-anchors-intro)
13. (find-multiwindow-intro)
14. (find-rcirc-intro)
15. (find-templates-intro)
16. (find-prepared-intro)
17. (find-bounded-intro)
18. (find-channels-intro)
19. (find-videos-intro)
Items 1 and 2 should give you a good grasp of the main ideas -
namely, that _elisp hyperlinks and interactive scripts can be
embedded anywhere_. The other tutorials mainly show how to make
these ideas pervasive.
The last item above is an index of the video tutorials, with
scripts for downloading local copies of them and links to
important positions in the videos.
There are also these two, ahem, \"things\", that I use in
workshops, but that are not very eev-specific:
A. (find-emacs-intro)
B. (find-defun-intro)
Installation: way 1
===================
If you're a real beginner and you are reading this in a web browser
then this is the easiest way to install eev and start playing with it.
Mark the multi-line \"{ ... }\" block below, copy it to the clipboard
with ctrl-C, and paste it to a shell running in a terminal to execute
its commands. It will download the current version of eev and unpack
it into ~/eev/.
{
rm -Rv ~/eev/
mkdir ~/eev/
cd ~/eev/
rm -v eev2.tgz
wget http://angg.twu.net/eev-current/eev2.tgz
tar -xvzf eev2.tgz
}
Now do the same with this block:
{
{
echo '#!/bin/sh'
echo 'cd ~/eev/ && emacs -l ./eev-readme.el --eval=\"(find-eval-intro)\"'
} > ~/e
chmod 755 ~/e
}
You now have a shell script that you can invoke with
~/e
that starts Emacs, loads eev, and opens this tutorial:
(find-eval-intro)
Once you learn how to navigate the help system by following elisp
hyperlinks and going back, the rest is easy.
The README
==========
The README for eev2 is an elisp file,
(find-eev \"eev-readme.el\")
that contains an easy way of installing eev - in either a
temporary directory or in a permanent one - and initial
instructions for trying the main keys. HIGHLY RECOMMENDED!
Installing eev
==============
The instructions below are adapted from:
(find-eev-update-links \"/tmp/eev/\")
and: (find-eev \"eev-readme.el\")
You should download the tarball with all the elisp files, unpack
it somewhere - doing something like this (here you can use F8 if
you already have eev installed),
(eepitch-shell)
(eepitch-kill)
(eepitch-shell)
rm -Rv /tmp/eev/
mkdir /tmp/eev/
cd /tmp/eev/
wget http://angg.twu.net/eev-current/eev2.tgz
tar -xvzf eev2.tgz
and then evaluate these sexps (type C-x C-e at the end of each
line):
(add-to-list 'load-path \"/tmp/eev/\")
(require 'eev2-all)
(eev-mode 1)
This will turn on eev-mode - which just activates a few
keybindings. To understand the main ideas, please follow these
two tutorials:
(find-eval-intro)
(find-eepitch-intro)
To toggle eev-mode on and off, use `M-x eev-mode'.
The keybindings
===============
`eev-mode' defines its own meanings for lots of meta-shift-letter
key combinations - which are not normally used by Emacs - and,
besides that, only for:
`M-e' (find-eval-intro \"`M-e'\")
`M-k' (find-eval-intro \"`M-k'\")
`M-j' (find-eejump-intro \"\\neejump\\n\")
`M-h' (find-links-intro \"Elisp hyperlinks buffers\")
`' (find-eepitch-intro \"The main key: \")
For the full lists of keybindings, see:
(find-efunctiondescr 'eev-mode)
(find-eminormodekeymapdescr 'eev-mode)
(find-efunctiondescr 'eev-avadj-mode)
(find-eminormodekeymapdescr 'eev-avadj-mode)
" rest)))
;; (find-eev-intro)
;;; _
;;; _____ ____ _| |
;;; / _ \ \ / / _` | |
;;; | __/\ V / (_| | |
;;; \___| \_/ \__,_|_|
;;;
;; «find-eval-intro» (to ".find-eval-intro")
;; (find-intro-links "eval")
;; (find-TH "eev-article" "hyperlinks")
;; http://angg.twu.net/eev-article.html#hyperlinks
;; file:///home/edrx/TH/L/eev-article.html#hyperlinks
;; (find-TH "eev-article" "forward-and-back")
;; (find-efunction 'eek-eval-last-sexp)
(defun find-eval-intro (&rest rest) (interactive)
(let ((ee-buffer-name "*(find-eval-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-eval-intro)
Source code: (find-eev \"eev-intro.el\" \"find-eval-intro\")
More intros: (find-eev-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
It is meant as both a tutorial and a sandbox.
The standard way to evaluate Lisp: `C-x C-e'
============================================
The most important idea in Emacs is that Lisp code can appear
anywhere, and you can evaluate a Lisp expression (a \"sexp\") by
placing the cursor (the \"point\") just after it and typing `C-x
C-e'; the result is then displayed in the echo area. Try it in
the line below, with the point in the three different indicated
positions - you should get different results.
(+ (* 2 3) (* 4 5))
^ ^^
| | \\
6 20 26
The end of line and `M-e'
=========================
A common operation is to move the point to the end of the current
line, then run `C-x C-e'. That can be done with `C-e C-x C-e',
but eev-mode implements a shorthand for it: `M-e'. Try it here:
(+ (* 2 3)
(* 4 5)
)
`M-e' accepts several different numeric prefixes that alter its
behavior. We are only interested in one of them now - `M-0 M-e'
highlights the sexp for a fraction of a second insted of
executing it. Try it above.
In some rare occasions we might want to run something like `M-e'
but without moving to the end of the line first. Eev-mode
implements a key binding for that: `M-E' (meta-shift-e). As an
exercise, try to use `M-0 M-E' at several positions below, to
hightlight the subsexps `(* 2 3)', `(* 4 5)', and `4'.
(+ (* 2 3) (* 4 5))
What to execute, and in what order
==================================
Note that the order of evaluation may be important:
(setq a 5)
(setq a 6)
(* a a)
By executing `(setq a 5)' and then `(* a a)' above we get 25,
by executing `(setq a 6)' and then `(* a a)' we get 36 - the
current value of `a' is the one of the last `setq' executed.
An exercise: edit the three sexps above to introduce a
`(setq a 22)', then use that sexp and the `(* a a)' to calculate
the square of 22.
MORAL: Elisp code can appear anywhere in any Emacs buffer, but it
is _passive by default_. It only gets executed if we move the
point to the right positions and type `C-x C-e', `M-e', or
similar keys. Sexps can be executed any number of times, in any
order, and can be edited and modified.
Elisp hyperlinks
================
Some Emacs functions can be used as hyperlinks. When sexps like
(find-file \"/tmp/\")
(info \"(emacs)Lisp Eval\")
(describe-function 'find-file)
(find-function 'find-file)
(man \"cat\")
are executed they \"open a new page\" - actually, they create a
new buffer, or reuse it if it already exists - and it is usually
possible to \"go back\" by killing the new buffer. However for
some functions, like `man', which by default open a manpage in
another window, \"going back\" would mean something different.
Eev defines several functions to let us use sexps as hyperlinks.
The main conventions on these functions are:
1) their names start with \"find-\",
2) calls to them can be \"refined\" with a pos-spec (this will
be discussed below),
3) they open the new buffer in the current window (to make it
easier to \"go back\" after following them - see the next
section),
4) they don't display much output in the echo area,
5) when they create temporary buffers with lots of sexps then:
a) the first sexp in that buffer is one that can regenerate
that buffer when executed,
b) all the sexps are prefixed with the string stored in the
variable `ee-hyperlink-prefix', to let these sexps be
pasted into scripts as comments (see below).
Note that sometimes the most obvious name for a hyperlink
function starting with `find-' is already taken by Emacs - for
example, `find-file' and `find-function'. In those cases eev use
other names: `find-fline', `find-efunction', etc. Here are the
eev versions of the links above:
(find-fline \"/tmp/\")
(find-node \"(emacs)Lisp Eval\")
(find-efunctiondescr 'find-file)
(find-efunction 'find-file)
(find-man \"cat\")
Going back
==========
Web browsers let you follow a hyperlink and then \"go back\".
There are different ways of going back - if you opened the new
page on a new window or tab, then going back means deleting the
new window or tab (or just switching to the old window/tab); if
you opened the new page on the same window/tab, then you need to
use the \"back\" button.
Eev-mode defines two keys for \"going back\": `M-k', that kills
the current buffer, and `M-K', that just hides it (\"buries\" it
in the bottom of the list of all buffers). Try following the link
below by , then deleting its buffer with `M-k' to go back:
(find-node \"(emacs)Shell\")
In some cases we know that we may want to go \"forward\" again
after going back, and we may not want to delete the target buffer
- for example, because it would take a while to rebuild it again,
or because we would lose the position of the point there. Most
hyperlink functions in eev are able to reuse a buffer that
\"looks like\" the desired target buffer; the test for
lookalikeness is based on the name of the buffer only. Try to
follow the links below with `M-e', then come back to this buffer
with `M-k', then follow them again. Then try the same thing with
`M-K' instead of `M-k', to see the difference - in the `find-sh'
example below the \"sleep\" takes one second to run, so
revisiting the existing output buffer after a `M-K' is much
quicker than recreating it anew.
(find-man \"1 bash\")
(find-sh \"sleep 1; echo 'This was run at:'; date\")
Refining hyperlinks
===================
Most hyperlinks functions defined by eev can be \"refined\" by
the addition of extra arguments. These extra arguments are called
a \"pos-spec\" (or a \"pos-spec-list\") and they specify a
position in the target buffer. The first argument means a certain
line number, when it is a number, or the first occurrence of a
certain string, when it is a string. Try:
(find-node \"(emacs)Command Index\")
(find-node \"(emacs)Command Index\" \"eval-last-sexp\")
Further arguments mean either \"move down n lines\" or \"search
for the next occurrence of a string\", depending on whether they
are numbers or strings. Try:
(find-sh \"seq 2095 2115\")
(find-sh \"seq 2095 2115\" \"2100\")
(find-sh \"seq 2095 2115\" \"2100\" \"9\")
(find-sh \"seq 2095 2115\" \"2100\" 2)
Pos-spec-lists
==============
The optional arguments that refine a hyperlink form what we call
a \"pos-spec-list\". For example, the pos-spec-list here has two
elements,
(find-sh \"seq 2095 2115\" \"2100\" \"9\")
and in most cases an empty pos-spec-list, like this,
(find-sh \"seq 2095 2115\")
means: \"if the target buffer already exists then just open it\"
- so that following that hyperlink would jump to the current
position of the point in that buffer.
Pos-spec-lists are usually interpreted by the function
`ee-goto-position'. The first argument is interpreted in a
special way, according to its type:
string -> jump to the first occurrence of
that string in the buffer
number -> jump to the n-th line
and the other arguments are interpreted (recursively) by
`ee-goto-rest':
string -> jump to the next occurence of that string
number -> move down n lines
list -> evaluate the list
If you want to add support for more complex pos-spec-lists, just
replace `ee-goto-rest' with your own extended version.
Anchors and pages
=================
\[See:\] (find-anchors-intro)
Some hyperlink functions, like `find-efunction' and
`find-evariable', jump to specific positions in buffers - the
beginning of the definition of a function or a variable in the
source code - even when their pos-spec-lists are empty, so they
process all their extra arguments with just `ee-goto-rest'.
Other hyperlink functions transform the first argument of a
pos-spec-list in a special way it if is a string - for example,
in `find-available', which is based on `find-Package',
(find-available \"bash\")
(find-available \"bash\" \"bash-doc\")
the argument \"bash\" is converted to \"\\nPackage: bash\\n\",
and the two hyperlinks above jump to the description of the
package \"bash\" in the list of the available packages in a
Debian system.
The functions based on `find-anchor' transform an initial string
argument in the pos-spec-list by running `ee-format-as-anchor' on
it [TODO: document this], and the ones based on
`ee-goto-position-page' jump to the n-th \"page\" of a buffer if
the first argument of the pos-spec-list is a number, n; for
exemple, if n is 234 that will jump to the 233-th formfeed (233
and not 234 because the page 1 is before the first formfeed). For
more on \"pages\", see:
(find-pdf-like-intro \"PDF-like documents as text\")
Producing and refining hyperlinks
=================================
If you are on an Info page, typing `M-h M-i' will create a
temporary buffer containing a header - which we will discuss
later - and several (possibly equivalent) links to that info
page. Something like this:
________________________________________________________
|;; (find-einfo-links) |
| |
|;; (info \"(emacs)Misc Buffer\") |
|;; (find-node \"(emacs)Misc Buffer\") |
|;; (find-enode \"Misc Buffer\") |
| |
| |
|--:**- *Elisp hyperlinks* All L1 (Fundamental)---|
|________________________________________________________|
These links are meant to be cut & pasted - possibly after
refining them to make them more precise. Let's look first at the
two key sequences that make refining much easier. Remember that
`M-w' (`kill-ring-save') is roughly correspondent to what is
called \"copy\" is most modern interfaces, and `C-y' (`yank') is
roughly correspondent to \"paste\". Both `M-w' and `C-y' operate
on Emacs's \"kill ring\", and to make our examples trivial to
follow we will first put a string on the kill ring:
(kill-new \"C-y\")
(car kill-ring)
Now let's see how refine hyperlinks quickly. `M-h M-2' duplicates
the current line; we will use that to refine a copy of a working
hyperlink, instead of working directly on the original, and
risking breaking it. And `M-h M-y' refines the hyperlink on the
current line by adding a string - the top element in the kill
ring - to its sexp. Try this below; you should be able to convert
(find-enode \"Kill Ring\")
(find-enode \"Yanking\")
into
(find-enode \"Kill Ring\")
(find-enode \"Kill Ring\" \"C-y\")
(find-enode \"Yanking\")
(find-enode \"Yanking\" \"C-y\")
with few keystrokes, as you can leave the Meta key pressed. The
full key sequence for duplicating and refining is `M-h M-2 M-h
M-y', but we can think of it as `M-h2hy'.
Now try a more serious exercise: follow the `(find-enode ...)'
hyperlink below, copy a word or two from its contents to the kill
ring with `M-w', then generate the temporary buffer with
hyperlinks to that Info page with `M-h M-i', then duplicate one
of its hyperlinks with `M-h M-2', refine it with `M-h M-y', and
copy the result to this sandbox with `M-w' (or `C-w') and `C-y'.
As this is a long sequence of instructions, it is better to run
`C-x 1 C-x 2' or `C-x 1 C-x 3' before following the hyperlink, to
keep the instructions visible.
(find-enode \"Command Index\")
What else?
==========
Eev-mode defines several other key sequences similar to `M-h
M-i'. You can get the full list here:
(find-efunctiondescr 'eev-mode)
(find-efunctiondescr 'eev-mode \"M-h f\")
Try also this:
(find-efunction-links 'eev-mode)
and for other tutorials like this one, try:
(find-wrap-intro)
(find-eepitch-intro)
\[To do: explain M-x ee-hyperlink prefix and how to embed
hyperlinks in scripts]
" rest)))
;; (find-eval-intro)
;;; _ _ _ _ _
;;; ___ ___ _ __ (_) |_ ___| |__ (_)_ __ | |_ _ __ ___
;;; / _ \/ _ \ '_ \| | __/ __| '_ \ _____| | '_ \| __| '__/ _ \
;;; | __/ __/ |_) | | || (__| | | |_____| | | | | |_| | | (_) |
;;; \___|\___| .__/|_|\__\___|_| |_| |_|_| |_|\__|_| \___/
;;; |_|
;;
;; «find-eepitch-intro» (to ".find-eepitch-intro")
;; (find-intro-links "eepitch")
;; (find-eev "eepitch.readme")
(defun find-eepitch-intro (&rest rest) (interactive)
(let ((ee-buffer-name "*(find-eepitch-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-eepitch-intro)
Source code: (find-eev \"eev-intro.el\" \"find-eepitch-intro\")
More intros: (find-eval-intro)
(find-wrap-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial (for eepitch) and a sandbox.
The motivation for eepitch: taking notes and redoing
====================================================
Suppose that we have to do some reasonably complex task using a
shell, and that we want to take notes of what we do because we
might have to do something similar later.
The two usual ways to interact with a shell are:
1) through a _script_, that is, by preparing in advance all
commands to be executed, putting them in a script file, and
then running that file,
2) _interactively_, by typing the commands one by one on a
shell prompt.
Suppose that we have to discover which commands to run as we go;
that rules out preparing a script beforehand, so we need to use
the shell interactively. After issuing the right commands, the
two usual ways to retrieve what we did are:
a) through the _shell history_, which records the last commands
that the shell received,
b) by looking at the full _transcript_ of our interaction with
the shell.
The way (a) gets a list of commands, without comments, that can
be then saved into a text editor; the way (b) may require some
tricky editing to isolate the commands from their outputs.
Eepitch.el implements a simple alternative way of interacting
with shells (and other shell-like programs) while keeping notes.
It has only one essential key binding, , which is better
explained through the executable example in the next section, and
two unessential features, `M-T' and \"\", which will be
explained later.
The main key:
==================
Emacs can run a shell in a buffer, and it can split its frame
into windows, like this:
___________________
| | |
| our | a |
| notes | shell |
| | buffer |
|_________|_________|
The usual way to use a shell buffer is to move the cursor there
and type commands into its prompt; the eepitch-y way is to leave
the cursor at the \"notes\" buffer, write the commands for the
shell there, and send these commands to the shell with .
Here's what does:
When we type on a line that starts with a red
star (\"\"), it executes the rest of the line as Lisp, and
moves down; when we type on a line that does not start
with a \"\", it makes sure that the \"target buffer\" is being
displayed (the \"target\" is usually the buffer called
\"*shell*\"), it \"send\"s the current line to the target
buffer, and moves down.
\"Sending the current line to the target buffer\" means copying
the contents of the current line to the target - as if the user
had typed that line there by hand -, then \"typing\" a at
the target buffet.
Please try that in the example after this paragraph, by typing
six times starting at the first line that says
\" (eepitch-shell)\". The three red star lines at the top will
create a target buffer, destroy it, and create it again; the
other three lines will send commands to the target shell.
(eepitch-shell)
(eepitch-kill)
(eepitch-shell)
echo \"We are at: $PWD\"
cd /tmp/
echo \"We changed to: $(pwd)\"
Other targets
=============
Just like `(eepitch-shell)' creates a shell buffer and sets the
eepitch target to it, `(eepitch-python)' creates a buffer with a
Python interpreter and uses it as the eepitch target. Try:
(eepitch-python)
(eepitch-kill)
(eepitch-python)
def square (x):
return x*x
print(square(5))
We can use several targets at the time, alternating between them.
For example:
(eepitch-shell)
(eepitch-kill)
(eepitch-shell)
echo Hello... > /tmp/o
(eepitch-python)
(eepitch-kill)
(eepitch-python)
print(open(\"/tmp/o\").read())
(eepitch-shell)
echo ...and bye >> /tmp/o
(eepitch-python)
print(open(\"/tmp/o\").read())
There is a (much) more advanced example of working with several
targets here:
(find-prepared-intro \"An `ee' for Python\")
More on eepitch-kill
====================
Note that `(eepitch-kill)' kills the _current_ target, that may
or may not be a shell buffer, a Python interaction buffer, etc...
That explains the first line in blocks like:
(eepitch-python)
(eepitch-kill)
(eepitch-python)
and:
(eepitch-shell)
(eepitch-kill)
(eepitch-shell)
by running the first `(eepitch-python)' we can be sure that the
following `(eepitch-kill)' will kill the Python buffer, not the
shell buffer! And the last `(eepitch-python)' in the block of
three lines will then create a new Python interaction buffer,
erasing all definitions done in previous sessions.
Creating eepitch blocks: `M-T'
==============================
Write just \"shell\" or \"python\" in a line, then type
`M-T' (i.e., meta-shift-t) there. The line will be turned into
three - an \" (eepitch-xxx)\", an \" (eepitch-kill)\", and an
\" (eepitch-xxx)\". We call these blocks of three lines
\"eepitch blocks\". Try this below, converting the \"shell\" into
an eepitch block for starting a shell.
shell
pwd
cd /tmp/
pwd
Red stars
=========
Eepitch.el sets the glyph for the char 15 to a red star in the
standard display table. In layman's terms: eepitch.el tells Emacs
that the character 15 should be displayed as a red star. The
character 15 corresponds to control-O, whose default
representation on screen would be \"^O\". You can enter a
literal ^O in a buffer by typing `C-q C-o'.
For more information
====================
On hyperlinks: (find-eval-intro)
On keys similar to `M-T': (find-wrap-intro)
An older text about eepitch:
(find-eev \"eepitch.readme\")
(find-eev \"eepitch.readme\" \"the-trivial-case\")
(find-eev \"eepitch.readme\" \"red-stars\")
(find-eev \"eepitch.readme\" \"eepitch-blocks\")
(find-eev \"eepitch.readme\" \"eepitch-blocks\")
Many functions like `eepitch-shell':
(find-efunction 'eepitch-bash)
What functions can generate target buffers:
(find-eevfile \"eepitch.el\" \"shell-like sexp\")
(find-efunction 'eepitch)
" rest)))
;; (find-eepitch-intro)
;; (find-pytutnode "Methods of File Objects")
;;; _ _
;;; __ ___ __ __ _ _ __ (_)_ __ | |_ _ __ ___
;;; \ \ /\ / / '__/ _` | '_ \ _____| | '_ \| __| '__/ _ \
;;; \ V V /| | | (_| | |_) |_____| | | | | |_| | | (_) |
;;; \_/\_/ |_| \__,_| .__/ |_|_| |_|\__|_| \___/
;;; |_|
;;
;; (find-intro-links "wrap")
;; «find-wrap-intro» (to ".find-wrap-intro")
(defun find-wrap-intro (&rest rest) (interactive)
(let ((ee-buffer-name "*(find-wrap-intro)*"))
(apply 'find-estring-lv "\
\(Re)generate: (find-wrap-intro)
Source code: (find-eev \"eev-intro.el\" \"find-wrap-intro\")
More intros: (find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
Eepitch and eev
===============
Eepitch defines only two keys - and - and is a
particular case of something more general: \"wrapping commands\", that
follow these conventions:
1) they are bound to meta-shift-letter keys (M-T, M-F, M-M, ...),
2) they transform the current line and then move down,
3) they produce Lisp code meant to be executed with `M-e' or `F8',
4) they are listed at:
(find-efunctiondescr 'eev-mode \"M-F\")
5) their keybindings are only available when eev-mode is turned on.
To understand how they work, please follow the instructions below and
try them here. Note that this buffer is a sandbox, and it can be
recreated by executing the sexp \"(find-wrap-intro)\" at the top.
Note that the wrapping commands are all bound to key sequences of
the form meta-SHIFT-letter - don't forget the shift!!!
: produce an eepitch block
===============================
If you type on a line containing just the word \"shell\" you get
three lines, like this:
(eepitch-shell)
(eepitch-kill)
(eepitch-shell)
We call a block of three lines like this an \"eepitch block\", and
eepitch blocks can be used to set up interactions with external
programs. Try typing on the lines that say \"shell\" and \"python\"
below, and use them to send some lines to bash and to a python
interpreter (with ):
bash
export PS1='$PWD% '
cd /tmp/
function ee () { set -v; . /tmp/ee.sh; set +v; }
rm -v /tmp/ee.sh
cat > /tmp/ee.sh <<'%%%'
echo Hello
cd /etc/
%%%
cat /tmp/ee.sh
bash /tmp/ee.sh
ee
python
square = lambda x: x*x
square(5)
: hyperlink to a file or a directory
=========================================
If you type on the lines below,
/etc/
/tmp/
~/
~/.emacs
you get hyperlinks like these:
# (find-fline \"/etc/\")
# (find-fline \"/tmp/\")
# (find-fline \"~/\")
# (find-fline \"~/.emacs\")
: hyperlink to the output of a shell command
=================================================
If you type on a line containing a shell command you get a
hyperlink that starts with `find-sh', and that when followed opens a
temporary buffer with the output of that shell command, like these:
# (find-sh \"find --help\")
# (find-sh \"find /etc | sort\")
# (find-sh \"find /etc -type d | sort\")
# (find-sh \"find /etc -type d -maxdepth 1 | sort\")
# (find-sh \"find /etc -type d -maxdepth 2 | sort\")
Try it here:
dict smop
dict 'minor detail'
If you have the packages dict, dictd and dict-jargon installed
these hyperlinks will show you the meaning of the expressions
\"smop\" and \"minor detail\".
# (find-sh \"dict smop\")
# (find-sh \"dict 'minor detail'\")
: hyperlink to a manpage
=============================
Try here:
1 tac
All wrapping functions
======================
Below is a list of all wrapping functions, with tests and
hyperlinks:
(eek \"2* M-A ;;; Test eewrap-anchor\")
Source: (find-eev \"eev-wrap.el\" \"eewrap-anchor\")
;;
(eek \"2* M-C ;;; Test eewrap-code-c-d\")
Source: (find-eev \"eev-wrap.el\" \"eewrap-code-c-d\")
foo /tmp/foobar/
(eek \"2* M-D ;;; Test eewrap-debian\")
Source: (find-eev \"eev-wrap.el\" \"eewrap-debian\")
bash
(eek \"2* M-F ;;; Test eewrap-find-fline\")
Source: (find-eev \"eev-wrap.el\" \"eewrap-find-fline\")
/tmp/foobar/
(eek \"2* M-J ;;; Test eewrap-eejump\")
Source: (find-eev \"eev-wrap.el\" \"eewrap-eejump\")
422 (find-eev-intro \"find-wrap-intro\")
(eek \"2* M-J ;;; Test eewrap-eejump\")
Source: (find-eev \"eev-wrap.el\" \"eewrap-eejump\")
42
(eek \"2* M-M ;;; Test eewrap-man\")
Source: (find-eev \"eev-wrap.el\" \"eewrap-man\")
1 tac
(eek \"2* M-P ;;; Test eewrap-pdflike\")
Source: (find-eev \"eev-wrap.el\" \"eewrap-pdflike\")
foopdf $S/http/foo.org/bar.pdf
(eek \"2* M-R ;;; Test eewrap-rm/mkdir/cd\")
Source: (find-eev \"eev-wrap.el\" \"eewrap-rm/mkdir/cd\")
/tmp/foo/
(eek \"2* M-S ;;; Test eewrap-sh\")
Source: (find-eev \"eev-wrap.el\" \"eewrap-sh\")
seq 1 20
(eek \"2* M-T ;;; Test eewrap-eepitch\")
Source: (find-eev \"eepitch.el\" \"eewrap-eepitch\")
python
(eek \"2* M-V ;;; Test eewrap-audiovideo\")
Source: (find-eev \"eev-wrap.el\" \"eewrap-audiovideo\")
slimetutorial /tmp/slime-tutorial.mp4
(eek \"2* M-Z ;;; Test eewrap-zsh\")
Source: (find-eev \"eev-wrap.el\" \"eewrap-zsh\")
echo $SHELL
(eek \"2* <> ;;; Test eewrap-eewrap\")
Source: (find-eev \"eev-wrap.el\" \"eewrap-eewrap\")
U user-defined a b c
Wrapping functions generate hyperlinks
======================================
...this is a slogan - a huge idea, in a very shortened form. In its
full form, that would be:
(Some) wrapping function provide one of the basic ways to produce
elisp hyperlinks quickly; the second basic way, which is a bit more
complex conceptually, is via Elisp hyperlinks buffers. This, and the
whole rationale behind generating and using elisp hyperlinks, is
explained here:
(find-links-intro \"Elisp hyperlinks buffers\")
The \"some\" in beginning of the long version of the slogan, above, is
because a few of the wrapping commands, for example, and ,
are used to produce things that are not hyperlinks - usually other
kinds of scripts.
# Local Variables:
# coding: raw-text-unix
# ee-anchor-format: \"«%s»\"
# End:
" rest)))
;; (find-wrap-intro)
;;; _ _ _
;;; | (_)_ __ | | _____
;;; | | | '_ \| |/ / __|
;;; | | | | | | <\__ \
;;; |_|_|_| |_|_|\_\___/
;;;
;; (find-intro-links "links")
;; «find-links-intro» (to ".find-links-intro")
(defun find-links-intro (&rest rest) (interactive)
(let ((ee-buffer-name "*(find-links-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-links-intro)
Source code: (find-eev \"eev-intro.el\" \"find-links-intro\")
More intros: (find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
What is a hyperlink?
====================
In a previous tutorial - (find-eval-intro) - we saw that several
kinds of sexps can be used as hyperlinks. For example, these:
(find-fline \"/tmp/\")
(find-node \"(emacs)Lisp Eval\")
(find-efunctiondescr 'find-file)
(find-efunction 'find-file)
(find-man \"cat\")
Hyperlinks in a web browser _usually_ take us to a different
page, or to a different position in the same page, and in those
cases it is possible to go back to previous position from there;
but sometimes hyperlinks - or webpage buttons - are associated to
Javascript code, and \"following the link\" then means executing
that code. Web browsers try to make it impossible to have
hyperlinks or webpages that will send out your private
information, or that will put your system in a unusable state.
Security is web browsers is achieved by restricting what the
scripts in a page can do.
Sexp hyperlinks, in contrast, can do essentially anything - and,
instead of _security_, they have _transparency_. The code that a
sexp hyperlink will execute is visible, and users are supposed to
know that sexp hyperlinks with `find-fline', `find-node',
`find-efunctiondescr', etc, are very safe - but the ones that
start with `find-sh' may not be. It is possible to write
something like:
(find-sh \"\")
but it is not possible to hide that action behind an
innocent-looking button that says \"click for a larger image\".
So, _any_ elisp sexp can be _used_ as a sexp hyperlink; but
people are only going to follow a sexp hyperlink if they can more
or less predict (quickly!) what that hyperlink is going to do...
Readability is important, so let's take a look at the most common
kinds of hyperlinks.
Elisp hyperlinks buffers
========================
Emacs has several help commands, whose bindings start with `C-h',
that display their information in (temporary) \"help buffers\" -
and in many cases these generated help buffers have hyperlinks,
that can be followed by typing on them.
Eev has something similar, but using the prefix `M-h' and
following very different design decisions. Let's start with a
comparison, between Emacs's `C-h f' (`describe-function') and
eev's `M-h M-f' (`find-efunction-links'). Remember that `M-e'
accepts prefix arguments, and that `M-2 M-e' displays the target
of a hyperlink at another window without switching to there; use
that on the two sexps below to see the results by yourself:
\"C-h f find-file\" -> (find-efunctiondescr 'find-file)
\"M-h M-f find-file\" -> (find-efunction-links 'find-file)
Note that we used `find-efunctiondescr' instead of
`describe-function'; `find-efunctiondescr' is a variant of
`describe-function' that that follows eev's conventions, as
explained here:
(find-eval-intro \"main conventions\")
`C-h f find-file' produces a buffer with readable text and
\"usual\" hyperlinks that can be followed by typing RET on them,
while `M-h M-f find-file' produces a buffer like this:
___________________________________________________________
|# (find-efunction-links 'find-file) |
|# (where-is 'find-file) |
|# (describe-function 'find-file) |
|# (find-efunctiondescr 'find-file) |
|# (find-efunction 'find-file) |
|# (find-efunctionpp 'find-file) |
|# (find-efunctiond 'find-file) |
|# (find-estring (documentation 'find-file)) |
|# (find-estring (documentation 'find-file t)) |
|# (symbol-file 'find-file 'defun) |
|# (find-fline (symbol-file 'find-file 'defun)) |
| |
|# (Info-goto-emacs-command-node 'find-file) |
|# (find-enode \"Command Index\" \"* find-file:\") |
|# (find-elnode \"Index\" \"* find-file:\") |
| |
| |
|--:**- *Elisp hyperlinks* All L1 (Fundamental eev)--|
|___________________________________________________________|
What is that?...
Elisp hyperlinks buffers conventions
====================================
Let's refer to Emacs's help buffers as \"C-h buffers\" and to
eev's elisp hyperlink buffers as \"M-h buffers\". Here is a quick
list of the main differences and conventions; some of them will
be expanded later:
1) C-h buffers are usually named \"*Help*\", while
M-h buffers are usually named \"*Elisp Hyperlinks*\";
2) C-h buffers are generated by functions called \"describe-*\",
M-h buffers are generated by functions called \"find-*-links\";
3) C-h buffers may contain \"usual-looking\" links, that can be
followed by typing RET on them, and this is implemented via
\"buttons\"; C-h buffers are \"ascii plus text properties\",
while M-h buffers are plain ascii;
4) C-h buffers are read-only, while
M-h buffers are read-and-write. The idea is that we can not
only follow the hyperlinks in a M-h buffer but also modify
them - usually by \"refining\" them, like this,
(find-eval-intro \"Refining hyperlinks\")
then test the modified versions, and copy-and-paste those
hyperlinks to other, more permanent places. This is much
easier to do when we are working in plain ascii; the buttons
in C-h buffers are non-trivial to create, to edit and to
save.
5) C-h buffers are _readable_, while
M-h buffers may look like (technical) gibberish.
This is intentional - M-h buffers have a do-it-yourself,
\"I'm the result of a 5-minute hack\" feeling because most
of them started just like that, as 5-minute hacks that
turned out to be useful enough, and only suffered very minor
changes later on. Try this:
(find-find-links-links)
Most `find-*-links' were created from that template - and it
should be easy to create other ones.
5) Many `M-h' commands, like `M-h f' and `M-h M-i', generate
sexp hyperlinks that \"point to where we are now\"; but once
we are in an M-h buffer this idea - whose basis is:
from (almost) anywhere in Emacs it should to be easy to
create a hyperlink to where we are now - changes to:
6) The first line (the \"top sexp\") of an M-h buffer
regenerates the buffer. And, at last,
7) The elisp hyperlinks in M-h buffers are prefixed by the
string in `ee-hyperlink-prefix'.
`find-here-links'
=================
The most important of the commands that generates buffers with elisp
hyperlinks - \"M-h commands\", in the terminology explained above - is
`find-here-links', which integrates most of the functionalities of
several more basic M-h commands. We will explain first what it _does_,
then its _usage_.
`find-here-links' is bound to `M-h M-h' to make it very easy to
invoke. If you are reading this then \"here\" means the buffer
\"*(find-links-intro)*\", in a certain position. Try to type `M-h M-h';
you will get a buffer like this,
____________________________________________________________
|# See: |
|# (find-links-intro \"`find-here-links'\") |
|# (find-efunctiondescr 'eev-mode \"M-h M-h\") |
| |
|# (find-links-intro) |
| |
| |
|--:**- *Elisp hyperlinks* All L1 (Fundamental eev) -|
|____________________________________________________________|
which contains a 3-line header with help links, that we will explain
soon, and then a link to \"here\", i.e., to the buffer
\"*(find-links-intro)*\". Note that the link
(find-links-intro)
can be \"refined\" to, for example,
(find-links-intro \"which contains a 3-line header\")
using the tricks described in these sections:
(find-eval-intro \"Refining hyperlinks\")
(find-eval-intro \"Producing and refining hyperlinks\")
(find-eval-intro \"Producing and refining hyperlinks\" \"`M-h M-2'\")
(find-eval-intro \"Producing and refining hyperlinks\" \"`M-h2hy'\")
but `find-here-links' by itself only produces \"unrefined\" links - so
when we say that `find-here-links' produces links to \"here\" we mean
just \"to the current buffer\", not \"to the a certain position in the
current buffer\".
`find-here-links' works for several kinds of \"here\"s - it works for
intros like this one, for Info pages, for manpages, for files and
directories, for descriptions of Emacs functions and variables, and
for a few other cases. Try the sexps below:
(find-here-links-test '(find-eval-intro))
(find-here-links-test '(find-node \"(dir)Top\"))
(find-here-links-test '(find-enode \"Lisp Eval\"))
(find-here-links-test '(find-fline \"~/\"))
(find-here-links-test '(find-eevfile \"eepitch.el\"))
(find-here-links-test '(find-efunction 'ee-eval-last-sexp))
(find-here-links-test '(find-efunctiondescr 'ee-eval-last-sexp))
(find-here-links-test '(find-evardescr 'ee-hyperlink-prefix))
(find-here-links-test '(find-efacedescr 'eepitch-star-face))
(find-here-links-test '(find-ecolors \"\\nred\"))
(find-here-links-test '(find-efaces \"eepitch-star-face\"))
(find-here-links-test '(find-customizegroup 'rcirc))
(find-here-links-test '(find-man \"1 cat\"))
[^ oops, this test doesn't work on multi-window settings...]
Each one of them tests a different case of `find-here-links',
creating a window setup like this:
______________________________________
| | |
| | target of |
| | sexp |
| this |______________________|
| intro | |
| | result of running |
| | find-here-links on |
| | [target of sexp] |
|_______________|______________________|
The cursor is kept at the left window (\"this intro\"), so you
can compare the different cases using just , , and M-e.
`find-here-links': usage patterns
=================================
Typically what happens is this. We are putting our notes - eepitch
blocks, hyperlinks, etc - in a certain file; let's refer to it as the
\"e-script\". Then we start to navigate for information, and we find
something interesting. We want to add a link pointing to that
\"something interesting\" to our e-script notes - but for that we need
to produce that sexp hyperlink, and ideally we would like to do that
in a way that does not disturb much our attention. Consider this
diagram [note: it DOES NOT imply that the Emacs frame is split into three
windows - typically we will switch between buffers in a single window]:
______________________________________
| | |
| | something |
| ==> interesting |
| e-script |_________||___________|
| | \\/ |
| | result of running |
| <== find-here-links on |
| | [sthing intrstng] |
|_______________|______________________|
and this series of steps:
0. We start navigating from the e-script buffer, and when we
1. find something interesting [in another buffer], we
2. run `find-here-links' at the \"something interesting\" buffer,
3. identify among the sexps in the find-here-links buffer one that
points to that \"something interesting\",
4. copy that sexp to the kill-ring,
5. go back to the e-script buffer,
6. insert that sexp into the e-script buffer,
7. execute that sexp to go back to the \"something interesting\",
8. continue navigating & doing stuff.
At (8) we are essentially back to (1), but we have added to our
e-script buffer a link to \"something interesting\".
Note that to add refining we need to add a step before (2) and
another one after (3):
1.9. select a string to search for and copy it to the kill-ring,
3.1. refine that sexp using the \"string to search for\" (with M-h2hy)
\[TO DO: explain the keys that I normally use to perform all
this; explain why I am not the right person to optimize these
steps - because I can type these key sequences without thinking,
and step (3) sometimes gives several sexps for us to choose from]
Basic and non-basic hyperlinks
==============================
How can we learn to recognize what each hyperlink sexp does? And
which ones are safe(r), and which ones are not? How do we
classify all hyperlink sexps?
We can start by dividing the hyperlink functions into a fixed set
of \"basic\" ones and an unbounded set of \"non-basic\" ones. In
the buffer generated by
(find-efunction-links 'find-file)
these hyperlinks
(find-efunctiondescr 'find-file)
(find-efunction 'find-file)
(find-efunctionpp 'find-file)
(find-efunctiond 'find-file)
(find-estring (documentation 'find-file))
(find-estring (documentation 'find-file t))
(find-fline (symbol-file 'find-file 'defun))
calls \"basic\" eev hyperlink functions, that are just interfaces
to Emacs function slightly tweaked into functions that follow
eev's conventions - they are refinable, use the current window,
etc. But these two,
(find-enode \"Command Index\" \"* find-file:\")
(find-elnode \"Index\" \"* find-file:\")
are generated by calls to `code-c-d' or similar functions, that
generate some elisp code as text, from templates, and evaluate
that code, as explained here:
(find-code-c-d-intro)
(find-pdf-like-intro)
(find-audiovideo-intro)
The `code-*' functions define hyperlink functions whose names are
of the form `find-{stem}{suffix}', and each of these `code-*'
function has an associated `find-code-*' function that just
displays what the corresponding `code-*' would execute. So one
way to get acquainted to the most common of these suffixes is to
follow these hyperlinks:
(find-code-c-d \"CODE\" \"/DIR/\" :info \"INFO\")
(find-code-pdf \"CODE\" \"FILE.pdf\")
(find-code-pdf-text \"CODE\" \"FILE.pdf\")
(find-code-audio \"CODE\" \"FILE\")
(find-code-video \"CODE\" \"FILE\")
From these only the functions whose suffixes end with \"sh\" or
\"sh0\" and inherently dangerous; the others are usually safe if
no hacks had been done.
Some hyperlinks functions - for example the ones created by
`code-pdf', `code-audio', etc - invoke external programs, and
_may_ behave in bad ways when given unsafe arguments; these
functions are implemented using the low-level functions
`find-bgprocess' and `find-callprocess', which of course are
unsafe too.
Also, the functions `find-*-links', `find-*-intro' and
`find-code-*' simply create temporary buffers, and are thus very
safe - but, as always, think carefully before executing any code
that they generate.
ee-hyperlink-prefix
===================
`ee-hyperlink-prefix' is both a variable and a function that
helps us set that variable; it started to an experiment on how to
create an alternative to `M-x customize' and ended up becoming
the inspiration for all the `find-*-links' functions.
If you run `M-x ee-hyperlink-prefix' you should get a buffer like
this:
___________________________________________________________
|# (ee-hyperlink-prefix) |
|# (setq ee-hyperlink-prefix \"# \") |
| |
|# (setq ee-hyperlink-prefix \"# \") |
|# (setq ee-hyperlink-prefix \";; \") |
|# (setq ee-hyperlink-prefix \"-- \") |
|# (setq ee-hyperlink-prefix \"// \") |
|# (setq ee-hyperlink-prefix \"% \") |
| |
| |
|--:**- *Elisp hyperlinks* All L1 (Fundamental eev)--|
|___________________________________________________________|
where the first line regenerates the buffer, the second line sets
the variable `ee-hyperlink-prefix' to its current value, and each
one of the lines after the first blank line sets
`ee-hyperlink-prefix' to one of several fixed common values. If
we change the value of `ee-hyperlink-prefix' with one of the
`setq's and execute the first line again we see that all the
prefixes, plus the argument \"# \" in the second line, change.
Try this, with `M-2 M-e' on each line:
(progn (setq ee-hyperlink-prefix \"# \") (ee-hyperlink-prefix))
(progn (setq ee-hyperlink-prefix \"% \") (ee-hyperlink-prefix))
The first line regenerates the buffer
=====================================
\[To do: explain this convention with examples; explain the
conventions for the \"variants of the first line\"\]
(find-find-links-links)
(find-find-links-links \"\\\\M-u\")
(find-find-links-links \"\\\\M-u\" \"USERTEST\")
(find-find-links-links \"\\\\M-u\" \"USERTEST\" \"a\")
(find-find-links-links \"\\\\M-u\" \"USERTEST\" \"a b\")
(find-find-links-links \"\\\\M-u\" \"USERTEST\" \"a b c\")
Pointing to where we are now
============================
Several of the `M-h' commands are mainly meant to help us
generate hyperlinks to \"where we are now\": to the current file,
to the current Info page, to the current `find-*-intro', to an
Emacs function or variable we are inspecting, to the current
buffer, and so on. They don't try to be very smart -
\[To do: write this\]
(find-efunctiondescr 'eev-mode)
(find-efunctiondescr 'eev-mode \"M-h f\")
(eek \"M-h M-i\")
(find-enode \"Lisp Eval\")
(progn (find-enode \"Lisp Eval\") (eek \"M-h M-i\"))
(eek \"M-h f ;; find-file-links\")
(eek \"M-h M-b ;; find-ebuffer-links\")
for example, `M-h M-i' generates links to
the current \"intro\" buffer - like this one - _and_ to the
current Info page (the \"i\" in `M-h M-i' has two meanings).
Try:
(eek \"M-h M-i\")
you should get something like this:
___________________________________________________________
|# (find-einfo-links \"links\") |
| |
|[No \"*info*\" buffer] |
| |
|# (find-links-intro) |
| |
| |
|--:**- *Elisp hyperlinks* All L1 (Fundamental eev)--|
|___________________________________________________________|
The rest of the buffer
======================
Several elisp hyperlinks buffers are composed of two parts: a
series of links at the top, and then a template-generated text
that is mean to be copied to somewhere else. The canonical
example is
(find-eev-update-links)
which ends with stuff that you can copy to your .emacs file to
make Emacs load eev by default. The end of the buffer generated
by `find-eev-update-links' looks more or less like this:
____________________________________________________________
|# (ee-copy-rest 0 '(find-fline \"~/.emacs\")) |
| |
|;; Load eev2. |
|;; See: (find-file \"~/eev/\") |
|;; (find-file \"~/eev/eev-readme.el\") |
|;; Generated by: (find-eev-update-links \"~/eev/\") |
|;; |
|(add-to-list 'load-path \"~/eev/\") |
|(require 'eev2-all) ; (find-eev \"eev2-all.el\") |
|(eev-mode 1) ; (find-eev \"eev-mode.el\") |
| |
| |
|--:**- *Elisp hyperlinks* Bot L56 (Fundamental eev)---|
|____________________________________________________________|
The line with `ee-copy-rest' is a hack. Its first argument is a
number, that we will call the \"skip\", and the second is
a (quoted) sexp hyperlink, that we will call the \"code\". The
rule that defines what is the \"rest of the buffer\" is this:
Move to the beginning of the next line, then skip (i.e., move
down) more SKIP lines. The rest of the buffer is everything
from that point on.
A sexp like `(ee-copy-rest ...)' does several things:
1) it highlights the rest of the buffer temporarily (like as
with `M-0 M-e'),
2) it copies the rest of the buffer to the kill ring (like as
with `M-w'),
3) it runs CODE to open its target in a window at the right
side (like as with `M-3 M-e')
\[To do: add examples - including examples that let us create Lua
scripts etc\]
" rest)))
;; (find-links-intro)
;; (find-eevfile "eev-template.el" "defun find-efunction-links")
;;; _ _ _ _
;;; ___ ___ __| | ___ ___ __| | (_)_ __ | |_ _ __ ___
;;; / __/ _ \ / _` |/ _ \_____ / __|____ / _` |_____| | '_ \| __| '__/ _ \
;;; | (_| (_) | (_| | __/_____| (_|_____| (_| |_____| | | | | |_| | | (_) |
;;; \___\___/ \__,_|\___| \___| \__,_| |_|_| |_|\__|_| \___/
;;;
;; «find-code-c-d-intro» (to ".find-code-c-d-intro")
(defun find-code-c-d-intro (&rest rest) (interactive)
(let ((ee-buffer-name "*(find-code-c-d-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-code-c-d-intro)
Source code: (find-eev \"eev-intro.el\" \"find-code-c-d-intro\")
More intros: (find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
Avoiding full path names
========================
Suppose that you have downloaded (\"psne\"-ed) this URL,
http://www.lua.org/ftp/lua-5.1.4.tar.gz
with `M-x brep' - see:
(find-psne-intro)
and you unpacked that tarball into the directory ~/usrc/ (I
prefer to use that instead of /usr/src/) with:
tar -C ~/usrc/ -xvzf $S/http/www.lua.org/ftp/lua-5.1.4.tar.gz
Now you can access some directories and files of the unpacked
tarball with:
(find-fline \"~/usrc/lua-5.1.4/\")
(find-fline \"~/usrc/lua-5.1.4/src/\")
(find-fline \"~/usrc/lua-5.1.4/src/lstrlib.c\")
(find-fline \"~/usrc/lua-5.1.4/test/\")
(find-fline \"~/usrc/lua-5.1.4/test/README\")
(find-fline \"~/usrc/lua-5.1.4/doc/\")
(find-w3m \"~/usrc/lua-5.1.4/doc/contents.html\")
but it's a bit clumsy to have to use the \"~/usrc/lua-5.1.4/\"
every time, so eev provides a nice way to define shorthands. We
want to be able to write just this instead of the sexps above,
(find-lua51file \"\")
(find-lua51file \"src/\")
(find-lua51file \"src/lstrlib.c\")
(find-lua51file \"test/\")
(find-lua51file \"test/README\")
(find-lua51file \"doc/\")
(find-lua51w3m \"doc/contents.html\")
and here the directory \"~/usrc/lua-5.1.4/\" became a mnemonic
\"lua51\" in the middle of the names of some functions.
We will call these sexps with \"lua51\" \"shorter hyperlinks\".
Shorter hyperlinks
==================
How can we generate the definitions for `find-lua51file' and
`find-lua51w3m' from just the strings \"lua51\" and
\"~/usrc/lua-5.1.4/\"? Try this:
(find-code-c-d \"lua51\" \"~/usrc/lua-5.1.4/\")
you will get a temporary buffer with a lot of Lisp code -
including a definition for `find-lua51file' and another one for
`find-lua51w3m'. That Lisp code has not been executed yet; the
function `find-code-c-d' is just for debugging, and we can regard
it as a hyperlink to the code that this sexp would execute:
(code-c-d \"lua51\" \"~/usrc/lua-5.1.4/\")
So, to define a family of functions including `find-lua51file'
and `find-lua51w3m', for a given \"mnemonic\" - \"lua51\" in this
case - and a given \"directory\" - \"~/usrc/lua-5.1.4/\" - we run
this:
(code-c-d \"lua51\" \"~/usrc/lua-5.1.4/\")
which generates a block of Lisp code, as a string, and evaluates
it. Note: the original (and rather confusing) terminology for the
\"mnemonic\" was \"code\"; that's why the \"c\" in `code-c-d'.
Extra arguments to `code-c-d'
=============================
`code-c-d' supports extra arguments - for example, this works:
(find-code-c-d \"el\" \"~/usrc/emacs/lisp/\" :info \"elisp\")
Look at the end of the generated code and you will see that it
has a definition for `find-elnode' - such that
(find-elnode \"Constant Variables\")
is a shorthand (a \"shorter hyperlink\") for:
(find-node \"(elisp)Constant Variables\")
What is important to understand here is how these definitions
with extra arguments are structured - so that you will be able to
understand the source code when you need to. Both `code-c-d' and
`find-code-c-d' are defined with a `&rest' in their argument
lists, like this (NOTE: do not execute these defuns!):
(defun code-c-d (c d &rest rest) ...)
(defun find-code-c-d (c d &rest rest) ...)
and they both invoke `ee-code-c-d', which does all the template
work and returns a big string; `ee-code-c-d' passes its `rest'
argument to a recursive function called `ee-code-c-d-rest', and
for each one of the suported keywords there is a corresponding
function, also recursive; for `:info' it is called
`ee-code-c-d-:info'. Their specifications are like this:
(defun ee-code-c-d (c d &rest rest) ...)
(defun ee-code-c-d-rest (rest) ...)
(defun ee-code-c-d-:info (manual &rest rest) ...)
and one very non-obvious trick is used to make the code short.
When `ee-code-c-d-rest' and `ee-code-c-d-:info' are run they can
access the values the `c' and the `d' that were passed to
`ee-code-c-d' (due to dynamic scoping), so `c' and `d' do not
need to be passed down explicitly as arguments.
Try:
(find-code-c-d \"CODE\" \"/DIR/\" :info \"INFO\")
Other similar functions
=======================
See: (find-brxxx-intro)
(find-pdf-like-intro)
(find-audiovideo-intro)
Try: (find-code-pdf \"CODE\" \"FILE.pdf\")
(find-code-pdf-text \"CODE\" \"FILE.pdf\")
(find-code-audio \"CODE\" \"FILE.mp3\")
(find-code-video \"CODE\" \"FILE.mp4\")
" rest)))
;; (find-TH "eev-article")
;; (find-TH "eev-article" "shorter-hyperlinks")
;; (find-code-c-d-intro)
;;; _ _
;;; _ __ ___ _ __ ___ (_)_ __ | |_ _ __ ___
;;; | '_ \/ __| '_ \ / _ \_____| | '_ \| __| '__/ _ \
;;; | |_) \__ \ | | | __/_____| | | | | |_| | | (_) |
;;; | .__/|___/_| |_|\___| |_|_| |_|\__|_| \___/
;;; |_|
;;
;; «find-psne-intro» (to ".find-psne-intro")
;; (find-TH "eev-article" "local-copies")
;; (find-angg ".emacs" "brep")
;; (find-eev "eev-browse-url.el" "find-psne-links")
;; (find-eev "eev-browse-url.el" "brep")
(defun find-psne-intro (&rest rest) (interactive)
(let ((ee-buffer-name "*(find-psne-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-psne-intro)
Source code: (find-eev \"eev-intro.el\" \"find-psne-intro\")
More intros: (find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
Local copies of files from the internet
=======================================
Emacs knows how to fetch files from the internet, but for most
purposes it is better to use local copies. Suppose that the
environment variable $S is set to ~/snarf/; then running this
(eepitch-shell)
(eepitch-kill)
(eepitch-shell)
mkdir -p $S/http/www.gnu.org/software/emacs/
cd $S/http/www.gnu.org/software/emacs/
wget http://www.gnu.org/software/emacs/emacs-paper.html
echo 'http://www.gnu.org/software/emacs/emacs-paper.html' >> ~/.psne.log
# (find-fline \"$S/http/www.gnu.org/software/emacs/emacs-paper.html\")
# (find-w3m \"$S/http/www.gnu.org/software/emacs/emacs-paper.html\")
creates a local copy of `emacs-paper.html' inside ~/snarf/http/
and appends the URL to the file ~/.psne.log. The two lines in
comments are hyperlinks to the local copy; The `find-fline' opens
it as a file in the obvious way, and `find-w3m' opens it \"as
HTML\", using a text-mode web browser called w3m that can be run
either in standalone mode or inside Emacs; `find-w3m' uses w3m's
Emacs interface, and it accepts extra arguments, which are
treated as a pos-spec-list.
The old way: psne
=================
A long time ago eev used to include a shell function called
`psne' that ran all that with a single command. This:
psne http://www.gnu.org/software/emacs/emacs-paper.html
would run the `mkdir', the `cd', the `wget' and the `echo' above.
If psne were just a shell script then it wouldn't be able to
change the current directory for the calling shell, so it had to
be defined as shell function instead of a script, and the user
had to patch his ~/.bashrc (or ~/.zshrc, or whatever) to install
the definition for psne and make it available. That was VERY
clumsy.
From now on we will use \"psne\" as a verb: to psne a URL means
to download a local copy of it into the right place, change to
its directory and save its name into the file \"~/.psne.log\".
The new way: M-x brep
=====================
Try to run this:
(find-psne-links \"http://www.gnu.org/software/emacs/emacs-paper.html\")
or, equivalently, put the point on the URL below and then run
`M-x brep':
http://www.gnu.org/software/emacs/emacs-paper.html
You will get a temporary buffer for psne-ing the URL above. It
will contain a `mkdir', a `cd', a `wget' and an `echo', plus an
eepitch block and some elisp hyperlinks, and it can be executed
with `F8's. Moral of the story: the \"new\" way to download a
local copy of a url is to put the point on it, then run `M-x
brep', then execute the resulting e-script. This does not require
any patching of rcfiles, as the shell-function version of `psne'
used to do.
The environment variable $S
===========================
If when eev is loaded by Emacs the environment variable $S is
unset, it will be set to a default value - namely, to the
expansion of \"$HOME/snarf\". Processes started from Emacs, such
as shells created with `eepitch-shell' or `find-sh', or external
terminals created by sexps like
(find-bgprocess \"xterm\")
(find-bgprocess \"gnome-terminal\")
(find-bgprocess \"eterm\")
will then inherit that value. Try it:
(getenv \"S\")
(find-sh0 \"echo $S\")
(eepitch-shell)
(eepitch-kill)
(eepitch-shell)
echo $S
Try also to create an external shell not from Emacs - for
example, from your window manager's list of available
applications, or from a text-mode login - and run \"echo $S\"
there: you will notice that $S is unset.
Old versions of eev used to require the user to run a script that
would patch his rcfiles (i.e., ~/.bashrc, ~/.zshrc, etc) to set
$S on startup. That turned out to be unreliable - it was better
to teach people how to distinguish those processes that inherit
$S from Emacs from those that don't, and let the experts patch
their rcfiles by hand.
`browse-url' and friends
========================
If you place the point on the URL below
http://www.gnu.org/software/emacs/emacs-paper.html
and run `M-x browse-url', Emacs will make an external browser
visit the remote version of that URL. One (bad) way to visit the
local copy of that URL is to modify the URL above by hand to
adjust it to your value of $S, until you obtain something like
this:
file:///home/edrx/snarf/http/www.gnu.org/software/emacs/emacs-paper.html
and then run `M-x browse-url' on it.
One - rather primitive - way of visiting the local copy of that
URL with find-file is to modify the URL by hand, replacing its
\"http://\" with n \"$S/http/\", and then visit that file. For
example:
http://www.gnu.org/software/emacs/emacs-paper.html
(find-fline \"$S/http/www.gnu.org/software/emacs/emacs-paper.html\")
If you put the point on the URL and run `M-x brfl' on it you will
visit the local copy \"as a file\", with `find-file' /
`find-fline'. Visiting URLs - or their local copies - is
something that we do so frequently that we need ways to do that
with few keystrokes, which is why `brfl' has a short - and
cryptic - name. The conventions are:
\"br\" is the common prefix for all the browse-url-like
functions in eev,
\"f\" means to use `find-fline' (or, equivalently, `find-file'),
\"l\" is an optional suffix meaning to use the local copy.
The details on how to create these \"brxxx functions\" are here:
(find-brxxx-intro)
" rest)))
;; (find-enode "Command Index" "browse-url")
;; (find-efunction 'browse-url)
;; (find-elnode "System Environment")
;; (find-enode "Environment")
;; (find-eevfile \"eev.el\" \"$HOME/snarf\")
;; (find-psne-intro)
;;; _ _ _
;;; | |__ _ ____ ____ ____ __ (_)_ __ | |_ _ __ ___
;;; | '_ \| '__\ \/ /\ \/ /\ \/ /____| | '_ \| __| '__/ _ \
;;; | |_) | | > < > < > <_____| | | | | |_| | | (_) |
;;; |_.__/|_| /_/\_\/_/\_\/_/\_\ |_|_| |_|\__|_| \___/
;;;
;; «find-brxxx-intro» (to ".find-brxxx-intro")
(defun find-brxxx-intro (&rest rest) (interactive)
(let ((ee-buffer-name "*(find-brxxx-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-brxxx-intro)
Source code: (find-eev \"eev-intro.el\" \"find-brxxx-intro\")
More intros: (find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
Introduction
============
We saw in
(find-psne-intro)
(find-psne-intro \"M-x brep\")
(find-psne-intro \"M-x brfl\")
(find-psne-intro \"`browse-url' and friends\")
that we can use `M-x brep' to download local copies of files from
the internet, and that `M-x brfl' on a URL runs `find-fline' on
the local copy of that URL. `brep' and `brfl' are
\"`browse-url'-like functions\" defined by eev; we will refer to
them, and to other such functions, as \"brxxx-functions\". Every
brxxx-function is an interactive interface to some \"base
function\"; for `brep' and `brfl' we have:
brxxx-function base function
-------------- -------------
brep find-psne-links
brfl find-fline
What we will see here is how `code-brfile' and `code-brurl' -
which are somewhat similar to `code-c-d' - can be used to define
brxxx-functions from base functions.
A first example
===============
Let's define two trivial base functions, one that expects a URL,
and another one that expects a file name:
(defun foo-url (url) (format \"Got URL: %s\" url))
(defun foo-file (filename) (format \"Got filename: %s\" filename))
Note that they don't do much - they just return explanatory
strings.
These two calls,
(code-brurl 'foo-url :remote 'brshowu :local 'brshowul)
(code-brfile 'foo-file :local 'brshowfl)
define three brxxx-functions: `brshowu' and `brshowul' for the
base function `foo-url', and `brshowfl' for the base function
`foo-file'. You can inspect the definitions by running these
sexps,
(find-code-brurl 'foo-url :remote 'brshowu :local 'brshowul)
(find-code-brfile 'foo-file :local 'brshowfl)
and you can test what `foo-url', `foo-file', `brshowu',
`brshowul', and `brshowfl' do by running the sexps below.
(foo-url \"http://a/b\")
=> \"Got URL: http://a/b\"
(foo-file \"/c/d/e/f\")
=> \"Got filename: /c/d/e/f\"
(brshowu \"http://a/b\")
=> `(foo-url \"http://a/b\") -> \"Got URL: http://a/b\"'
(brshowul \"http://a/b\")
=> `(foo-url \"file:///home/edrx/snarf/http/a/b\") ->
\"Got URL: file:///home/edrx/snarf/http/a/b\"'
(brshowfl \"http://a/b\")
=> `(foo-file \"/home/edrx/snarf/http/a/b\") ->
\"Got filename: /home/edrx/snarf/http/a/b\"'
Now let's go to what matters. Put the point on the URL below, and
run `M-x brshowu', `M-x brshowul' and `M-x brshowfl':
http://a/b
you will see that `brshowu', `brshowul', and `brshowfl' can be
called interactively, and when they are called interactively they
use as their argument either the URL around point, or something
obtained from it - the local file name or a local URL associated
to that URL.
The conversions
===============
One underlying idea behind all this is that we have two
conversion functions, one from URLs to file names, and another
from (absolute) file names to URLs starting with \"file:///\".
They work like this:
http://a/b -> $S/http/a/b -> file:///home/edrx/snarf/http/a/b
/tmp/c -> file:///tmp/c
try:
(ee-url-to-fname \"http://a/b\")
(ee-fname-to-url \"/tmp/c\")
(ee-url-to-local-url \"http://a/b\")
Now execute the sexps below (with `M-2 M-e') to examine the code
that calls to `code-brurl' and `code-brfile' generate and
execute:
(find-code-brurl 'foo-url :remote 'brshowu :local 'brshowul)
(find-code-brfile 'foo-file :local 'brshowfl)
Naming conventions for brxxx-functions
======================================
By convention, each name for a brxxx-function is composed of a
prefix, a stem, and a suffix. The prefix is always \"br\", the
stem is a mnemonic for the base function, and the suffix is
either \"\", \"l\", or \"d\", meaning:
\"\" - use the URL without changes
\"l\" - use the local copy
\"d\" - dired variation (see below)
Here are the stems for some of the brxxx-functions defined by
eev:
Base function receives stem
------------- -------- ----
find-psne-links URL \"ep\"
browse-url-firefox URL \"m\"
find-googlechrome URL \"g\"
find-w3m URL \"w\"
find-fline file name \"f\"
find-audio file name \"audio\"
find-video file name \"video\"
find-xpdf-page file name \"xpdf\"
find-evince-page file name \"evince\"
find-xdvi-page file name \"xdvi\"
find-djvu-page file name \"djvu\"
find-pdf-text file name \"pdftext\"
find-djvu-text file name \"djvutext\"
In our example with `foo-url' and `foo-file' we had:
Base function receives stem
------------- -------- ----
foo-url URL showu
foo-file file name showf
Calling `code-brurl' and `code-brfile'
======================================
(code-brurl '
:remote 'br :local 'brl :dired 'brd)
\\---------------/ \\---------------/ \\----------------/
optional optional optional
(code-brfile ' :local 'brl :dired 'brd)
\\---------------/ \\----------------/
optional optional
This, like many other parts of eev, is a hack with a very concise
calling syntax - so we will see an example first, and then
dissect it to understand precisely how it works. If you are
curious about the inspirations behind it, here they are:
(find-code-c-d-intro)
(find-code-c-d-intro \"find-code-c-d\")
(find-code-c-d-intro \"Extra arguments\")
(find-enode \"Browse-URL\")
The dired variation
===================
In dired mode each line corresponds to a file
" rest)))
;; (find-brxxx-intro)
;;; _
;;; ___ ___ (_)_ _ _ __ ___ _ __
;;; / _ \/ _ \| | | | | '_ ` _ \| '_ \
;;; | __/ __/| | |_| | | | | | | |_) |
;;; \___|\___|/ |\__,_|_| |_| |_| .__/
;;; |__/ |_|
;;
;; (find-elnode "Defining Commands")
;; (find-enode "Arguments")
;; (find-TH "emacs" "eejump")
;; http://angg.twu.net/emacs.html#eejump
;; file:///home/edrx/TH/L/emacs.html#eejump
;; «find-eejump-intro» (to ".find-eejump-intro")
(defun find-eejump-intro (&rest rest) (interactive)
(let ((ee-buffer-name "*(find-eejump-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-eejump-intro)
Source code: (find-eev \"eev-intro.el\" \"find-eejump-intro\")
More intros: (find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
The problem
===========
Suppose that we have several files that we are working on, and we
want a quick way to jump to (i.e., to visit) any of them with
very few keystrokes; moreover,
1) we want our list of files to be preserved between one Emacs
session and another,
2) we know that each \"visit a file\" command will correspond
to an elisp hyperlink.
One quick solution would be to put the list of elisp hyperlinks
in a file, and make the key `M-j' open that file. But then
jumping to a file in that list becomes a two-step process: type
`M-j', move the point to the right line, type `M-e'. This would
be similar to what happens when we use one of the `find-e*'
commands, for example `find-efunction':
(find-efunction 'find-efunction)
(eek \"M-h M-f find-efunction\")
Those intermediate steps - seeing the list, locating visually the
right line, moving to it - are distracting, so we want to add new
items to our wishlist:
3) it should be possible to jump straight to any of the files
in the list, and with very few keystrokes,
4) the list should be stored in a format that lets us see
quickly which are the keystrokes for accessing each item - so
that we won't need to memorize anything,
5) the list should be easy to modify,
6) it should be possible to assign shorter key sequences to
files we visit more often,
7) the source code must be very simple.
A miniature
===========
My original solution was this: I used only one keybinding, `M-j',
that acted differently when invoked with different numeric
prefixes; when invoked as `M-1 M-j' it opened a certain file,
when invoked with `M-2 M-j' it opened another, and so on, and
when it was invoked with an unrecognized prefix or with no prefix
it jumped to its definition in my ~/.emacs. Its code was like
this (NOTE: do not execute these defuns):
;; eejump-simplified (`M-j'):
;; M-1 M-j opens a certain file,
;; M-2 M-j opens another file,
;; when the argument is 11, 22, 33 or 44 do something special,
;; like changing the font;
;; with no argument or with an unrecognized argument jump to the
;; definition of eejump in ~/.emacs; then we can see which numbers
;; correspond to which actions (the source is the documentation!), and
;; we can change the definition if needed - just run `M-e' at the
;; right place to make the changes apply.
;;
\(global-set-key (kbd \"M-j\") 'eejump-simplified)
\(defun eejump-simplified (arg) (interactive \"P\")
(cond ((eq arg 1) (find-file \"~/NOTES\"))
((eq arg 2) (find-file \"~/otherfile.txt\"))
;;
((eq arg 11) (set-frame-font \"fixed\"))
((eq arg 22) (set-frame-font \"terminus-16\"))
((eq arg 33) (set-frame-font \"terminus-bold-16\"))
((eq arg 44) (set-frame-font \"10x20\"))
(t (find-function 'eejump-simplified))))
except that my definition became huge with time as I added to it
more entries for files (and other actions!) that I used often,
and also entries that were used not so often...
All the \"options\" - i.e., all the `(eq arg nnn)' lines - had to
be together in a single very big defun, and there was no way to
add new options temporarily...
Families
========
Let's use a shorthand for key sequences: for example, `M-123j'
instead of `M-1 M-2 M-3 M-j'.
I tend to assign related numbers to related files. For example, I
use the prefix \"5\" for things that are Emacs-related: `M-5j'
visits my .emacs, `M-555j' visits the directory with all of eev's
elisp files, and `M-51j', `M-52j', etc, visit specific eev source
files that I happen to be working on. Also, I use the prefix
\"7\" for things related to LaTeX. So, the \"5*\" family is
composed of Emacs-related files, and the \"7*\" family of
LaTex-related files.
The definition of `eejump-simplified' given above does not
satisfy these two (new!) wishlist items:
8) it should be possible to jump to the definition of the
\"5*\" family by typing something like `M-5678j', where
\"5678\" is a non-assigned number that starts with the \"5*\"
prefix,
9) it should be possible to convert a number/hyperlink pair
very easily into to the code that assigns that elisp hyperlink
as the desired behavior for that number - and it should be
possible to do that both permanently (think in changing the
definition of `eejump-simplified' in your .emacs) and
temporarily (i.e., for the current Emacs session only).
eejump
======
The definition of `eejump' that comes with eev is a bit more
complex than the one given above, and it will not be shown
here (it involves a tricky recursive function) but it satisfies
the 9 wishlist items above. It works in this way: if you type,
say, `M-123j', then:
a) if `eejump-123' is defined, then execute it;
b) otherwise, if `eejump-12*' is defined, execute it;
c) otherwise, if `eejump-1*' is defined, execute it;
d) otherwise, if `eejump-*' is defined, execute it,
and if `eejump-*' also is not defined, you get an error.
Here is a block of \"defun\"s that defines (trivial) meanings for
\"91\", \"92\", \"991\", and \"992\", plus targets for the \"9*\"
family and for the \"99*\" family; it also has two tests in
comments that will be very important for an explanation below.
Let's refer as that, in this section and the next ones, as \"the
block of six defuns (plus four tests)\".
(defun eejump-9* () (find-efunction 'eejump-9*))
(defun eejump-91 () (message \"M-91j\"))
(defun eejump-92 () (message \"M-92j\"))
(defun eejump-99* () (find-efunction 'eejump-99*))
(defun eejump-991 () (message \"M-991j\"))
(defun eejump-992 () (message \"M-992j\"))
;; (find-function-noselect 'eejump-9*)
;; (find-function-noselect 'eejump-99*)
;; (find-efunction 'eejump-9*)
;; (find-efunction 'eejump-99*)
Try to evaluate each of the sexps above with `M-e', then try to
run things like `M-92j' and `M-992j' - they should work - and
then something like `M-99876j'; that will not work, you'll get an
error like \"Don't know where `eejump-99*' is defined\"...
eejump blocks
=============
Let's a call a sequence of defuns for eejumps with the same
prefix, like this, starting with a `(defun eejump-* ...)',
(defun eejump-99* () (find-efunction 'eejump-99*))
(defun eejump-991 () (message \"M-991j\"))
(defun eejump-992 () (message \"M-992j\"))
an \"eejump block\".
There are two sample eejump blocks in eejump.el, for the prefixes
\"\" and \"5\", starting at:
(find-eev \"eejump.el\" \"eejump-*\")
(find-eev \"eejump.el\" \"eejump-5*\")
You should probably copy them to your .emacs, and then start
modifying them.
Making an `eejump-nn*' work
===========================
If you execute a line like
(defun eejump-9* () (find-efunction 'eejump-9*))
then Emacs will only record that `eejump-9*' has been defined in
this buffer - and thus will be able to jump to its definition
when you type something like `M-987j' - if two conditions are
met:
a) the defun is executed with `M-x eval-region', `M-x
eval-buffer', or some variant of `load' or `require' (`M-e'
will not do!),
b) the buffer with the definition is associated to a file; see
these two pages of the Emacs manuals
(find-enode \"Buffers\" \"visiting\")
(find-elnode \"Buffer File Name\")
if that concept is not totally familiar to you.
So, as an experiment, copy the block with six defuns and four
tests above to some buffer associated to a file, mark it, and
execute it with `M-x eval-region'. Now the tests should work -
and key sequences like `M-987j' should also work, and should jump
to the right places. See also:
(find-elnode \"Where Defined\")
Producing `eejump-nnn's and `eejump-nnn*'s
==========================================
Look again to the block of six \"defun\"s above. Now type `M-J'
on each of the six lines below:
9
91 (message \"M-91j\")
92 (message \"M-92j\")
99
991 (message \"M-991j\")
992 (message \"M-992j\")
you will notice that you've just generated a block of defuns like
the one in the previous section! `M-J' works like this: it tries
to split the current line into \"words\" separated by whitespace,
but producing a maximum of two \"words\" (the 2nd, 3rd, etc
\"words\" as treated as a single \"word\"); if the second word is
empty, then `M-J' produces a definition for an `eejump-nnn*'; if
it is not empty, then `M-J' produces a definition for an
`eejump-nnn', treating the second \"word\" as a sexp.
Note that `M-J' is quite dumb - it doesn't check if the first
\"word\" is a number, nor if the second is a sexp. Use it with
care! Try using `M-J' on the \"a b ...\" lines below - you will
get useless definitons.
a b c d
a b c
a b
a
Permanent and temporary
=======================
If you create a block like the block of six defuns above in your
.emacs file then you'll be attributing a \"permanent\" meaning to
`M-91j', ..., `M-992j', and if you create it in a file that is
not evaluated in every Emacs session (and execute it, of course),
then you'll be attributing just a \"temporary\" meaning to
`M-91j', ..., `M-992j'.
# Local Variables:
# coding: raw-text-unix
# ee-anchor-format: \"%s\"
# End:
" rest)))
;; (find-eejump-intro)
;;; _ __ _ _ _
;;; _ __ __| |/ _| | (_) | _____
;;; | '_ \ / _` | |_ _____| | | |/ / _ \
;;; | |_) | (_| | _|_____| | | < __/
;;; | .__/ \__,_|_| |_|_|_|\_\___|
;;; |_|
;;
;; «find-pdf-like-intro» (to ".find-pdf-like-intro")
(defun find-pdf-like-intro (&rest rest) (interactive)
(let ((ee-buffer-name "*(find-pdf-like-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-pdf-like-intro)
Source code: (find-eev \"eev-intro.el\" \"find-pdf-like-intro\")
More intros: (find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
PDF-like documents
==================
Let's introduce a bit of (improvised!) terminology: we will say
that a document is \"PDF-like\" when it is in a format like PDF,
PostScript, DVI or DJVU - i.e., divided into pages. Emacs has a
standard mode for viewing PDF-like documents,
(find-enode \"Document View\")
but we will see a more eev-like way of pointing to pages of
PDF-like documents.
Two test documents
==================
The following script creates two PDF-like documents - a DVI and a
PDF - that we will use in the examples below.
(eepitch-shell)
(eepitch-kill)
(eepitch-shell)
cd /tmp/
cat > /tmp/foo.tex <<'%%%'
\\documentclass[12pt,oneside]{book}
\\begin{document}
\\Huge
\\frontmatter
a \\newpage
b \\newpage
c \\newpage
\\mainmatter
\\chapter{One}
\\newpage foo
\\chapter{Two}
\\end{document}
%%%
latex foo.tex
pdflatex foo.tex
In these two documents the page _names_ do not correspond to the
page _numbers_; the pages are named \"i\", \"ii\", \"iii\",
\"1\", \"2\", \"3\", but their numbers are 1, 2, 3, 4, 5, 6.
In a table:
number name contents
----------------------
1 i a
2 ii b
3 iii c
4 1 Chapter 1 - One
5 2 foo
6 3 Chapter 3 - Two
Using external viewers
======================
The following sexps can be used to open the documents
\"/tmp/foo.dvi\" and \"/tmp/foo.pdf\" on the first page of
Chapter 1 - i.e., the page whose number is 4, and whose \"name\"
is 1 - using two of my favorite viewers, xdvi and xpdf, and a
low-level function, `find-bgprocess':
(find-bgprocess '(\"xdvi\" \"+4\" \"/tmp/foo.dvi\"))
(find-bgprocess '(\"xpdf\" \"/tmp/foo.pdf\" \"4\"))
Alternatively, we can invoke these viewers like this,
(find-xdvi-page \"/tmp/foo.dvi\" 4)
(find-xpdf-page \"/tmp/foo.pdf\" 4)
or, as they ignore extra arguments, like this,
(find-xdvi-page \"/tmp/foo.dvi\" (+ 3 1) \"Chapter 1\")
(find-xpdf-page \"/tmp/foo.pdf\" (+ 3 1) \"Chapter 1\")
where the `(+ 3 1)' and the \"Chapter 1\" are just to make these
links more readable by humans. The `3' is what we will call the
\"offset\" of the document: a quantity that can be added to page
\"names\" (outside the \"front matter\" of the document) to
convert them to page \"numbers\".
Let's introduce more terminology. Programs like xdvi and xpdf are
\"external viewers for PDF-like documents\", but that's too long,
so let's shorten this to \"external PDF-like viewers\", or
\"external viewers\", or just \"viewers\"; `find-xdvi-page',
`find-xpdf-page' and similar functions are \"medium-level viewing
words\".
The high-level way
==================
File names of PDF-like documents are often very long - especially
for documents that we have \"psne\"-ed from the web. To avoid
having to keep copies of these file names everywhere we can use
`code-c-d'-like words - like these:
(code-xdvi \"fd\" \"/tmp/foo.dvi\")
(code-xpdf \"fp\" \"/tmp/foo.pdf\")
(find-fdpage (+ 3 1) \"Chapter 1\")
(find-fppage (+ 3 1) \"Chapter 1\")
Each medium-level viewing word has an associated code-c-d-like
word - that creates \"high-level viewing words\". In the example
above, we used `code-xdvi' to create the high-level viewing word
`find-fdpage', that invokes `find-xdvi-page', and `code-xpdf' to
create the high-level viewing word `find-fppage', which invokes
`find-xpdf-page',
Note that the \"fd\" in `find-fdpage' stands for not only the
filename - \"/tmp/foo.dvi\" - but also for the medium-level word
to be used - `find-xdvi-page'; same for \"fp\".
Default external viewers
========================
We saw that for each of the supported formats of PDF-like
documents - DVI, PostScript, PDF, DJVU - there are medium-level
and high-level viewing words that use specific programs; for
example, for \"xpdf\" we have `find-xpdf-page' and `code-xpdf',
and for \"evince\" we have `find-evince-page' and `code-evince'.
But for each of the formats we also have words that use the
current default viewer for that format:
Format Medium-level High-level
----------------------------------------
DVI find-dvi-page code-dvi
PostScript find-ps-page code-ps
PDF find-pdf-page code-pdf
DJVU find-djvu-page code-djvu
The four `find--page' words above are aliases to
`find--page' names, and to change a default viewer
you should use a `defalias' on the `find-', like these:
(defalias 'find-pdf-page 'find-evince-page)
(defalias 'find-pdf-page 'find-xdpf-page)
After running a `defalias' like the above all the high-level
viewing words defined using `code-pdf' will automatically switch
to the new default viewer (because words defined with `code-pdf'
call `find-pdf-page').
PDF-like documents as text
==========================
Some PDF-like documents can be converted to text - usually uglily
and imprecisely, but the result is often useful anyway - by
external programs like \"pdftotext\" and \"djvutxt\". The
medium-level sexps below invoke these programs on the given
filenames and displays their output in an Emacs buffer:
(find-pdftotext-text \"/tmp/foo.pdf\")
(find-djvutxt-text \"/tmp/foo.djvu\")
We can also use the correspondent generic medium-level words,
that are aliases to the default converters:
(find-pdf-text \"/tmp/foo.pdf\")
(find-djvu-text \"/tmp/foo.djvu\")
As the output of these converters is also divided into pages -
with formfeeds as separators - it is easy to jump to specific
pages in the output, and if the first argument after the file
name is a number it is interpreted as a page number; string
arguments coming after that are interpreted as strings to be
search (forward) for. So these links make sense:
(find-pdf-text \"/tmp/foo.pdf\" (+ 3 1))
(find-pdf-text \"/tmp/foo.pdf\" (+ 3 1) \"Chapter 1\")
and note that the following pair of links make sense too - the
first one calls an external viewer, the second one opens the
conversion to text:
(find-pdf-page \"/tmp/foo.pdf\" (+ 3 1) \"Chapter 1\")
(find-pdf-text \"/tmp/foo.pdf\" (+ 3 1) \"Chapter 1\")
Note that they both point to the same page... The argument
\"Chapter 1\" is ignored in the first link, but when a pair of
links like that appear on consecutive lines it is clear for human
readers that they are both links to the same place, only rendered
in different ways. Note that the passage from this:
(find-pdf-text \"/tmp/foo.pdf\" (+ 3 1))
to this:
(find-pdf-text \"/tmp/foo.pdf\" (+ 3 1))
(find-pdf-text \"/tmp/foo.pdf\" (+ 3 1) \"Chapter 1\")
is a special case of \"refining hyperlinks\", an idea that we saw
in:
(find-eval-intro \"Refining hyperlinks\")
High-level hyperlinks to pdf-like documents
===========================================
By executing
(code-pdf \"fp\" \"/tmp/foo.pdf\")
(code-pdf-text \"fp\" \"/tmp/foo.pdf\" 3)
we can use shorter hyperlinks, like
(find-fppage (+ 3 1) \"Chapter 1\")
(find-fptext (+ 3 1) \"Chapter 1\")
instead of the longer forms with `find-pdf-page' and
`find-pdf-text'. This works exactly like `code-c-d', as explained
here:
(find-code-c-d-intro)
Try these sexps to see the code that the `code-pdf' and the
`code-pdf-text' above execute:
(find-code-pdf \"fp\" \"/tmp/foo.pdf\")
(find-code-pdf-text \"fp\" \"/tmp/foo.pdf\" 3)
There is a wrapping comand for producing these
`code-pdf'/`code-pdf-text' pairs quickly - `M-P'. Try it here:
fp /tmp/foo.pdf
Producing and refining hyperlinks to pages
==========================================
We also have something like this
(find-eval-intro \"Producing and refining hyperlinks\")
for pdf-like documents, that will let us produce hyperlinks to
the current page of the current pdf-like document very quickly,
but it depends on several hacks.
Note that the functions `code-pdf', `code-pdf-text',
`find-xxxpage', `find-xxxtext', set the global variables
`ee-page-c', `ee-page-fname', and `ee-page-offset'. You can
inspect their definitions with:
(find-code-pdf \"fp\" \"/tmp/foo.pdf\")
(find-code-pdf-text \"fp\" \"/tmp/foo.pdf\" 3)
Here's how these variables are used. Try this:
(code-pdf \"fp\" \"/tmp/foo.pdf\")
(code-pdf-text \"fp\" \"/tmp/foo.pdf\" 3)
(kill-new \"Two\")
(eek \"M-h M-p\")
You should get a page with several hyperlinks to the \"current
page\" of the current pdf-like document, including some like
these:
(find-fppage 1)
(find-fptext 1)
(find-fppage (+ 3 -2))
(find-fptext (+ 3 -2))
(find-fppage 1 \"Two\")
(find-fptext 1 \"Two\")
(find-fppage (+ 3 -2) \"Two\")
(find-fptext (+ 3 -2) \"Two\")
Where did the \"fp\", the \"1\", the \"3\", the \"-2\" and the
\"Two\" above come from?
The page number, which in the links above is sometimes \"1\",
sometimes \"(+ 3 -2)\", is obtained by counting the number of
formfeeds before point; this makes sense only when we are
visiting the buffer generated by \"(find-fptext ...)\". The
\"fp\" is taken from the variable `ee-page-c', which was set by
`(code-pdf-text \"fp\" ...)' or by `(find-fptext ...)'; same for \"3\",
which is taken from the variable `ee-page-offset'. Finally, the \"Two\"
is the last kill, from the top of the kill-ring; we usually set it by
selecting a region of text from the `(find-fptext ...)' buffer and
typing `M-w'.
An alternative way to produce hyperlinks to pages, which, as the hack
above, also uses `ee-page-c' and `ee-page-offset', is to prepare a
series of lines with a page number followed by a text that will play a
similar role to the \"last kill\", and then type `M-Q' on each line. Try
this below, by first executing the `code-pdf-text' then typing four
`M-Q's.
(code-pdf \"debt\" \"~/books/graeber__debt.pdf\")
(code-pdf-text \"debt\" \"~/books/graeber__debt.pdf\" 8)
1 1 On The Experience of Moral Confusion
21 2 The Myth of Barter
43 3 Primordial Debts
73 4 Cruelty and Redemption
It is usually not hard to produce such page-number-plus-text
lines for `M-Q' from the table of contents of a book. The ones
above were extracted from
(find-debttext 7 \"Contents\")
with a bit of fiddling by hand and keyboard macros. Keyboard
macros are VERY useful; if you don't use them yet, see:
(find-enode \"Keyboard Macros\")
" rest)))
;; (find-pdf-like-intro)
;;; _ _ __ _ _
;;; __ _ _ _ __| (_) ___ / /_ _(_) __| | ___ ___
;;; / _` | | | |/ _` | |/ _ \ / /\ \ / / |/ _` |/ _ \/ _ \
;;; | (_| | |_| | (_| | | (_) / / \ V /| | (_| | __/ (_) |
;;; \__,_|\__,_|\__,_|_|\___/_/ \_/ |_|\__,_|\___|\___/
;;;
;; «find-audiovideo-intro» (to ".find-audiovideo-intro")
;; (find-intro-links "audiovideo")
(defun find-audiovideo-intro (&rest pos-spec-list) (interactive)
(let ((ee-buffer-name "*(find-audiovideo-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-audiovideo-intro)
Source code: (find-eev \"eev-intro.el\" \"find-audiovideo-intro\")
More intros: (find-eev-intro)
(find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
Time offsets
============
Links to audio and video files are similar to links to pdf-like
documents, but instead of page numbers we use \"time offsets\" to
refer to positions. Time offsets are strings like 1:23, 12:34, or
1:23:45. The sexp hyperlinks below should all work if you have the
files that they refer to:
(find-audio \"/tmp/mysong.mp3\")
(find-audio \"/tmp/mysong.mp3\" \"1:23\")
(find-audio \"/tmp/mysong.mp3\" \"1:23\" \"comment are ignored\")
(find-video \"/tmp/myvideo.mp4\")
(find-video \"/tmp/myvideo.mp4\" \"1:23\")
(find-video \"/tmp/myvideo.mp4\" \"1:23\" \"comment are ignored\")
Note that they work by invoking an external player - mplayer, by
default - and its error messages appear here:
(find-ebuffer \"*Messages*\")
Shorter hyperlinks to audio and video files
===========================================
If you type `M-V' (`eewrap-audiovideo') on a line containing a
shorthand word and a file name of an audio or video file, for
example, here,
sunwillset ~/Zoe_Keating/Sun_Will_Set.ogg
you will get something like this:
;; (find-fline \"~/Zoe_Keating/\")
(code-audio \"sunwillset\" \"~/Zoe_Keating/Sun_Will_Set.ogg\")
(code-video \"sunwillset\" \"~/Zoe_Keating/Sun_Will_Set.ogg\")
;; (find-sunwillset)
;; (find-sunwillset \"0:00\")
you should delete the line with the wrong sexp by hand - in this
case the wrong one is the one with `code-video', as we are
working with a sound file - and execute the other one; this will
define a function called `find-sunwillset', that plays the audio
file with `find-audio'. Run this this sexp to inspect its code:
(find-code-audio \"sunwillset\" \"/tmp/Zoe_Keating__Sun_Will_Set.ogg\")
you will notice that running `find-sunwillset' sets a variable,
with:
(setq ee-audiovideo-last 'find-sunwillset)
As we shall see soon, some operations play again the default
audio or video file, starting from some given time offset. The
default is always what is stored in `ee-audiovideo-last', and
each call to a short hyperlink of the form `find-xxxaudio' or
`find-xxxvideo' sets that variable.
Passing options to mplayer
==========================
By default mplayer is called with just a few command-line options,
besides the ones that tell it at what position to start playing -
typically just these for videos,
-fs -osdlevel 2
to make it run in full-screen mode with an on-screen display
showing the current position, and no options for audio.
If you want to change this you should redefine these functions:
(ee-mplayer-video-options)
(ee-mplayer-audio-options)
`eev-avadj-mode'
================
\"avadj-mode\" is a shorthand for \"audio/video adjust mode\".
When `eev-avadj-mode' is active we get keys for adjusting time
offsets quickly and for playing again the default audio or video
file at a given time offset, all of this without moving the
point. The keys are:
M-- decrease the time offset by one second
M-+ increase the time offset by one second
M-= same as M-+, for convenience
M-p play the default audio/video file at a time offset
You can toggle eev-avadj-mode on and off with `M-x
eev-avadj-mode', or with this sexp:
(eev-avadj-mode)
When it is on you will see an \"avadj\" at the mode line. Let's
examine `M--' and `M-+' first. With eev-avadj-mode on, try typing
several `M--'s and `M-+'s (or `M-='s) on the line below:
This time offset - 9:59 - will change
Now, as an exercise, try to use `M--'s and `M-+'s/`M-='s, plus
`M-h M-2' (`ee-duplicate-this-line') and other more standard
editing commands, to convert this line
(find-exampleaudio \"0:00\")
into:
(find-exampleaudio \"0:00\")
(find-exampleaudio \"0:12\" \"blah\")
(find-exampleaudio \"0:30\" \"bleh\")
That should give you an idea of how to index audio or video files
- by creating elisp hyperlinks, with comments, to specific
positions in them. Of course in a real-world situation we would
execute these sexps occasionally to check if they are really
pointing to the right places, and then make further adjustments;
we are not doing that yet.
The time-from-bol
=================
All the keys in eev-avadj-mode operate on the \"time-from-bol\"
of the current line: the first occurrence, in the current line,
of a string that looks like a time offset. Note that the search
starts from the beginning of the line (\"-from-bol\"), and if
there are several possibilities, the first one is chosen.
Remember that `M-e' has a variant that just highlights what would
be executed, instead of evaluating a sexp:
(find-eval-intro \"`M-0 M-e'\")
`M-p' also has something like this: `M-0 M-p' highlights the
time-from-bol and displays in the echo area the sexp that it
would execute to invoke a player - instead of running that sexp.
Try to evaluate these sexps:
(code-audio \"sunwillset\" \"~/Zoe_Keating/Sun_Will_Set.ogg\")
(find-sunwillset)
;; ^ don't worry if this fails - we are only calling it
;; to set `ee-audiovideo-last'
and now try `M-0 M-p' on these lines:
;; 4:19 blah
;; 2:19
For more realistic examples, see:
(find-videos-intro)
Youtube-dl
==========
Videos at Youtube are identified by unique 11-char codes that are
assigned to them when they are uploaded. We will call those 11-char
codes \"hashes\", even though the term is not totally adequade in this
case, and we will explain the main ideas considering the case of an
imaginary video whose title is just TITLE, and whose hash is
\"abcdefghijk\". The URL to access that video at Youtube would be this:
http://www.youtube.com/watch?v=abcdefghijk
\\---------/
its hash
If we execute this on a shell,
cd /tmp/
youtube-dl -t 'http://www.youtube.com/watch?v=abcdefghijk'
then youtube-dl would download a local copy of the video; due to the
option \"-t\" (\"--title\"), the name of the local copy would have both
the title of the video and its hash, and, if the video is in MP4
format, that would be
/tmp/TITLE-abcdefghijk.mp4.part
during the download, and would be renamed to
/tmp/TITLE-abcdefghijk.mp4
as soon as the download is finished.
Downloading a local copy
========================
Place the point at hash in the URL below,
http://www.youtube.com/watch?v=abcdefghijk
and run `M-x find-youtubedl-links'; `find-youtubedl-links' will use
the hash at point as a default for one of its arguments, will run
something equivalent to this sexp,
(find-youtubedl-links nil nil \"abcdefghijk\")
and will create a buffer like this:
___________________________________________________________________________
|# (find-youtubedl-links \"/tmp/\" \"{title}\" \"abcdefghijk\" \"{ext-}\" \"{stem}\") |
|# (find-youtubedl-links \"/tmp/\" nil \"abcdefghijk\" nil \"{stem}\") |
| |
|# (find-youtubedl-links \"~/videos/\" nil \"abcdefghijk\" nil \"{stem}\") |
|# (find-youtubedl-links \"~/videos/tech/\" nil \"abcdefghijk\" nil \"{stem}\") |
|# (find-youtubedl-links \"/tmp/videos/\" nil \"abcdefghijk\" nil \"{stem}\") |
|# (find-youtubedl-links \"/tmp/\" nil \"abcdefghijk\" nil \"{stem}\") |
|# (find-efunction 'find-youtubedl-links) |
| |
| (eepitch-shell2) |
| (eepitch-kill) |
| (eepitch-shell2) |
|# http://www.youtube.com/watch?v=abcdefghijk |
|# http://www.youtube.com/watch?v=abcdefghijk#t=0m00s |
|# http://www.youtube.com/watch?v=abcdefghijk#t=0h00m00s |
|cd /tmp/ |
|youtube-dl -t 'http://www.youtube.com/watch?v=abcdefghijk' |
| |
|# youtube-dl -t -F 'http://www.youtube.com/watch?v=abcdefghijk' |
|# youtube-dl -t -f 18 'http://www.youtube.com/watch?v=abcdefghijk' |
| |
|# (find-es \"video\" \"youtube-dl\") |
|# (find-fline \"/tmp/\" \"abcdefghijk\") |
|# (find-fline \"/tmp/\" \"{title}-abcdefghijk\") |
|# (find-fline \"/tmp/\" \"{title}-abcdefghijk{ext-}\") |
|# (find-video \"/tmp/{title}-abcdefghijk{ext-}\") |
|# (find-video \"/tmp/{title}-abcdefghijk{ext-}.part\") |
|# (code-video \"{stem}video\" \"/tmp/{title}-abcdefghijk{ext-}\") |
|# (code-video \"{stem}video\" \"/tmp/{title}-abcdefghijk{ext-}.part\") |
|# (find-{stem}video) |
|# (find-{stem}video \"0:00\") |
| |
|# Error messages (for the player): |
|# (find-ebuffer \"*Messages*\") |
| |
| |
|--:**- *Elisp hyperlinks* All L1 (Fundamental)----------------------|
|___________________________________________________________________________|
which has LOTS of things... the part
(eepitch-shell2)
(eepitch-kill)
(eepitch-shell2)
cd /tmp/
youtube-dl -t 'http://www.youtube.com/watch?v=abcdefghijk'
is obvious: it is an eepitch script that downloads a local copy
of the video from Youtube.
Guessing the title and extension
================================
Let's simulate what would happen after the eepitch script above -
Execute this:
(find-sh0 \"rm -v /tmp/TITLE-abcdefghijk*\")
(find-sh0 \"echo > /tmp/TITLE-abcdefghijk.mp4.part\")
Now use `M-2 M-e' to compare the buffers generated by two calls
to `find-youtubedl-links' below:
(find-youtubedl-links nil nil \"abcdefghijk\")
(find-youtubedl-links \"/tmp/\" nil \"abcdefghijk\")
In the second one we get a buffer where all occurrences
of \"{title}\" have been substituted by \"TITLE\", and all
occurrences of \"{ext-}\" by \".mp4\". What happenned was that
(ee-youtubedl-guess* \"/tmp/\" \"abcdefghijk\")
--> (\"/tmp/TITLE-abcdefghijk.mp4.part\")
did find files what that hash string in their names in the
directory \"/tmp/\", and the function `ee-youtubedl-split' has
picked up the first of these file names and has split it into
components:
(ee-youtubedl-split \"/tmp/TITLE-abcdefghijk.mp4.part\")
--> (\"/tmp/\" \"TITLE\" \"abcdefghijk\" \".mp4\" \".mp4.part\")
The last of these components is what we will call the \"ext\" -
the \"full extension\" - and the previous one is the \"ext-\" -
the \"extension minus its optional `.part'\". The first three
components are the \"dir\", the \"title\", and the \"hash\".
The first lines regenerate the buffer
=====================================
The arguments to `find-youtubedl-links' are:
(find-youtubedl-links DIR TITLE HASH EXT- STEM)
and we just saw how `ee-youtubedl-guess*' and
`ee-youtubedl-split' can be used to guess TITLE, EXT and EXT-
from DIR and HASH.
All the arguments to `find-youtubedl-links' have defaults,
that are used when the received arguments are nil:
* when HASH is nil, use the youtube hash around point,
or \"{hash}\" if none;
* when DIR is nil, use the value of `ee-youtubedl-dir',
or \"{dir}\" if none;
* when TITLE or EXT- are nil use the guessing method described
above, and when they fail use \"{title}\" or \"{ext-}\";
* when STEM is nil, use \"{stem}\".
The first two lines in a `find-youtubedl-links' regenerate the
buffer, and are usually equivalent to one another. In the buffer
generated by:
(find-youtubedl-links \"/tmp/\" nil \"abcdefghijk\")
they are:
(find-youtubedl-links \"/tmp/\" \"TITLE\" \"abcdefghijk\" \".mp4\" \"{stem}\")
(find-youtubedl-links \"/tmp/\" nil \"abcdefghijk\" nil \"{stem}\")
The first one has only non-nil arguments - all the rules for
guesses and defaults have been applied - where in the second one
TITLE and EXT- are made nil.
Selecting a directory
=====================
The second block of lines in the `find-youtubedl-links' buffer
are used to let we switch the directory quickly. If we just
execute `M-x find-youtubedl-links' with the point on our example
hash, or, equivalently, if we do this,
(find-youtubedl-links nil nil \"abcdefghijk\")
you will see that the first two lines will be:
(find-youtubedl-links \"~/videos/\" \"{title}\" \"abcdefghijk\" \"{ext-}\" \"{stem}\")
(find-youtubedl-links \"~/videos/\" nil \"abcdefghijk\" nil \"{stem}\")
which means that the guessing process didn't find a downloaded
copy, as TITLE is \"{title}\" and EXT- is \"{ext-}\". That's because
we are using \"~/videos/\" as the DIR, and our file
/tmp/TITLE-abcdefghijk.mp4.part
is elsewhere, and the guessing functions only search in one
directory...
The second block contains these sexps,
(find-youtubedl-links \"~/videos/\" nil \"abcdefghijk\" nil \"{stem}\")
(find-youtubedl-links \"~/videos/tech/\" nil \"abcdefghijk\" nil \"{stem}\")
(find-youtubedl-links \"/tmp/videos/\" nil \"abcdefghijk\" nil \"{stem}\")
(find-youtubedl-links \"/tmp/\" nil \"abcdefghijk\" nil \"{stem}\")
and if we execute the last one we set DIR to \"/tmp/\".
To change the dir strings \"~/videos/\", \"~/videos/tech/\", \"/tmp/videos/\",
\"/tmp/\", that appear in the second block of `find-youtubedl-links'
buffers, change the variables `ee-youtubedl-dir', `ee-youtubedl-dir2',
`ee-youtubedl-dir3', `ee-youtubedl-dir4.'
How to download
===============
Test the download
=================
Create short links
==================
(find-youtubedl-links \"/tmp/\" \"TITLE\" \"abcdefghijk\" \".mp4\" \"{stem}\")
(find-youtubedl-links nil nil \"abcdefghijk\")
(find-eev \"eev-audiovideo.el\")
(find-eev \"eev-audiovideo.el\" \"eev-avadj-mode\")
" pos-spec-list)))
;; (find-audiovideo-intro)
;;; _ _ _ _ _
;;; _ __ ___ _ _| | |_(_)_ _(_)_ __ __| | _____ __
;;; | '_ ` _ \| | | | | __| \ \ /\ / / | '_ \ / _` |/ _ \ \ /\ / /
;;; | | | | | | |_| | | |_| |\ V V /| | | | | (_| | (_) \ V V /
;;; |_| |_| |_|\__,_|_|\__|_| \_/\_/ |_|_| |_|\__,_|\___/ \_/\_/
;;;
;; «find-multiwindow-intro» (to ".find-multiwindow-intro")
;; (find-intro-links "multiwindow")
(defun find-multiwindow-intro (&rest pos-spec-list) (interactive)
(let ((ee-buffer-name "*(find-multiwindow-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-multiwindow-intro)
Source code: (find-efunction 'find-multiwindow-intro)
More intros: (find-eev-intro)
(find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
Introduction
============
In many situations - for example, when we want to script a
debugger, or to test programs that have to talk to one another,
or to control several external machines simultaneously - the
default window setup for eepitch, which is this,
____________________
| | |
| | |
| script | shell |
| | |
| | |
|__________|_________|
is not enough; other setups, like these,
______________________
| | | _________________________
| | shell A | | | |
| |___________| | script | GDB |
| script | | | | |
| | shell B | |____________|____________|
| |___________| | | |
| | | | program | program |
| | shell C | | I/O | source |
|__________|___________| |____________|____________|
may be necessary. Eev comes with a few _low-level_ tools for
creating these setups; they are not very smart, but they should
be easy to understand and to tweak - and I have the impression
that ideas for good high-level tools will only come from
practical experimentation.
`find-wset'
===========
Suppose that we are in a buffer A, and we want to create a window
configuration with A at the left, and with the buffers B and C
stacked on one another at the right. That is:
___________ ___________
| | | | |
| | | | B |
| A | --> | A |_____|
| | | | |
| | | | C |
|___________| |_____|_____|
To do that from the keyboard we could type this:
C-x 3 C-x o C-x b B RET C-x 2 C-x o C-x b C RET
You can try that here (the initial `C-x 1' is an extra, for
convenience):
(eek \"C-x 1 ;; delete-other-windows
C-x 3 ;; split-window-horizontally (left/right)
C-x o ;; other-window (-> right)
C-x b B RET ;; switch to the buffer `B'
C-x 2 ;; split-window-vertically (upper/lower)
C-x o ;; other-window (-> lower right)
C-x b C RET ;; switch to the buffer `C'
\")
We can write something equivalent to that as a `progn', in a way
that makes it easy to replace later the `C-x b B RET' and the
`C-x b C RET' by arbitrary sexp hyperlinks. We get:
(progn (eek \"C-x 1 C-x 3 C-x o\")
(find-ebuffer \"B\")
(eek \"C-x 2 C-x o\")
(find-ebuffer \"C\")
(eek \"C-x o\")
)
When I started to rewrite my window configurations into that form
I realized that the `eek's were being used in a very limited way
- they only invoked a very small repertoire of window commands,
all of them starting with `C-x'. So maybe I should have an
interpreter for a simple language of window commands and sexp
hyperlinks, in the which window setup above could be expressed
like this:
`(\"13o\"
(find-ebuffer \"B\")
\"2o\"
(find-ebuffer \"C\")
\"o\"
)
`find-wset' supports something like that, but with all the window
command strings collapsed into a single one, with \"_\"s meaning
\"execute the next sexp from the sexp list\". The corresponding
call to `find-wset' is:
(find-wset \"13o_2o_o\" '(find-ebuffer \"B\") '(find-ebuffer \"C\"))
For the full list of supported window command characters - and
how to extend it - see the source:
(find-eev \"eev-multiwindow.el\")
High-level words
================
Very often we want to create window setups like
_______________ _______________
| | | | | |
| | | | | B |
| A | B | or | A |_______| ;
| | | | | |
| | | | | C |
|_______|_______| |_______|_______|
there are shorthands for that. If you run
(find-2a sexpA sexpB)
that will create a window setting like the one at the left above,
initially with two copies of the current buffer, then will run
sexpA at the window \"A\" and sexpB at the window \"B\", and
finally will select the window \"A\", i.e., leave the cursor at
the window at the left; this
(find-2b sexpA sexpB)
will do exactly the same as the `(find-2a ...)' above, but will
select the window \"B\" - the one at the right - at the end of
the process. For three-window settings we have these:
(find-3a sexpA sexpB sexpC)
(find-3b sexpA sexpB sexpC)
(find-3c sexpA sexpB sexpC)
all three create the three-window setting at the right above,
initially with all three windows displaying the current buffer,
then run sexpA at the window \"A\", sexpB at the window \"B\",
and sexpC at the window \"C\"; the difference is that find-3a
selects the window \"A\", find-3b the window \"B\", find-3c the
window \"C\".
Several eepitch targets
=======================
If we try to build a window setup like this one, with two eepitch
targets, with just `find-wset', we will run into problems -
________________________
| | |
| | *shell* |
| script |_____________|
| | |
| | *shell 2* |
|__________|_____________|
because `(eepitch-shell)' and `(eepitch-shell2)' try to create a
shell buffer and put it in an _another_ window, not the one we
are in... one solution is to call the `(eepitch-*)' sexps inside
an `ee-here', like this:
(ee-here '(eepitch-shell))
(ee-here '(eepitch-shell2))
where `ee-here' is a hack that runs a sexp in a way that
preserves the current window configuration, then switches the
buffer in the current selected window to the current eepitch
target. We can use this to create the window setting above,
(find-wset \"13o2_o_o\"
' (ee-here '(eepitch-shell))
' (ee-here '(eepitch-shell2))
)
This is too long - and would make a very bad one-liner - but
there are two shorthands. First, \"e\" is a variant of \"_\" that
runs its sexp inside an `(ee-here ...) - so this is equivalent
the thing above,
(find-wset \"13o2eoeo\"
'(eepitch-shell)
'(eepitch-shell2)
)
Second, these things are useful enough to deserve a high-level
word, so this is equivalent to:
(find-3ee '(eepitch-shell) '(eepitch-shell2))
Restarting eepitch targets
==========================
Sometimes we want to do the same as above, but restarting both
eepitch targets, i.e., something like this:
(find-3ee '(progn (eepitch-shell) (eepitch-kill) (eepitch-shell))
'(progn (eepitch-shell2) (eepitch-kill) (eepitch-shell2))
)
There's a variant of `ee-here' that does that: `ee-here-reset'.
For example,
(ee-here-reset '(eepitch-shell2))
is equivalent to:
(ee-here '(progn (eepitch-shell2) (eepitch-kill) (eepitch-shell2)))
and the letter \"E\" is a variant of \"e\" that uses
`ee-here-reset' instead of `ee-here'; also, `find-3EE' is a
variant of `find-3ee' that restarts both targets. Let's adapt
this example,
(find-eepitch-intro \"Other targets\")
to make it show the two eepitch targets at once in a three-window
settings. It becomes:
(find-3EE '(eepitch-shell) '(eepitch-python))
(eepitch-shell)
echo Hello... > /tmp/o
(eepitch-python)
print(open(\"/tmp/o\").read())
(eepitch-shell)
echo ...and bye >> /tmp/o
(eepitch-python)
print(open(\"/tmp/o\").read())
Now compare:
(eek \"C-x 1\")
(find-3ee '(eepitch-shell) '(eepitch-python))
(find-3EE '(eepitch-shell) '(eepitch-python))
Non-trivial examples
====================
See:
(find-prepared-intro \"An `ee' for Python\")
(find-rcirc-intro \"The server buffer and the channel buffers\")
Eepitch blocks for two targets
==============================
An eepitch script with two targets uses several different kinds
of red star lines - `(eepitch-target1)', `(eepitch-target2)',
`(find-3EE ...)', `(find-3ee ...)', etc. We don't want to have to
type all those by hand, so there is a hack similar to `M-T' that
generates all those kinds from just \"target1\" and \"target2\"
to let us just copy around the sexps we need. It is bound to
`meta-shift-3', which Emacs sees as `M-#'. Compare the result of
typing `M-T' here,
python
with the result of typing `M-#' on this line,
shell python
which yield this:
(find-3EE '(eepitch-shell) '(eepitch-python))
(find-3ee '(eepitch-shell) '(eepitch-python))
(eepitch-shell)
(eepitch-python)
Note that we use to `find-3EE' to restart targets instead of
`eepitch-kill' (this is non-trivial - think about it =/)...
Adding support for new characters in `find-wset'
================================================
The standard characters supported by `find-wset' are these:
char action key
---- ---------------------------- ---------
`1' `delete-other-windows' (C-x C-1)
`2' `split-window-vertically' (C-x C-2)
`3' `split-window-horizontally' (C-x C-3)
`s' `split-window-sensibly'
`o' `other-window' (C-x o)
`+' `balance-windows' (C-x +)
`_' execute the next sexp
but the action of each one is defined in a different function,
and to add support for a new character, say, `=', we just need to
define a function with the right name - in this case,
`find-wset-='.
The source code is simple enough, so take a look:
(find-eev \"eev-multiwindow.el\" \"find-wset-_\")
(find-eev \"eev-multiwindow.el\" \"find-wset-=\")
(find-eev \"eev-multiwindow.el\" \"find-wset-!\")
Note that `find-wset-!' restarts an eepitch target, while
`find-wset-=' will reuse an eepitch target if its buffer already
exists. [Obs: \"=\" and \"!\" have been mostly superseded by
\"e\" and \"E\"... to do: explain this]
See: (find-prepared-intro)
[Example at find-prepared-intro]
Executing key sequences at other windows
========================================
It is possible to use multi-window settings, together with the
trick that `' on a red star line executes it as Lisp and
moves down, to create tutorials for Emacs modes. An example:
A tutorial for Info mode
========================
Here's a mini-tutorial for Info mode, demonstrating how to
navigate in Info using the usual movement keys, plus TAB,
, RET, l (last), u (up), n (next), p (prev), q (quit),
C-h i, and the digits 1-9. Note that the display in Info mode is
like this:
____________________________________________
|Next: Nonincremental Search, Up: Search | <- next/prev/up
| (emacs)Top > Search > Incremental Search | <- breadcrumbs
| |
| 19.1 Incremental Search | <- section number /
| | node name (long)
| (...) |
| |
|--:%%- *info* (emacs) Incremental Search |
|____________________________________________|
Here:
Define some hacks
(defun ow (n) (other-window n))
(defun eeoe (code) (ow 1) (prog1 (eval code) (ow -1)))
(defun eeok (keystr) (eeoe `(eek ,keystr)))
Prepare the windows
(ee-kill-buffer \"*info*\")
(find-wset \"1so_o\" '(find-enode \"Search\"))
The arrows (and other movent keys) work as expected.
Watch the cursor in the Info window...
(eeok \"3*\")
(eeok \"10*\")
TAB and move to the next and to the previous link.
Note that they consider all the links in a page, not only
the ones in menus - including the breadcrumb links at the top.
(eeok \"TAB ;; Info-next-reference\")
(eeok \"TAB ;; Info-next-reference\")
(eeok \"TAB ;; Info-next-reference\")
(eeok \"TAB ;; Info-next-reference\")
(eeok \"TAB ;; Info-next-reference\")
(eeok \" ;; Info-prev-reference\")
(eeok \" ;; Info-prev-reference\")
(eeok \" ;; Info-prev-reference\")
(eeok \" ;; Info-prev-reference\")
RET follows a link, l (last) goes back.
Watch the section number: 19 -> 32.3.6 -> 19.
(eeok \"RET ;; Info-follow-nearest-node\")
(eeok \"l ;; Info-history-back\")
The digits 1-9 can be used to go straight to subsections.
For example, a `4' would follow the 4th _menu_ link -
ignoring the non-menu links.
Watch the section number: 19 -> 19.1 -> 19.1.1.
(eeok \"1 ;; Info-nth-menu-item\")
(eeok \"1 ;; Info-nth-menu-item\")
The keys `u', `n', `p' (up, next, and prev) move through the
tree structure. Watch the section number:
19.1.1 -u-> 19.1 -u-> 19 -n-> 20 -n-> 21 -p-> 20 -p-> 19
(eeok \"u ;; Info-up\")
(eeok \"u ;; Info-up\")
(eeok \"n ;; Info-next\")
(eeok \"n ;; Info-next\")
(eeok \"p ;; Info-prev\")
(eeok \"p ;; Info-prev\")
`q' leaves Info mode - more precisely, it buries the info buffer.
`C-h i' goes back to the Info buffer (or restarts info).
(eeok \"q ;; Info-exit\")
(eeok \"C-h i ;; info\")
" pos-spec-list)))
;; (find-multiwindow-intro)
;;; _
;;; _ __ ___(_)_ __ ___
;;; | '__/ __| | '__/ __|
;;; | | | (__| | | | (__
;;; |_| \___|_|_| \___|
;;;
;; «find-rcirc-intro» (to ".find-rcirc-intro")
;; (find-intro-links "rcirc")
(defun find-rcirc-intro (&rest pos-spec-list) (interactive)
(let ((ee-buffer-name "*(find-rcirc-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-rcirc-intro)
Source code: (find-efunction 'find-rcirc-intro)
More intros: (find-eev-intro)
(find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
Recent versions with Emacs come with two IRC clients built-in:
Rcirc and ERC. I never understood ERC well enough, and I found
Rcirc quite easy to understand and to hack, so eev has some
support for Rcirc (and no support for ERC).
The server buffer and the channel buffers
=========================================
If you type `M-6 M-6 M-j' - or `M-e' on the line below - then eev
runs this,
(find-freenode-3a \"#eev\")
which tells Emacs to connect to Freenode and to the channel #eev,
using this window setting:
_________________________
| | |
| | Freenode |
| | server |
| | messages |
| current |_____________|
| buffer | |
| | #eev |
| | channel |
| | |
|___________|_____________|
You will then be able to watch the process of connecting to
Freenode, which takes about 20s on my machine, by the messages
that will appear at the Freenode server buffer; at some point
rcirc will be allowed by the server to connect to channels, it
will request to connect to the channel #eev, and some login
messages, plus at list of all users connected to #eev and a
prompt, will appear at the #eev channel buffer.
`M-66j' is mostly for establishing a connection to an IRC server
and watching if any errors occur; once we know that we are
connected we can use `M-6j' - with just one `M-6' - which just
takes us to the #eev channel without changing the current window
configuration. A mnemonic: `M-66j', which is one keypress longer,
is to be used less often - essentially only once per session, or
when we want to check the status of our connection to Freenode.
Messages and commands
=====================
IRC is a command-line-ish protocol, in which lines starting with
\"/\" are treated as commands and other lines as messages. A
message typed at the #eev channel buffer is broadcast to all
other users also connected to #eev; some commands, like
/join #emacs
work in the same way no matter where they are typed, while
others, like for example \"/part\", work differently when typed
in #eev than when in #emacs. See:
(find-rcircnode \"rcirc commands\" \"/join #emacs\")
(find-rcircnode \"rcirc commands\" \"/part\")
Other channels
==============
where `find-freenode-3a' is based on `find-3a', described here:
(find-multiwindow-intro \"High-level words\")
(find-eev \"eev-rcirc.el\")
If you are new to IRC
=====================
Most of the discussions between Free Software developers still
happen in IRC channels, and mostly at Freenode. The best way to
understand what IRC is - for modern people, I mean - is probably
to try this first:
http://webchat.freenode.net/
IRC is a command-line-ish protocol, in which lines starting with
\"/\" are treated as commands and other lines are messages to be
broadcast. Try to \"/join\" the channels \"#emacs\" and \"#eev\",
with \"/join #emacs\" and \"/join #eev\"; in that webchat, try to
switch between the channels you're connected to by clicking on
the tabs at the top - and note that there is also a tab for a
channel-ish thing that has only messages from the server. Try
also to leave these channels with \"/part\", \"/part #emacs\",
\"/part #eev\".
In Rcirc each one of these channels, including the server
channel, becomes an Emacs buffer. The names of these buffers will
be:
*irc.freenode.net*
#emacs@irc.freenode.net
#eev@irc.freenode.net
(defun eejump-66 () (find-freenode-3a \"#eev\"))
For more information see:
(find-node \"(rcirc)Top\")
(find-node \"(rcirc)Internet Relay Chat\")
(find-node \"(rcirc)rcirc commands\")
http://www.emacswiki.org/emacs/RcIrc
http://www.irchelp.org/
(find-node \"(erc)Top\")
http://www.emacswiki.org/emacs/ErC
" pos-spec-list)))
;; (find-rcirc-intro)
;;; _ _ _
;;; | |_ ___ _ __ ___ _ __ | | __ _| |_ ___ ___
;;; | __/ _ \ '_ ` _ \| '_ \| |/ _` | __/ _ \/ __|
;;; | || __/ | | | | | |_) | | (_| | || __/\__ \
;;; \__\___|_| |_| |_| .__/|_|\__,_|\__\___||___/
;;; |_|
;;
;; «find-templates-intro» (to ".find-templates-intro")
;; (find-intro-links "templates")
(defun find-templates-intro (&rest rest) (interactive)
(let ((ee-buffer-name "*(find-templates-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-templates-intro)
Source code: (find-eev \"eev-intro.el\" \"find-templates-intro\")
More intros: (find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
`ee-template0'
==============
\(find-efunctiondescr 'ee-template0)
\(find-efunction 'ee-template0)
`ee-H', `ee-S', `ee-HS'
=======================
`find-find-links-links'
=======================
\(find-links-intro)
\(find-find-links-links)
\(find-efunction 'ee-stuff-around-point)
interactive
`find-elinks'
=============
\(find-efunction 'find-elinks)
(find-intro-links)
\(find-eev \"eev-tlinks.el\" \"find-intro-links\")
\(find-eevfile \"eev-tlinks.el\")
The innards: templates
======================
Several functions in eev besides `code-c-d' work by replacing
some substrings in \"templates\"; they all involve calls to
either the function `ee-template0', which is simpler, or to
`ee-template', which is much more complex.
The function `ee-template0' receives a single argument - a
string, in which each substring surrounded by `{...}'s is to be
replaced, and replaces each `{...}' by the result of evaluating
the `...' in it. For example:
(ee-template0 \"a{(+ 2 3)}b\")
--> \"a5b\"
Usually the contents of each `{...}' is the name of a variable,
and when the result of evaluating a `{...}' is a string the
replacement does not get `\"\"'s.
The function `ee-template' receives two arguments, a list and a
template string, and the list describes which `{...}' are to be
replaced in the template string, and by what. For example, here,
(let ((a \"AA\")
(b \"BB\"))
(ee-template '(a
b
(c \"CC\"))
\"_{a}_{b}_{c}_{d}_\"))
--> \"_AA_BB_CC_{d}_\"
the \"{d}\" is not replaced. Note that the list (a b (c \"CC\"))
contains some variables - which get replaced by their values -
and a pair, that specifies explicitly that every \"{c}\" should
be replaced by \"CC\".
Templated buffers
=================
Introduction
Conventions:
the first line regenerates the buffer,
buffer names with \"**\"s,
(find-evariable 'ee-buffer-name)
code
`find-elinks'
=============
Variant: `find-elinks-elisp'
`find-e*-links'
===============
\(find-eev \"eev-elinks.el\")
`find-*-intro'
==============
`eewrap-*'
==========
Experiments
===========
\(find-efunction 'find-youtubedl-links)
\(find-efunction 'ee-hyperlinks-prefix)
\(find-efunction 'find-newhost-links)
\(find-efunction 'find-eface-links)
Note that there is no undo.
" rest)))
;; (find-templates-intro)
;; «find-anchors-intro» (to ".find-anchors-intro")
;; (find-intro-links "anchors")
(defun find-anchors-intro (&rest rest) (interactive)
(let ((ee-buffer-name "*(find-anchors-intro)*"))
(apply 'find-estring-lv "\
\(Re)generate: (find-anchors-intro)
Source code: (find-eev \"eev-intro.el\" \"find-anchors-intro\")
More intros: (find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
Introduction: `ee-anchor-format' and `to'
=========================================
A hyperlink like
(to \"foo\")
jumps to the first occurrence of the string \"«foo»\" in the
current buffer. The way to convert from \"foo\" to \"«foo»\" is
controlled by the variable `ee-anchor-format', and the sexp
`(to \"foo\")' is roughly equivalent the third sexp below:
ee-anchor-format
(format ee-anchor-format \"foo\")
(ee-goto-position (format ee-anchor-format \"foo\"))
We will call strings in `«»'s _anchors_, and we will say
that `(to \"foo\")' jumps \"to the anchor `foo'\".
Anchors can be used to create sections and indexes, as we shall
see soon - but due to some old design decisions that I was never
able to find good alternatives for, this tutorial needs to start
with a BIG WARNING.
WARNING: some glyphs need raw-text-unix
=======================================
The best way to make anchors stand out is to use colored glyphs
for them - just like we made `^O's appear as red star glyphs for
eepitch, as described here:
(find-eepitch-intro \"\\nRed stars\\n\")
For historical reasons, the glyphs for `«' and `»' defined in
(find-eev \"eev-anchors.el\")
use the characters 171 and 187; as far as I know, these
characters are only \"safe\" - in the sense that Emacs will not
try to convert them to anything else - in unibyte buffers. The
best way to make sure that anchors with `«»'s will work in a
certain file is to put a \"Local variables:\" section at the end
of it, as has been done in this buffer - and use that to set both
the file coding to raw-text-unix and the value of
`ee-anchor-format' to \"«%s»\".
Note that if you change a \"Local variables:\" section by hand
you will probably have to either reload the file or run `M-x
normal-mode' to make the new settings take effect.
Indexes
=======
In a situation like this,
«one» (to \"two\")
«two» (to \"one\")
we have two anchors, and typing `M-e' at the line with the anchor
\"one\" takes us to the line with the anchor \"two\", and typing
`M-e' at the line with the anchor \"two\" takes us to the line
with the anchor \"one\". In a situation like this we say that the
anchors \"one\" and \"two\" _point to one another_.
In a case like this,
«.three» (to \"three\")
«three» (to \".three\")
where the names of two anchors pointing to one another differ by
an initial dot, we will say that the anchor \".three\" is the
\"index anchor\", and the anchor \"three\" is the \"section
anchor\"; and one way to create an index for a file is to group
all the index anchors together. For an example, see:
(find-eev \"eev-intro.el\" \".find-eev-intro\")
Creating index/section anchor pairs
===================================
Use `M-A' (`eewrap-anchor'). Note that this has been briefly
mentioned here:
(find-wrap-intro \"All wrapping functions\")
It will convert a line with a syntax like
comment-prefix
into:
comment-prefix «.anchor-name» (to \"anchor-name\")
comment-prefix «anchor-name» (to \".anchor-name\")
where comment-prefix is any string and anchor-name is a string
without `<>'s. Note that the `<>'s, which are easy to type, are
converted into `«»'s, which are harder.
find-anchor
===========
\(find-eev \"eev-anchors.el\")
\(find-eev \"eev-anchors.el\" \"find-anchor\")
code-c-d and :anchor
====================
\(find-eev \"eev-code.el\" \"ee-code-c-d-:anchor\")
# Local Variables:
# coding: raw-text-unix
# ee-anchor-format: \"«%s»\"
# End:
" rest)))
;; (find-anchors-intro)
;;; _
;;; _ __ _ __ ___ _ __ __ _ _ __ ___ __| |
;;; | '_ \| '__/ _ \ '_ \ / _` | '__/ _ \/ _` |
;;; | |_) | | | __/ |_) | (_| | | | __/ (_| |
;;; | .__/|_| \___| .__/ \__,_|_| \___|\__,_|
;;; |_| |_|
;;
;; «find-prepared-intro» (to ".find-prepared-intro")
;; (find-eev "eev-bounded.el")
(defun find-prepared-intro (&rest rest) (interactive)
(let ((ee-buffer-name "*(find-prepared-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-prepared-intro)
Source code: (find-eev \"eev-intro.el\" \"find-prepared-intro\")
More intros: (find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
Prepared shells
===============
Long before eepitch had been created, eev had another way -
technically much simpler, but clumsier from the user's point of
view - to send commands to external shells (and other shell-like
programs; but to simplify we will say just \"shells\"). Here is
an overview of how it worked: if the user marked the three lines
below,
rm -Rv /tmp/foo
mkdir /tmp/foo/
cd /tmp/foo/
and typed `M-x eev' (which stood for \"Emacs-execute-verbosely\")
then Emacs would save those three lines into a temporary script
file, usually \"~/.eev/ee.sh\"; that would be just half of
\"sending commands to an external shell\", and for the other half
the user would have to go to an external prepared shell - that
would usually be running in an xterm, and totally independent
from Emacs - and type \"ee\" there. The shell had to be
\"prepared\" in the sense that it would understand the \"ee\"
command correctly, as meaning: \"execute the commands in the
temporary script as if the user were typing them at the prompt\".
Technically, that would mean that instead of calling
\"~/.eev/ee.sh\" as a shell script its contents would be
\"sourced\" - i.e., executed in the current shell context - and
in verbose mode.
Usually we would prepare bash by patching the file ~/.bashrc and
putting the definition for \"ee\" there. We will discuss how to
do that later; now let's test a simple environment in which `M-x
eev' and \"ee\" work. First execute these two sexps:
(make-directory \"~/.eev/\" 'force)
(eev \"rm -Rv /tmp/foo\\nmkdir /tmp/foo/\\ncd /tmp/foo/\\n\")
Now run this script
(eepitch-bash)
(eepitch-kill)
(eepitch-bash)
export PS1='$PWD# '
function ee () { set -v; . ~/.eev/ee.sh; set +v; }
`ee'
====
\[Explain how several interpreters can be programmed to accept
an `ee' command to execute temporary scripts\]
http://angg.twu.net/eev-article.html#making-progs-receive-cmds
(find-eev \"eev-langs.el\")
(find-eev \"eev-bounded.el\")
(find-eev \"eev-rctool\")
An `ee' for Python
==================
Here is a simple way to make Python execute commands saved in a
temporary script when the user types `ee()' (note that it is not
just `ee' - the `()' is needed). We will show first an example in
which the temporary script is prepared by running \"cat\" from a
shell - then we will explain a more user-friendly way to save a
region from the current buffer as the temporary script.
Note that the demo below uses `find-wset', which is an
advanced (i.e., hackish) feature explained here:
(find-multiwindow-intro \"Several eepitch targets\")
(find-3EE '(eepitch-shell) '(eepitch-python))
(find-3ee '(eepitch-shell) '(eepitch-python))
(eepitch-python)
import os
def ee():
execfile(os.getenv(\"HOME\")+\"/.eev/ee.py\", globals())
(eepitch-shell)
cat > ~/.eev/ee.py <<'%%%'
print(1+2)
%%%
(eepitch-python)
ee()
(eepitch-shell)
cat > ~/.eev/ee.py <<'%%%'
def foo (x):
return x*x
print foo(5)
%%%
(eepitch-python)
ee()
print(foo(6))
`eepy'
======
The function `eev' receives three parameters, called `s', `e', and
`altfile'; `e' and `altfile' are optional, and `s' should be either a
string or a number. When `s' is a string, then the commands to be
saved into the temporary script are taken from `s'; the numeric case
will be discussed later.
A call to
(eev \"print(1+2)\" nil \"~/.eev/ee.py\")
writes \"print(1+2)\" (with an added trailing newline, but that's
a technical detail) into the \"alternative file\"
\"~/.eev/ee.py\" - the default would be \"~/.eev/ee.sh\". We can
that to simplify our demo a bit:
(eek \"C-x 1\")
(eepitch-python)
(eepitch-kill)
(eepitch-python)
import os
def ee():
execfile(os.getenv(\"HOME\")+\"/.eev/ee.py\", globals())
(eev \"print(1+2)\" nil \"~/.eev/ee.py\")
ee()
(eev \"def foo (x):\\n return x*x\\n\\nprint foo(5)\" nil \"~/.eev/ee.py\")
ee()
print(foo(6))
In the example below the first line defines a `eepy' in a
simplistic way:
(defun eepy (s &optional e) (eev s e \"~/.eev/ee.py\"))
(eek \"C-x 1\")
(eepitch-python)
(eepitch-kill)
(eepitch-python)
import os
def ee():
execfile(os.getenv(\"HOME\")+\"/.eev/ee.py\", globals())
(eepy \"print(1+2)\")
ee()
(eepy \"def foo (x):\\n return x*x\\n\\nprint foo(5)\")
ee()
print(foo(6))
`M-x eepy' and `M-x eev'
========================
Now let's define a more realistic `eepy' - one that can also be
called interactively. We want `M-x eepy' to save the current
_region_ into the temporary script; `eepy' has to be a _command_,
and we will use the argument \"r\" to its `interactive' clause,
to make the function `eepy' receive two numbers - the start and
the end of the region - and it will pass these two numbers to
`eev'.
(defun eepy (s &optional e)
\"Save the region between S and E (or the string S) into ~/.eev/ee.py .\"
(interactive \"r\")
(eev s e \"~/.eev/ee.py\"))
When the first argument, `s', to `eev', is a number, not a
string, then `eev' expects the second argument, `e', to also be a
number - and then `s' and `e' are considered as the extremities
of a region of text in the current buffer. This idea - that the
first argument can be either a string or a number - comes from:
(find-efunctiondescr 'write-region \"If START is a string\")
But try these:
(ee-se-to-string \"foo\" nil)
(ee-se-to-string-with-nl \"foo\" nil)
(ee-se-to-string \"foo\\n\" nil)
(ee-se-to-string-with-nl \"foo\\n\" nil)
(ee-se-to-string (- (point) 5) (point))
(ee-se-to-string-with-nl (- (point) 5) (point))
(ee-se-to-string (point) (- (point) 5))
(ee-se-to-string-with-nl (point) (- (point) 5))
\[Garbage:\]
(find-elnode \"Defining Commands\")
(find-defun-intro \"\\ninteractive\\n\")
(find-efunction 'eev)
" rest)))
;; (find-prepared-intro)
;; (find-bashnode "Bourne Shell Builtins" "current shell context")
;;; _ _ _
;;; | |__ ___ _ _ _ __ __| | ___ __| |
;;; | '_ \ / _ \| | | | '_ \ / _` |/ _ \/ _` |
;;; | |_) | (_) | |_| | | | | (_| | __/ (_| |
;;; |_.__/ \___/ \__,_|_| |_|\__,_|\___|\__,_|
;;;
;; «find-bounded-intro» (to ".find-bounded-intro")
;; (find-intro-links "bounded")
(defun find-bounded-intro (&rest pos-spec-list) (interactive)
(let ((ee-buffer-name "*(find-bounded-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-bounded-intro)
Source code: (find-eev \"eev-intro.el\" \"find-bounded-intro\")
More intros: (find-eev-intro)
(find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
Note that you need to understand the concept of \"prepared
shells\" quite well to be able to use this... see:
(find-prepared-intro)
Bad news: I've been using this feature very little, and I have
not yet adapted the old, crappy docs to the new \"intro\"
format... =\\ So this is just a bunch of notes!
Source code: \(find-eev \"eev-bounded.el\")
Obsolete related code: \(find-eev \"eev-langs.el\")
Old mentions to this: \(find-TH \"eev-article\" \"delimited-regions\")
http://angg.twu.net/eev-article.html#delimited-regions
Delimited (\"bounded\") regions
===============================
Try:
#
# (eev-bounded)
cd
echo At: $PWD
cd /tmp/
echo At: $PWD
#
%
% (eelatex-bounded)
Hello
%
Defining new bounded functions
==============================
Try:
(find-code-bounded 'eev-bounded 'eev \"\\n#\\n\")
(find-code-bounded 'eev-bounded 'eev 'ee-delimiter-hash)
as usual, when we remove the \"find-\"s the generated code is
executed instead of displayed.
The default bounded function
============================
...is stored in the variable `ee-bounded-function', and can be
re-run with `M-x ee-bounded-function' (i.e., there's a function
with the same name as the variable). I used to bind `f3' to that,
but in modern Emacsen this is bound to a macro key:
(find-enode \"Basic Keyboard Macro\" \"\")
so you should do something like this, but for your favourite key:
(define-key eev-mode-map [f3] 'ee-bounded-function)
" pos-spec-list)))
;; (find-bounded-intro)
;;; _ _
;;; ___| |__ __ _ _ __ _ __ ___| |___
;;; / __| '_ \ / _` | '_ \| '_ \ / _ \ / __|
;;; | (__| | | | (_| | | | | | | | __/ \__ \
;;; \___|_| |_|\__,_|_| |_|_| |_|\___|_|___/
;;;
;; «find-channels-intro» (to ".find-channels-intro")
;; (find-intro-links "channels")
(defun find-channels-intro (&rest pos-spec-list) (interactive)
(let ((ee-buffer-name "*(find-channels-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-channels-intro)
Source code: (find-eev \"eev-intro.el\" \"find-channels-intro\")
More intros: (find-eev-intro)
(find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
Introduction
============
Before eepitch had been invented, eev had two other ways to send
commands to external shell-like programs. The first way,
described here,
(find-prepared-intro \"\\n`ee'\\n\")
was technically very simple: running `M-x eev' would save a
series of commands - usually the contents of the region - into a
temporary script file, and then the user would type something
like `ee' at the prompt of a (\"prepared\") shell; that would
make it read the saved commands and execute them.
Here we will describe the second of the Old Ways - one in which
the target program, which is usually a shell running in an xterm,
is sent a signal saying \"execute the command NOW\" as soon as a
command is saved into a temporary file by Emacs. The difficulty
is that this requires not only a directory for temporary files,
but also an Expect script, which acts as an intermediary that
listens to signals and handles them pretending that the saved
commands came from the keyboard... and, as some people have said,
this is \"a nightmare to set up\".
Here we explain the protocol - which can be adapted to other
cases too, like, for example, to make Emacs talk to SmallTalk
environments and to computer algebra systems with GUIs - and we
will present several tests that should help with troubleshooting.
The innards
===========
Let's start with a detailed low-level view of of what we have
just summarized as to \"save a command into a temporary file,
then send a signal to the external program etc etc\".
Warning: this document is still VERY INCOMPLETE, and some parts
of it are just notes, drafts, and links that may not work for
you... =(
(find-eev \"eegchannel\")
(find-eev \"anim/\")
(find-eev \"anim/channels.anim\")
http://angg.twu.net/eev-current/eegchannel.html
The protocol, in diagrams
=========================
Here's a diagram that shows roughly what we have when X is
running both an Emacs and an xterm, each in a separate window.
Many details have been omitted - for examples, the real
communication happens through fifos and ptys, that are not shown
- but it's easy to build a complete diagram from this. The arrows
indicate flow of information.
keyboard mouse display
| | ^
v v |
+----------------------------+
| |
| X |
| |
+----------------------------+
key/mouse | ^ display key/mouse | ^ display
events v | commands events v | commands
+---------+ +---------+
| | | |
| emacs | | xterm |
| | | |
+---------+ +---------+
chars and | ^ chars and
signals v | signals
+---------+
| |
| sh |
| |
+---------+
To make the external shell at the right able to receive commands
from Emacs we will insert a program between the \"xterm\" and the
\"sh\" boxes - an Expect script called eechannel, that will
usually be totally transparent, in the sense that it will let all
the chars and signals that it receives pass through it without
changes.
The trick is that \"eechannel\" will also be \"listening to
commands from the outside\", according to the following protocol:
1) each instance of eechannel \"listens\" to a fixed, named
\"channel\"; for simplicity, let's suppose that this name is
\"A\".
2) When an eechannel receives a signal SIGUSR1 it reads a
string from the file \"eech.A.str\" and sends that to the
shell, as if the user had typed that.
3) To make it simpler to send the signal, when eechannel starts
up it saves its pid into the file \"eech.A.pid\".
That protocol can be depicted as the four horizontal arrows
below; the temporal order is from top to bottom.
+-------------+
| |
| xterm |
| |
+-------------+
+-----------+ | ^
| | --> eeg.A.str v |
| emacs | <-- eeg.A.pid +-------------+
| | -----------------> | |
+-----------+ eeg.A.str ---> | eechannel A |
| |
+-------------+
| ^
v |
+-------------+
| |
| sh |
| |
+-------------+
When Emacs wants to send a line, say, \"cd /tmp/\", to eechannel,
it does this:
1) \"--> eeg.A.str \" writes \"cd /tmp/\" into eech.A.str,
2) \"<-- eeg.A.pid \" reads eechannel's pid from eech.B.str,
3) \"----------------->\" sends a signal SIGUSR1 to that pid,
4) \" eeg.A.str --->\" ...and when eechannel receives a SIGUSR1
it reads the contents of eech.A.str and
sends that to its spawned shell.
Actually there's something else - how these programs are started.
If we run just \"xterm\", it behaves in its default way, and runs
a shell. But if we run
\"xterm -e eechannel A /bin/sh\"
then xterm runs \"eechannel A /bin/sh\" instead of just
\"/bin/sh\"; and \"eechannel A /bin/sh\" runs \"/bin/sh\".
Also, evaluating this
(find-bgprocess \"xterm\")
from Emacs runs an xterm, which runs a shell; evaluating either
of these sexps,
(find-bgprocess \"xterm -e eechannel A /bin/sh\")
(find-bgprocess \"xterm -e eechannel A $SHELL\")
runs an xterm, which runs the \"eechannel\" script, which runs a
shell. The sexp
(eexterm \"A\")
is a shorthand for the one using \"$SHELL\". Also, note that
\"eechannel A ...\" saves its pid into \"eech.A.pid\".
The diagram that shows what happens when we run `(eexterm \"A\")'
is this one, below - note that the four arrows of the sending
protocol are not shown.
+------------+
| |
| X |
| |
+------------+
/ ^ \\ ^
v / v \\
+-----------+ +-------------+
| | initiates | |
| emacs |:::::::::::>| xterm |
| | | |
+-----------+ +-------------+
:: | ^
\\/ v |
+-------------+
| |
eeg.A.pid <-- | eechannel A |
| |
+-------------+
:: | ^
\\/ v |
+-------------+
| |
| sh |
| |
+-------------+
Downloading and testing eechannel
=================================
Here I'll suppose that the directory \"~/bin/\" exists and is in
your PATH. Run this to download the \"eechannel\" script and make
it executable:
(eepitch-shell)
(eepitch-kill)
(eepitch-shell)
cd ~/bin/
# See: http://angg.twu.net/bin/eechannel.html
wget -n http://angg.twu.net/bin/eechannel
chmod 755 eechannel
Now let's test - from Emacs - if a local copy of \"eechannel\"
exists, is in your PATH, and can be executed (remember that it
needs Expect). Calling \"eechannel\" with not enough arguments
should yield a nice error message.
(find-fline \"~/bin/eechannel\")
(find-sh \"~/bin/eechannel\")
(find-sh \"eechannel\")
It uses the environment variable EEVTMPDIR to decide where the
temporary files - ee.CHANNELAME.pid, ee.CHANNELNAME.str - will
be, so let's check that this directory exists:
(getenv \"EEVTMPDIR\")
(find-fline \"$EEVTMPDIR/\")
Running eechannel with a first argument \"-v\" should show a lot
of info, and then save the pid at eech.CHANNELAME.pid and run the
given command. Let's try with a command that exits immediately.
(find-sh \"eechannel -v A /bin/true\")
(find-fline \"$EEVTMPDIR/\" \"eech.A.pid\")
Now let's verify - using just eepitch, without xterm at this
moment - whether eechannel is being able to receive signals. In
the eepitch script below, two `(find-sh0 \"kill ...\")'s should
each make the controlled program receive a command - at the first
\"kill\" an \"echo 2\", at the second an \"echo 3\".
(eepitch-comint \"A\" \"eechannel -v A /bin/sh\")
(eepitch-kill)
(eepitch-comint \"A\" \"eechannel -v A /bin/sh\")
echo 1
(find-sh0 \" cat $EEVTMPDIR/eech.A.pid\")
(find-sh0 \"echo 'echo 2' > $EEVTMPDIR/eech.A.str\")
(find-sh0 \" cat $EEVTMPDIR/eech.A.str\")
(find-sh0 \"kill -USR1 $(cat $EEVTMPDIR/eech.A.pid)\")
(find-sh0 \"echo 'echo 3' > $EEVTMPDIR/eech.A.str\")
(find-sh0 \"kill -USR1 $(cat $EEVTMPDIR/eech.A.pid)\")
echo 4
If the eepitched shell did run \"echo 1\", \"echo 2\", \"echo
3\", \"echo 4\", then things are working - \"echo 1\" and \"echo
4\" were sent through eepitch, but \"echo 3\" and \"echo 4\" were
sent though channels.
Now let's check if we can run an xterm, and if it can run an
eechannel-ed shell instead of a plain shell. Check if the second
sexp above starts an xterm, displays the info from \"eechannel
-v\", and then runs a shell:
(find-bgprocess \"xterm\")
(find-bgprocess \"xterm -e eechannel -v A $SHELL\")
(find-bgprocess \"xterm -e eechannel A $SHELL\")
if that worked, run the four sexps below with ,
(find-sh0 \"echo 'echo 1' > $EEVTMPDIR/eech.A.str\")
(find-sh0 \"kill -USR1 $(cat $EEVTMPDIR/eech.A.pid)\")
(find-sh0 \"echo 'echo 2' > $EEVTMPDIR/eech.A.str\")
(find-sh0 \"kill -USR1 $(cat $EEVTMPDIR/eech.A.pid)\")
and check if the eechannel-ed shell in the xterm has received the
commands \"echo 1\" and \"echo 2\". If it did, try the
higher-level version below - but use s on each line instead
of the s:
(eexterm \"A\")
echo 3
echo 4
If that worked, we're done. =)
Several xterms
==============
http://angg.twu.net/eev-current/anim/channels.anim.html
(eexterm \"A\")
(eexterm \"B\")
# listen on port 1234
netcat -l -p 1234
(eexterm \"A\")
# Send things to port 1234 (on localhost)
{
echo hi
sleep 1
echo bye
sleep 1
} | netcat -q O localhost 1234
\[NOT DONE YET. The rest is (recyclable) garbage.\]
\(Old stuff:)
emacs runs: (find-bgprocess \"xterm -T 'channel A' -e eegchannel A /bin/sh\")
xterm runs: eegchannel A /bin/sh
eegchannel saves its pid at ~/.eev/eeg.A.pid and runs: /bin/sh
At this point the xterm is running a shell that is \"listening on
channel A\"; eegchannel pretends to be transparent and passes all
characters and signals in the vertical arrows transparently - but when
it receives a certain signal (a SIGUSR1) it reads the contents from
the file ~/.eev/eeg.A.str and passes it to the shell, as if those
characters were coming from the xterm - i.e., as if the used had typed
them.
Here are the details of this \"protocol\":
when we type F9 on a line containing \"echo foo\",
emacs saves the string \"echo foo\\n\" into ~/.eev/A.str,
emacs reads the pid of eegchannel from ~/.eev/eeg.A.pid (say, \"1022\"),
emacs runs \"kill -USR1 1022\",
eegchannel reads the string from ~/.eev/A.str, and sends it to the shell.
NOTE: one frequent question is: \"why are you using two normal files
and SIGUSR1s for the communication between emacs and eegchannel,
instead of making them talk through a fifo?\" - the answer is: try to
explain the details of fifos - including creation - to someone who
knows little about the inner workings of a *NIX kernel and who is
uncomfortable to accept another kind of black box... The way with two
files and SIGUSR1s is simpler, works well enough, and I've been able
to write all the code for it in a few hours - and I still don't know
enough about fifos to implement a fifo version of this.
and another one, that was mostly used to control external
programs running in dedicated xterms. You can see an animation
demonstrating it - and an explanation of what each line does -
here:
http://angg.twu.net/eev-current/anim/channels.anim.html
http://angg.twu.net/eev-current/doc/shot-f9.png
How to set it up
================
\[To be written\]
ssh edrx@other.machine
eegchannel A ssh edrx@other.machine
(find-prepared-intro \"\\n`ee'\\n\")
(find-eev \"anim/channels.anim\")
" pos-spec-list)))
;; (find-channels-intro)
;;; _ _
;;; __ _(_) __| | ___ ___ ___
;;; \ \ / / |/ _` |/ _ \/ _ \/ __|
;;; \ V /| | (_| | __/ (_) \__ \
;;; \_/ |_|\__,_|\___|\___/|___/
;;;
;; «find-videos-intro» (to ".find-videos-intro")
;; (find-intro-links "videos")
(defun find-videos-intro (&rest pos-spec-list) (interactive)
(let ((ee-buffer-name "*(find-videos-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-videos-intro)
Source code: (find-efunction 'find-videos-intro)
More intros: (find-eev-intro)
(find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
What we have now
================
I am producing a series of videos about eev - but at this moment
only two very broad introductions are ready 8-(. I have plans for
several short videos about specific usage patterns, but don't
hold your breath yet... also, these are my first videos EVER - so
please excuse any stutterings, hesitations and false starts...
The videos are uploaded to Youtube to make them very easy to
find, but Youtube reduces the resolution of the original videos
and makes them blurry and almost unreadable - so the best way to
watch them is to fetch local copies of the high-res .mp4 files.
Downloading local copies
========================
Here are direct links to both the low-res versions at Youtube
and to the corresponding high-res \".mp4\"s:
Eepitch: a way to control shell-like programs from Emacs
http://www.youtube.com/watch?v=Lj_zKC5BR64
http://angg.twu.net/eev-videos/video4-eepitch.mp4
An introduction to eev2 (2012nov11)
http://www.youtube.com/watch?v=doeyn5MOaB8
http://angg.twu.net/eev-videos/video2.mp4
\(The video about eepitch is shorter and far better than the
other one - please start by it.)
The ideas behind \"local copies\" are here:
(find-psne-intro)
These sexps generate the download scripts in temporary buffers:
(find-eev-video-links \"eepitchvideo\" \"video4-eepitch\" \"Lj_zKC5BR64\")
(find-eev-video-links \"eevvideo\" \"video2\" \"doeyn5MOaB8\")
Hyperlinks to the local copies of the videos
============================================
Notice that the download scripts above contain these sexps:
\(code-video \"eepitchvideo\" \"$S/http/angg.twu.net/eev-videos/video4-eepitch.mp4\")
\(code-video \"eevvideo\" \"$S/http/angg.twu.net/eev-videos/video2.mp4\")
After you execute them hyperlinks like these should work:
(find-eepitchvideo)
(find-eevvideo)
Note that they use mplayer to display the videos, and if you
don't have mplayer - or if you haven't downloaded the \".mp4\"s -
then you will get error messages in the \"*Messages*\" buffer.
You can inspect them with `C-x b *Messages*' or with:
(find-ebuffer \"*Messages*\")
Hyperlinks to positions
=======================
The first argument to `find-eepitchvideo' and to other similar
functions is a time offset; it is optional, and it defaults to
\"0:00\". Any further arguments are ignored, and this allows us
to use them as comments. So these two sexps are equivalent:
(find-eepitchvideo \"0:16\")
(find-eepitchvideo \"0:16\" \"the eepitch-to-shell-and-python example\")
We could use a series of `find-eepitchvideo' sexps to create a
\"table of contents\" for a video, similarly to what we do for
written documents...
Time offsets as hyperlinks to positions
=======================================
In some cases using sexps creates too much visual clutter, and we
would like to be able to create an index or table of contents
writing lines just like this,
0:16 the eepitch-to-shell-and-python example
instead of using explicit elisp hyperlinks.
There is a way to do this, but it is tricky. It involves
activating a mode, called `eev-avadj-mode', in which `M-p' is
bound to a command that locates the first thing looking like a
time offset in the current line, and calls the video player to
make it play the *current default video* starting from that time
offset; a sexp like
(find-eepitchvideo t)
just sets the current default video, but does not invoke the
player. All this is explained here:
(find-audiovideo-intro \"The time-from-bol\")
Eepitch video: table of contents
================================
\(eev-avadj-mode 1)
\(find-eepitchvideo t)
0:16 the eepitch-to-shell-and-python example, very quickly
1:18 executing eepitch scripts with `f8's; f8 on red star lines and normal lines
2:33 the eepitch-to-shell-and-python example - what each line does
3:15 the first three lines use advanced features
3:52 eepitch scripts are made to be executed interactively
5:25 the eepitch-to-shell-and-python example again, more slowly
5:58 what happens when the eepitch target is being shown
7:13 the default is to use two windows
7:33 what happens when the target does not exist
8:25 how to send commands to a new shell
8:54 how an eepitch block (like eepitch-shell/kill/shell) works
9:38 an example with shell comments (which eev uses as hyperlinks)
12:35 refining hyperlinks
12:35 converting shell commands into hyperlinks (by wrapping - by hand)
13:04 wrapping commands - bound to meta-uppercase-letters
13:53 M-M wraps the current line into a hyperlink to a manpage
14:12 demonstrating M-M, M-S and M-T with eek sexps
14:40 M-T wraps the current linto an eepitch-xxx/kill/xxx triple
15:47 introduction to the sandboxed tutorials and to M-j (eejump)
16:17 the default numeric arguments for eejump
16:35 M-5 M-j jumps to the index for the documentation for eev
17:15 temp. eev buffers usually start with a sexp that regenerates the buffer
18:23 where the eepitch-to-shell-and-python example is in the documentation
18:58 Other examples
19:07 pdf-like documents
20:43 a tutorial for Lua based on eepitch
22:26 that's it - last comments, where to find more info, how to get in touch
Eev video: table of contents
============================
\(eev-avadj-mode 1)
\(find-eevvideo t)
0:00 introduction
2:45 unpack the tarball and invoke Emacs
5:07 and make the cursor stop blinking
5:11 Emacs as a Lisp environment
11:48 Open the file \"VERSION\" (TAB completes)
12:15 (eek \"C-x C-f VERSION\") is not very readable
12:35 (find-file \".../VERSION\") is more readable
12:43 to follow it we type M-e, and M-k to go back
14:00 parts for humans and more or less for humans; passive sexps
14:34 variations of M-e that split the screen
15:09 left side is \"before\", right side is \"after\"
16:00 help on a key sequence
16:28 C-h k gives us help on a key sequence
17:46 (eek \"C-h k C-x C-f\") is an unreadble way to get help on a key
17:55 (describe-function 'find-file) is even messier
18:28 (find-efunctiondescr 'find-file) is cleaner - and why
20:14 introduction the eev documentation in \"intro\"s
22:30 (eek \"M-h M-k C-x C-f\") generates a list of hyperlinks
24:15 the first line regenerates the buffer
24:40 the intros are temporary buffers
25:07 we can play without destroying the documentation of eev
25:40 we can copy the hyperlinks to intros to other places
25:53 introduction to eejump
26:44 a plain M-j goes to the index of eejumps
28:00 M-5 M-j goes to the top level of the documentation in intros
28:22 M-2 M-j goes to (find-emacs-intro)
28:36 ...which has lots of links to the emacs manuals
28:54 (find-eev-update-links)
29:47 I could have done that with just instructions in English
30:01 ...but it was more interesting to do that in an executable way.
30:21 remember that the first line regenerates the buffer...
31:07 we use that to select a directory for installation.
31:40 an eepitch block
31:53 emacs is made to handle anyting that looks like text...
32:38 running terminals inside Emacs
32:52 the best of both worlds
33:50 f8
35:48 [oops - I forgot to unpack]
In Portuguese
=============
(find-eev-video-links \"eevvideopt\" \"video2pt\" \"yztYD9Y7Iz4\")
(code-video \"eevvideopt\" \"$S/http/angg.twu.net/eev-videos/video2pt.mp4\")
(eev-avadj-mode 1)
(find-eevvideopt t)
;; (find-eepitchvideo)
;; (find-eevvideo)
;; (find-eevvideopt)
Comparison with youtube
=======================
Note that Youtube has a trick that lets we use URLs that point to
specific positions in videos. For example, this,
http://www.youtube.com/watch?v=Lj_zKC5BR64&t=0m16s
makes the video about eepitch start at 0:16 instead of from the
beginning. Also, each video at Youtube can have uploader comments
and a discussion, and in the text of these comments things like
\"12:34\" become links that make the current video skip to that
position.
(find-audiovideo-intro)
Video2pt: Uma introducao ao eev2 (2012nov15)
=============================================
This is a version in Portuguese of the video above.
It is slightly longer than the version in English because it's
intended mostly for non-Emacsers, so some things are explained
\(much) more slowly...
At youtube: http://www.youtube.com/watch?v=yztYD9Y7Iz4
http://www.youtube.com/watch?v=yztYD9Y7Iz4&t=1h07m40s
Hi-res mp4: http://angg.twu.net/eev-videos/video2pt.mp4
(128228339 bytes, 122MB. Duration: 1:09:42)
# (find-eevvideopt)
# (find-eevvideopt \"1:07:40\" \"eepitch pro shell e pro Python\")
Long story short
================
You may want to copy the block of elisp below to your .emacs. You can
use this sexp to help you:
(ee-copy-rest 0 '(find-fline \"~/.emacs\"))
;; Hyperlinks to videos about eev.
;; See: (find-videos-intro)
;; (find-eev-video-links \"eepitchvideo\" \"video4-eepitch\" \"Lj_zKC5BR64\")
;; (find-eev-video-links \"eevvideo\" \"video2\" \"doeyn5MOaB8\")
;; (find-eev-video-links \"eevvideopt\" \"video2pt\" \"yztYD9Y7Iz4\")
\(code-video \"eepitchvideo\" \"$S/http/angg.twu.net/eev-videos/video4-eepitch.mp4\")
\(code-video \"eevvideo\" \"$S/http/angg.twu.net/eev-videos/video2.mp4\")
\(code-video \"eevvideopt\" \"$S/http/angg.twu.net/eev-videos/video2pt.mp4\")
;; (find-eepitchvideo)
;; (find-eevvideo)
;; (find-eevvideopt)
;; (find-ebuffer \"*Messages*\")
" pos-spec-list)))
;; (find-videos-intro)
;;; _ __
;;; __| | ___ / _|_ _ _ __
;;; / _` |/ _ \ |_| | | | '_ \
;;; | (_| | __/ _| |_| | | | |
;;; \__,_|\___|_| \__,_|_| |_|
;;;
;; «find-defun-intro» (to ".find-defun-intro")
;; (find-intro-links "defun")
(defun find-defun-intro (&rest rest) (interactive)
(let ((ee-buffer-name "*(find-defun-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-defun-intro)
Source code: (find-eev \"eev-intro.el\" \"find-defun-intro\")
More intros: (find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
\[At present this is just a _skeleton_ for a tutorial on defining
functions in Lisp...]
Simple examples
===============
(* 5 5)
(* 6 6)
(defun foo (a) (* a a))
(foo 5)
(foo 6)
(+ 5 5)
(defun foo (a) (+ a a))
(foo 5)
(symbol-function 'foo)
((lambda (a) (* a a)) 5)
((lambda (a) (+ a a)) 5)
See:
(find-elnode \"Function Cells\")
(find-elnode \"Defining Functions\")
Several arguments
=================
(defun foo (a b) (+ (* a a) (* b b)))
(foo 10 2)
(foo 5)
(defun foo () (+ (* 2 3) (* 4 5)))
(foo 10 2)
(foo 5)
(foo)
progn and prog1
===============
The body of a \"defun\" works like a \"progn\".
See: (find-elnode \"Index\" \"* progn:\")
(defun foo (a b) (* a b))
(defun foo (a b) (+ a b) (* a b))
(defun foo (a b) (* a b) (+ a b))
(defun foo (a b) (+ a b))
(foo 5 6)
(progn (* 5 6) (+ 5 6))
(progn \"ignored\" (+ 5 6) \"result\")
(progn)
(prog1 (* 5 6) (+ 5 6))
(prog1 \"result\" (+ 5 6) \"ignored\")
(prog1)
Docstrings
==========
Note that a string in a (progn ...) does nothing - unless it is
the last BODY-FORM.
But see: (find-elnode \"Documentation\")
Try:
(defun foo (a b) \"IGNORED\" (+ a b))
(defun foo (a b) \"This is the description of `foo'\" (+ a b))
(defun foo (a b) \"This is the docstring of `foo'\" (+ a b))
(defun foo (a b) \"This function returns (* A B). Note the italics!\" (+ a b))
(find-efunctiondescr 'foo)
&optional and &rest
===================
See: (find-elnode \"Argument List\")
Try:
(defun foo (a &optional b c) (list \"a,b,c:\" a b c))
(foo 11 22 33)
(foo 11 22)
(foo 11)
(foo)
(foo 11 22 33 44)
(defun foo (a &optional b c &rest r) (list \"a,b,c,r:\" a b c r))
(foo 11 22 33 44 55 66)
(foo 11 22 33 44 55)
(foo 11 22 33 44)
(foo 11 22 33)
(foo 11 22)
(foo 11)
(foo)
(defun foo (a &rest r) (list \"a,r:\" a r))
(foo 11 22 33 44)
(foo 11 22 33)
(foo 11 22)
(foo 11)
(foo)
A tool: my-insert
=================
See: (find-elnode \"Formatting Strings\")
Try:
(format \"<%s>\" \"hello\")
(format \"<%s>\" \"123\")
(format \"<%s>\" 123)
(format \"<%s>\" 'hello)
(format \"<%s>\" '(+ 2 3))
(format \"<%S>\" \"hello\")
(format \"<%S>\" \"123\")
(format \"<%S>\" 123)
(format \"<%S>\" 'hello)
(format \"<%S>\" '(+ 2 3))
Now define:
(defun my-insert (obj)
\"Print (insert) OBJ in the current buffer.\"
(insert (format \"\\n ;; \\\\--> %S\" obj)))
Try:
(my-insert 123)
(my-insert \"123\")
(my-insert \"hello\")
(my-insert 'hello)
(my-insert '(+ 2 3))
(my-insert nil)
(my-insert '())
(my-insert ())
See also:
(find-elnode \"Character Type\")
(find-elnode \"Basic Char Syntax\")
(find-elnode \"Basic Char Syntax\" \"?\\\\n\")
(find-elnode \"General Escape Syntax\")
interactive
===========
Not all Emacs functions are callable with `M-x' - only those that
are \"commands\" are callable in this way. And only \"commands\"
can be bound to keys...
See:
(find-elnode \"Defining Functions\" \"the first two of the BODY-FORMS\")
(find-elnode \"Defining Commands\")
(find-elnode \"Command Overview\")
When you execute an `(interactive ...)' it does nothing - it
simply ignores its arguments (which aren't even evaluated!) and
returns nil. But just as
(defun my-insert (obj) (insert (format \"\\n ;; \\\\--> %S\" obj)))
(find-efunctiondescr 'interactive)
(eek \"M-x foo\")
(commandp 'foo)
(defun foo (&rest rest) (interactive) (bar rest))
(eek \"M-x foo\")
(defun foo (&rest rest) (bar rest))
(defun foo (&rest rest) (interactive \"P\") (bar rest))
(eek \" M-x foo\")
(eek \"M-1 M-x foo\")
(eek \"M-1 M-2 M-3 M-x foo\")
(eek \"M-- M-2 M-3 M-x foo\")
(defun foo (&rest rest) (interactive \"R\") (bar rest))
(eek \"M-x foo\")
" rest)))
;; (find-defun-intro)
;; (find-defun-intro "&rest")
;; (find-defun-intro "\ninteractive\n")
;; (find-defun-intro "Defining Commands")
;;; _ _
;;; ___ _ __ ___ __ _ ___ ___ (_)_ __ | |_ _ __ ___
;;; / _ \ '_ ` _ \ / _` |/ __/ __|_____| | '_ \| __| '__/ _ \
;;; | __/ | | | | | (_| | (__\__ \_____| | | | | |_| | | (_) |
;;; \___|_| |_| |_|\__,_|\___|___/ |_|_| |_|\__|_| \___/
;;;
;; «find-emacs-intro» (to ".find-emacs-intro")
;; (find-intro-links "emacs")
(defun find-emacs-intro (&rest rest) (interactive)
(let ((ee-buffer-name "*(find-emacs-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-emacs-intro)
Source code: (find-eev \"eev-intro.el\" \"find-emacs-intro\")
More intros: (find-eev-intro)
(find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
Basic keys (eev)
================
The most basic keys of eev are:
M-e - to follow a hyperlink, see: (find-eval-intro \"Elisp hyperlinks\")
M-k - to go back, see: (find-eval-intro \"\\nGoing back\")
M-j - to jump to certain predefined places - in particular,
`M-j' takes you to the list of jump targets in (find-eev \"eejump.el\")
`M-2j' takes you to this help page.
`M-5j' takes you to: (find-eev-intro)
See: (find-eejump-intro \"Families\")
M-h M-h - hyperlinks to here, plus help.
See: (find-links-intro \"`find-here-links'\")
The mnemonics are:
M-e - evaluate/execute
M-j - jump
M-k - kill buffer
It is possible to start learning Emacs and eev by remembering
only that `M-j' jumps to an index; when you're lost, type `M-j',
and will see a reminder of the main keys and of the main jump
targets - after that you can learn how to use `M-k' to kill the
top buffer, and `M-e' to follow elisp hyperlinks. The other keys
are explained in \"intros\" like this one.
Files, Buffers, Windows, Frames, Display, etc
=============================================
Emacs can edit several files at the same time, each one
in a \"buffer\".
(find-enode \"Files\")
(find-enode \"Buffers\")
(find-enode \"Windows\")
(find-enode \"Frames\")
The display of Emacs looks like this (asciified):
__ _ _
______________emacs_______\\/|-|X|
/ | | \\
| | bla. | | Emacs
Window | | | | calls this
managers | | | | a \"window\".
call | | | /
this a | |--:** foo.txt (Fundamental) ----| <-- Its \"modeline\".
\"window\". / | | \\
Emacs \\ | bla bla. | | Another
calls | | bleh | | window.
this a | | | |
\"frame\". | | | /
| |--:** bar.txt (Fundamental) ----| <-- Its modeline.
\\ |Find file: ~/bletch.txt_ ________| <-- The minibuffer.
The bottom line of a frame is sometimes the \"echo area\",
sometimes the \"minibuffer\". The minibuffer acts like a
window when it is active, and `C-x o' can be used to move
from it to the \"normal windows\" and back. You can also
use the mouse to move between windows.
(find-enode \"Echo Area\")
(find-enode \"Minibuffer\")
(find-enode \"Other Window\")
By default there's also a \"menu bar\" (with textual entries) and
a \"tool bar\" (with icons) at the top of each frame, but
advanced users usually disable them.
(find-enode \"Menu Bar\")
(find-enode \"Tool Bars\")
Basic keys (Emacs)
==================
\(find-enode \"Keys\" \"key sequence\")
\(find-enode \"User Input\" \"`Control-a'\" \"usually written `C-a'\")
\(find-enode \"User Input\" \" key\")
\(find-enode \"Completion\" \"\")
(find-enode \"Quitting\")
C-g keyboard-quit (find-enode \"Quitting\" \"`C-g'\")
M-x execute-extended-command (find-enode \"M-x\" \"Running Commands by Name\")
Cutting & pasting
=================
The \"region\" where cut & copy operate is always what is between
the \"point\" and the \"mark\":
(find-enode \"Point\")
(find-enode \"Mark\")
You can do cut, copy and paste by using the icons in the toolbar
or by using the menu bar (the relevant options are under
\"Edit\"), but the keys are worth learning:
C-SPC -- set-mark-command (find-enode \"Setting Mark\")
C-x C-x -- exchange-point-and-mark (find-enode \"Setting Mark\" \"C-x C-x\")
C-w -- kill-region (cut) (find-enode \"Other Kill Commands\")
M-w -- kill-ring-save (copy) (find-enode \"Kill Ring\")
C-y -- yank (paste) (find-enode \"Kill Ring\")
Undoing
=======
C-/ -- undo (find-enode \"Basic Undo\")
C-_ -- undo (find-enode \"Basic Undo\")
(find-enode \"Undo\")
Windows
=======
See: (find-enode \"Frames\")
(find-enode \"Windows\")
C-x o -- other-window (find-enode \"Other Window\")
C-x 0 -- delete-window (find-enode \"Change Window\")
C-x 1 -- delete-other-windows (\"1 window\") (find-enode \"Change Window\")
C-x 2 -- split-window-vertically (Abv/Blw) (find-enode \"Split Window\")
C-x 3 -- split-window-horizontally (L|R) (find-enode \"Split Window\")
Other keys / reference
======================
M-x -- execute-extended-command (find-enode \"M-x\")
more about the minibuffer: (find-enode \"Minibuffer\")
TAB -- for completion: (find-enode \"Completion\")
for indentation: (find-enode \"Indentation\")
in programming modes: (find-enode \"Basic Indent\")
(find-enode \"Dired\")
C-x C-f -- find-file (find-enode \"Visiting\")
C-x C-s -- save-buffer (find-enode \"Saving\")
C-x C-c -- save-buffers-kill-emacs (find-enode \"Saving\")
C-x b -- switch-to-buffer (find-enode \"Select Buffer\")
C-x k -- kill-buffer (find-enode \"Kill Buffer\")
C-a -- beginning-of-line (find-enode \"Moving Point\")
C-e -- end-of-line (find-enode \"Moving Point\")
M-< -- beginning-of-buffer (find-enode \"Moving Point\")
M-> -- end-of-buffer (find-enode \"Moving Point\")
M-q -- fill-paragraph (find-enode \"Fill Commands\")
C-s -- isearch-forward (find-enode \"Incremental Search\")
C-r -- isearch-backward (find-enode \"Incremental Search\")
M-C-s -- isearch-forward-regexp (find-enode \"Regexp Search\")
M-C-r -- isearch-backward-regexp (find-enode \"Regexp Search\")
M-% -- query-replace (find-enode \"Replace\")
C-x ( -- start-kbd-macro (find-enode \"Keyboard Macros\")
C-x ) -- end-kbd-macro (find-enode \"Keyboard Macros\")
C-x e -- call-last-kbd-macro (find-enode \"Keyboard Macros\")
" rest)))
;; (find-emacs-intro)
;; (find-TH "emacs" "short-emacs-tutorial")
;; «find-org-intro» (to ".find-org-intro")
;; (find-intro-links "org")
(defun find-org-intro (&rest pos-spec-list) (interactive)
(let ((ee-buffer-name "*(find-org-intro)*"))
(apply 'find-estring "\
\(Re)generate: (find-org-intro)
Source code: (find-efunction 'find-org-intro)
More intros: (find-eev-intro)
(find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
Is is meant as both a tutorial and a sandbox.
Google Tech talk by Carsten Dominik (2008)
==========================================
http://orgmode.org/talks.html
http://orgmode.org/worg/org-tutorials/org-screencasts/org-mode-google-tech-talk.html
http://www.youtube.com/watch?v=oJTwQvgfgMM Emacs Org-mode - a system for note-taking and project planning
\(find-youtubedl-links \"/sda5/videos/\" \"Emacs_Org-mode_-_a_system_for_note-taking_and_project_planning\" \"oJTwQvgfgMM\" \".flv\" \"carsten2008\")
(ee-youtubedl-hash-to-fname \"oJTwQvgfgMM\")
\(setq ee-carsten2008 (ee-youtubedl-hash-to-fname \"oJTwQvgfgMM\"))
\(code-mplayer \"carsten2008\" ee-carsten2008)
\(find-carsten2008 \"0:00\")
\(eev-avadj-mode 1)
\(find-carsten2008 t)
1:20 Carsten Start
1:50 History
2:15 Working with Text Files
3:58 Notes (not tasks) based project planning
5:50 Outline mode - fixing
9:56 Structure Editing
11:00 Note taking other supports
13:35 Meta data Intro
14:57 tags
15:26 Timeplanning
15:53 Properties
16:02 Meta data propagation
16:49 Special Meta entry interfaces
17:55 DateTime interface
18:24 Column view
19:20 Capture with remember
23:02 Collect and Display
23:52 Sparse tree
25:47 Agenda view
27:27 Exporting and publishing
29:05 Tables
31:34 Calc
32:44 Radio tables
34:53 Context sensitive keys
38:13 How is org used
40:55 Evolved Software software
" pos-spec-list)))
;; (find-org-intro)
(provide 'eev-intro)
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "«%s»"
;; no-byte-compile: t
;; End:
eev-20141011/eev-mode.el 0000644 0001750 0001750 00000023746 12241547077 013262 0 ustar edrx edrx ;;; eev-mode.el -- a minor mode with keybindings for using eev conveniently.
;; Copyright (C) 2012,2013 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2013nov15
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;; (find-eev-intro)
;;; Commentary:
(defun ee-kill-this-buffer ()
"Kill the current buffer with fewer warnings than `kill-this-buffer'.
See: (find-eval-intro \"`M-k'\")"
(interactive)
(let ((kill-buffer-query-functions nil))
(kill-this-buffer)))
;;; _
;;; | | _____ _ _ _ __ ___ __ _ _ __
;;; | |/ / _ \ | | | '_ ` _ \ / _` | '_ \
;;; | < __/ |_| | | | | | | (_| | |_) |
;;; |_|\_\___|\__, |_| |_| |_|\__,_| .__/
;;; |___/ |_|
;;;
;;; eev mode keymap
(defvar eev-mode-map nil)
(defun eev-mode-map-set ()
"Add the standard keybindings for eev to `eev-mode-keymap'."
;;
;; Eepitch: a simple way to script interactive programs.
;; Explanation: (find-eepitch-intro "The main key: ")
;; (find-eepitch-intro "Creating eepitch blocks: ")
;; Source: (find-eev "eepitch.el")
(define-key eev-mode-map [f8] 'eepitch-this-line)
(define-key eev-mode-map "\M-T" 'eewrap-eepitch)
;;
;; Keys for following hyperlinks and for going back.
;; Explanation: (find-eval-intro "`M-e'")
;; (find-eval-intro "Going back")
;; Source: (find-eev "eev-eval.el")
(define-key eev-mode-map "\M-e" 'ee-eval-sexp-eol) ; extends C-e C-x C-e
(define-key eev-mode-map "\M-E" 'ee-eval-last-sexp) ; extends C-x C-e
(define-key eev-mode-map "\M-k" 'ee-kill-this-buffer)
(define-key eev-mode-map "\M-K" 'bury-buffer)
;;
;; Explanation: (find-wrap-intro)
;; Tests: (find-wrap-intro "all wrapping functions")
;; Source: (find-eev "eev-wrap.el")
(define-key eev-mode-map "\M-A" 'eewrap-anchor)
(define-key eev-mode-map "\M-C" 'eewrap-code-c-d)
(define-key eev-mode-map "\M-D" 'eewrap-debian)
(define-key eev-mode-map "\M-F" 'eewrap-find-fline)
(define-key eev-mode-map "\M-J" 'eewrap-eejump)
(define-key eev-mode-map "\M-M" 'eewrap-man)
(define-key eev-mode-map "\M-P" 'eewrap-pdflike)
(define-key eev-mode-map "\M-R" 'eewrap-rm/mkdir/cd)
(define-key eev-mode-map "\M-S" 'eewrap-sh)
(define-key eev-mode-map "\M-Z" 'eewrap-zsh)
;;
;; Keys for creating temporary buffers with elisp hyperlinks:
;; Source: (find-eev "eev-elinks.el")
(define-key eev-mode-map "\M-h\M-d" 'find-debpkg-links)
(define-key eev-mode-map "\M-h\M-f" 'find-efunction-links)
(define-key eev-mode-map "\M-h\M-i" 'find-einfo-links)
(define-key eev-mode-map "\M-h\M-k" 'find-ekey-links)
(define-key eev-mode-map "\M-h\M-p" 'find-pdflike-page-links)
(define-key eev-mode-map "\M-h\M-v" 'find-evariable-links)
(define-key eev-mode-map "\M-hf" 'find-file-links)
(define-key eev-mode-map "\M-hM" 'find-ekbmacro-links)
;; (define-key eev-mode-map "\M-h\M-m" 'find-manpage-links)
;; (define-key eev-mode-map "\M-hm" 'find-last-manpage-links)
;;
;; Information about text properties, faces, and chars:
;; (define-key eev-mode-map "\M-h\M-s" 'find-efacedescr)
(define-key eev-mode-map "\M-h\M-c" 'find-echardescr)
(define-key eev-mode-map "\M-h\M-s" 'find-eface-links)
(define-key eev-mode-map "\M-h\M-t" 'find-etpat)
(define-key eev-mode-map "\M-ht" 'find-etpat0)
;;
;; Extras:
(define-key eev-mode-map "\M-hg" 'find-git-links-1)
;;
;; Keys for editing hyperlinks:
;; Source: (find-eev "eev-edit.el")
(define-key eev-mode-map "\M-h\M-2" 'ee-duplicate-this-line)
(define-key eev-mode-map "\M-h\M-y" 'ee-yank-pos-spec)
(define-key eev-mode-map "\M-h\M--" 'ee-shrink-hyperlink-at-eol)
;;
)
(when (not eev-mode-map)
(setq eev-mode-map (make-sparse-keymap))
(eev-mode-map-set))
;;; _
;;; ___ _____ __ _ __ ___ ___ __| | ___
;;; / _ \/ _ \ \ / /____| '_ ` _ \ / _ \ / _` |/ _ \
;;; | __/ __/\ V /_____| | | | | | (_) | (_| | __/
;;; \___|\___| \_/ |_| |_| |_|\___/ \__,_|\___|
;;;
;;; eev mode
;;
;; (find-efunctiondescr 'eev-mode)
;; (find-ekeymapdescr eev-mode-map)
;; (find-elnode "Keys in Documentation")
(defvar eev-mode-lighter " eev")
(defvar eev-mode-help "Toggle eev mode, i.e, activate or deactivate the `eev-mode-map' keymap.
With a prefix argument ARG, turn eev-mode on if positive, else off.
See: (find-eev-intro)
\\
Commands to follow hyperlinks:
\\[ee-eval-sexp-eol] -- go to the end of line, then do \\[ee-eval-last-sexp]
\\[ee-eval-last-sexp] -- eval the sexp at the left of point
See: (find-eval-intro)
Commands to return from hyperlinks:
\\[ee-kill-this-buffer] -- kill this buffer
\\[bury-buffer] -- put this buffer at the end of the list of all buffers
See: (find-eval-intro \"\\nGoing back\\n\")
Other very very important commands:
\\[eejump] -- jump to where the main eejump targets are defined
M-5 \\[eejump] -- jump to the index of all sandbox tutorials for eev
See: (find-eejump-intro)
\\[eepitch-this-line] -- pitch this line to another Emacs buffer,
or execute it as lisp if it starts with `'
See: (find-eepitch-intro)
Commands to convert the current line into hyperlinks:
\\[eewrap-find-fline] -- wrap its contents in a `find-fline'
\\[eewrap-man] -- wrap its contents in a `find-man'
\\[eewrap-sh] -- wrap its contents in a `find-sh'
\\[eewrap-eepitch] -- generate an \" (eepitch-{xxx,kill,xxx})\" block
\\[eewrap-anchor] -- convert to two anchors pointing to one another
\\[eewrap-code-c-d] -- wrap its contents in a `code-c-d' and a `find-_file'
\\[eewrap-debian] -- wrap its contents in three Debian hyperlinks
\\[eewrap-eejump] -- make a `(defun eejump-N ...)' from N and a hyperlink
\\[eewrap-rm/mkdir/cd] -- make a rm/mkdir/cd triple
\\[eewrap-pdflike] -- generate links to pdf-like documents
\\[eewrap-audiovideo] -- generate audio/video hyperlinks
See: (find-wrap-intro)
Commands to generate pages with lists of hyperlinks:
\\[find-here-links] -- \"hyperlinks to here\", which supersedes all these:
\\[find-file-links] -- hyperlinks to the current file
\\[find-einfo-links] -- hyperlinks to the current Info node (or intro)
\\[find-grep-links] -- hyperlinks to `find-xxxgrep' sexps
\\[find-manpage-links] -- hyperlinks to a manpage (ask for name)
\\[find-last-manpage-links] -- hyperlinks to a manpage (being viewed)
See: (find-links-intro \"`find-here-links'\")
\\[find-efunction-links] -- hyperlinks to an Emacs function
\\[find-ekey-links] -- hyperlinks to a key sequence and to the function
associated to it
\\[find-evariable-links] -- hyperlinks to an Emacs variable
\\[find-eface-links] -- hyperlinks to a face (default: face at point)
\\[find-debpkg-links] -- hyperlinks about a Debian package
\\[find-ecolor-links] -- hyperlinks to a color
Commands to edit hyperlinks:
\\[ee-duplicate-this-line] -- duplicate this line
\\[ee-yank-pos-spec] -- yank into pos-spec-list
\\[ee-shrink-hyperlink-at-eol] -- shrink `find-xxxfile' to `find-xxx'
\\[eewrap-vldi-list-line] -- transform filename into hyperlink
See: (find-eval-intro \"Producing and refining hyperlinks\")
Other commands:
\\[find-eev-mode-links] -- show this help about eev-mode, or some links
\\[describe-char] -- lots of info about the character at point
\\[find-etpat] -- text properties at point
\\[find-etpat0] -- text properties at point (output in the echo area)")
(defun eev-mode-define ()
"Use this to redefine `eev-mode' with another lighter and another docstring."
(eval `
;;
(define-minor-mode eev-mode
,eev-mode-help
:init-value nil
:global t
:lighter ,eev-mode-lighter)
;;
))
(eev-mode-define)
;; (progn (eev-mode 0) (eev-mode 1))
;; (find-efunctiondescr 'eev-mode)
(provide 'eev-mode)
;; Deleted code:
;;
;; Run the default bounded action (usually `eev-bounded'):
;; (define-key eev-mode-map [f3] 'eeb-default)
;; Steppers:
;; (define-key eev-mode-map [f9] 'eechannel-do-this-line)
;; (define-key eev-mode-map [f12] 'eesteps-do-step)
;; (define-key eev-mode-map "\M-P" 'ee-yank-one-line)
;; For "compose pairs":
;; (define-key eev-mode-map [?\C-,] 'eev-compose-two-keys) ; only works on X
;; (define-key eev-mode-map [?\M-,] 'eev-compose-two-keys) ; works anywhere
;; \\[eechannel-do-this-line] -- send this line through the default channel,
;; or execute this line as lisp if it starts with `'
;; \\[eeb-default] -- execute the default action on bounded regions
;; \\[ee-yank-one-line] -- \"send\" the first line of the last kill, as if the
;; user had typed it
;; \\[eesteps-do-step] -- execute the next step from an `eesteps' list
;; \\[eev-help-page] -- switch to a help page, or hide it and return
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "«%s»"
;; ee-anchor-format: "defun %s "
;; no-byte-compile: t
;; End:
eev-20141011/eev-multiwindow.el 0000644 0001750 0001750 00000011467 12243036007 014701 0 ustar edrx edrx ;; eev-multiwindow.el - functions to create multi-window setups
;; Copyright (C) 2012,2013 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2013aug24
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;; (find-eev-intro)
;;; Commentary:
(defun find-wset-1 () (delete-other-windows))
(defun find-wset-2 () (split-window-vertically))
(defun find-wset-3 () (split-window-horizontally))
(defun find-wset-s () (split-window-sensibly (selected-window)))
(defun find-wset-o () (other-window 1))
(defun find-wset-+ () (balance-windows))
(defun find-wset-_ () (eval (car sexps)) (setq sexps (cdr sexps)))
(defun find-wset-\ ()) ; allow whitespace
(defun find-wset (chars &rest sexps)
"Create a multi-window setting according to CHARS and SEXPS.
A detailed explanation is here: (find-multiwindow-intro)
Here is a list of the standard characters that can be used in CHARS:
1: `delete-other-windows' (C-x C-1)
2: `split-window-vertically' (C-x C-2)
3: `split-window-horizontally' (C-x C-3)
s: `split-window-sensibly'
o: `other-window' (C-x o)
+: `balance-windows' (C-x +)
_: execute the next sexp in SEXPS.
To add support for a new character, say `C', just define
a function `find-wset-C'."
(if (not (equal chars ""))
(let ((c (substring chars 0 1))
(chars (substring chars 1)))
(funcall (ee-intern "find-wset-%s" c))
(apply 'find-wset chars sexps))))
;;; _ _ _ _ _
;;; ___ ___ _ __ (_) |_ ___| |__ | |__ __ _ ___| | _____
;;; / _ \/ _ \ '_ \| | __/ __| '_ \ | '_ \ / _` |/ __| |/ / __|
;;; | __/ __/ |_) | | || (__| | | | | | | | (_| | (__| <\__ \
;;; \___|\___| .__/|_|\__\___|_| |_| |_| |_|\__,_|\___|_|\_\___/
;;; |_|
(defun ee-here (code)
"Example: (ee-here '(eepitch-xxx)) opens the target of (eepitch-xxx) here.
\"Here\" means \"in the current window, without disturbing the
current window configuration\". Normal calls to `eepitch-xxx'
functions split the screen and open the target buffer in another
window; by wrapping them in an `(ee-here ...)' we can bypass
that. This is mainly for `find-wset'."
(let (result)
(find-ebuffer
(save-window-excursion
(setq result (eval code))
eepitch-buffer-name))
result))
(defun ee-here-reset (code)
"Like `ee-here', but also does an `eepitch-kill'."
(let (result)
(find-ebuffer
(save-window-excursion
(eval code)
(eepitch-kill)
(setq result (eval code))
eepitch-buffer-name))
result))
(defun find-wset-= () (ee-here (car sexps)) (setq sexps (cdr sexps)))
(defun find-wset-! () (ee-here-reset (car sexps)) (setq sexps (cdr sexps)))
(defun find-wset-O () (other-window -1))
;; Mnemonic: "e" and "E" are both to prepare eepitch windows,
;; and "E" is more aggressive than "e". See:
;; (find-multiwindow-intro)
(defun find-wset-e () (ee-here (car sexps)) (setq sexps (cdr sexps)))
(defun find-wset-E () (ee-here-reset (car sexps)) (setq sexps (cdr sexps)))
;; Temporary hacks (?)
;; See: (find-multiwindow-intro "High-level words")
(defun find-2a (a b) (find-wset "13_o_o" a b))
(defun find-2b (a b) (find-wset "13_o_" a b))
(defun find-3a (a b c) (find-wset "13_o2_o_o" a b c))
(defun find-3b (a b c) (find-wset "13_o2_o_oo" a b c))
(defun find-3c (a b c) (find-wset "13_o2_o_" a b c))
;; See:
;; (find-multiwindow-intro "Several eepitch targets")
;; (find-multiwindow-intro "Restarting eepitch targets")
(defun find-3ee (b c) (find-wset "13o2=o=o" b c))
(defun find-3EE (b c) (find-wset "13o2!o!o" b c))
(provide 'eev-multiwindow)
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "defun %s "
;; no-byte-compile: t
;; End:
eev-20141011/eev-pdflike.el 0000644 0001750 0001750 00000031462 12305715261 013737 0 ustar edrx edrx ;;; eev-pdflike.el -- hyperlinks to documents made of pages.
;; Copyright (C) 2012,2013 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2014mar05
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;;
;; (find-eev-intro)
;; (find-pdf-like-intro)
;;; Commentary:
;; (code-brfile 'find-fline :local 'brfl)
;; (code-brfile 'find-xpdfpage :local 'brxpdf :dired 'brxpdfd)
;; (code-brurl 'find-firefox :remote 'brm :local 'brml :dired 'brmd)
(require 'eev-brxxx)
;;; _ _ _
;;; __ ____ _ _ __(_) __ _| |__ | | ___ ___
;;; \ \ / / _` | '__| |/ _` | '_ \| |/ _ \/ __|
;;; \ V / (_| | | | | (_| | |_) | | __/\__ \
;;; \_/ \__,_|_| |_|\__,_|_.__/|_|\___||___/
;;
(defvar ee-page-c "{?}")
(defvar ee-page-fname "{?}")
(defvar ee-page-offset 0)
;;; ____ ____ _____ _ _ _
;;; | _ \| _ \| ___| | (_) | _____
;;; | |_) | | | | |_ _____| | | |/ / _ \
;;; | __/| |_| | _|_____| | | < __/
;;; |_| |____/|_| |_|_|_|\_\___|
;;;
;; See: (find-pdf-like-intro)
(defun ee-code-pdftext-rest (rest)
(ee-template0 "
;; {(ee-S `(ee-code-pdftext-rest ,@rest))}
"))
;;; _ __
;;; __ ___ __ __| |/ _|
;;; \ \/ / '_ \ / _` | |_
;;; > <| |_) | (_| | _|
;;; /_/\_\ .__/ \__,_|_|
;;; |_|
;;
;; (find-pdflikedef-links "xpdf" "c fname")
;;
;; find-xpdfpage
;; find-xpdf-page
;; code-xpdf
;;
(defalias 'find-xpdfpage
'find-xpdf-page)
(defun find-xpdf-page (fname &optional page &rest rest)
(find-bgprocess (ee-find-xpdf-page fname page)))
(defvar ee-find-xpdf-page-options '())
(defun ee-find-xpdf-page (fname &optional page)
`("xpdf"
,@ee-find-xpdf-page-options
,fname
,@(if page `(,(format "%d" page)))
))
(defun code-xpdf (c fname &rest rest)
(eval (ee-read (apply 'ee-code-xpdf c fname rest))))
(defun find-code-xpdf (c fname &rest rest)
(find-estring-elisp (apply 'ee-code-xpdf c fname rest)))
(defun ee-code-xpdf (c fname &rest rest)
(concat (ee-template0 "\
;; {(ee-S `(find-code-xpdf ,c ,fname ,@rest))}
;;
\(setq ee-pdflike-last 'find-{c}page)
\(defun find-{c}page (&optional page &rest rest)
(setq ee-pdflike-last 'find-{c}page)
(find-xpdf-page {(ee-pp0 fname)} page))
") (ee-code-pdftext-rest rest)))
(code-brfile 'find-xpdf-page :local 'brxpdfl :dired 'brxpdfd)
;;; _ __
;;; _ __ __| |/ _|
;;; | '_ \ / _` | |_
;;; | |_) | (_| | _|
;;; | .__/ \__,_|_|
;;; |_|
;;
(defalias 'find-pdfpage 'find-xpdfpage)
(defalias 'find-pdf-page 'find-xpdf-page)
(defalias 'code-pdf 'code-xpdf)
(defalias 'find-code-pdf 'find-code-xpdf)
;;; _
;;; _____ _(_)_ __ ___ ___
;;; / _ \ \ / / | '_ \ / __/ _ \
;;; | __/\ V /| | | | | (_| __/
;;; \___| \_/ |_|_| |_|\___\___|
;;;
;;
;; (find-pdflikedef-links "evince" "c fname")
;; (find-man "1 evince")
;;
;; find-evincepage
;; find-evince-page
;; code-evince
;;
(defalias 'find-evincepage
'find-evince-page)
(defun find-evince-page (fname &optional page &rest rest)
(find-bgprocess (ee-find-evince-page fname page)))
(defvar ee-find-evince-page-options '())
(defun ee-find-evince-page (fname &optional page)
`("evince"
,@ee-find-evince-page-options
;; ,@(if page `(,(format "--page-label=%d" page)))
,@(if page `(,(format "--page-index=%d" page)))
,fname))
(defun code-evince (c fname &rest rest)
(eval (ee-read (apply 'ee-code-evince c fname rest))))
(defun find-code-evince (c fname &rest rest)
(find-estring-elisp (apply 'ee-code-evince c fname rest)))
(defun ee-code-evince (c fname &rest rest)
(concat (ee-template0 "\
\(defun find-{c}page (&optional page &rest rest)
(find-evince-page {(ee-pp0 fname)} page))
{(ee-code-pdftext-rest rest)}
") (ee-code-pdftext-rest rest)))
(code-brfile 'find-evince-page :local 'brevincel :dired 'brevinced)
;;; _ _
;;; __ ____| |_ _(_)
;;; \ \/ / _` \ \ / / |
;;; > < (_| |\ V /| |
;;; /_/\_\__,_| \_/ |_|
;;;
;;
;; (find-pdflikedef-links "xdvi" "c fname")
;;
;; find-xdvipage
;; find-xdvi-page
;; code-xdvi
;;
(defalias 'find-xdvipage
'find-xdvi-page)
(defun find-xdvi-page (fname &optional page &rest rest)
(find-bgprocess (ee-find-xdvi-page fname page)))
(defvar ee-find-xdvi-page-options '())
(defun ee-find-xdvi-page (fname &optional page)
`("xdvi"
,@ee-find-xdvi-page-options
,@(if page `(,(format "+%d" page)))
,fname))
(defun code-xdvi (c fname &rest rest)
(eval (ee-read (apply 'ee-code-xdvi c fname rest))))
(defun find-code-xdvi (c fname &rest rest)
(find-estring-elisp (apply 'ee-code-xdvi c fname rest)))
(defun ee-code-xdvi (c fname &rest rest)
(concat (ee-template0 "\
\(defun find-{c}page (&optional page &rest rest)
(find-xdvi-page {(ee-pp0 fname)} page))
{(ee-code-pdftext-rest rest)}
") (ee-code-pdftext-rest rest)))
(code-brfile 'find-xdvi-page :local 'brxdvil :dired 'brxdvid)
(defalias 'code-dvi 'code-xdvi)
(defalias 'find-code-dvi 'find-code-xdvi)
;;; _ _
;;; __| |(_)_ ___ _
;;; / _` || \ \ / / | | |
;;; | (_| || |\ V /| |_| |
;;; \__,_|/ | \_/ \__,_|
;;; |__/
;;
;; (find-pdflikedef-links "djvu" "c fname")
;;
;; find-djvupage
;; find-djvu-page
;; code-djvu
;;
(defalias 'find-djvupage
'find-djvu-page)
(defun find-djvu-page (fname &optional page &rest rest)
(find-bgprocess (ee-find-djvu-page fname page)))
(defvar ee-find-djvu-page-options '())
(defun ee-find-djvu-page (fname &optional page)
`("djview"
,@ee-find-djvu-page-options
,@(if page `(,(format "--page=%d" page)))
,fname))
(defun code-djvu (c fname &rest rest)
(eval (ee-read (apply 'ee-code-djvu c fname rest))))
(defun find-code-djvu (c fname &rest rest)
(find-estring-elisp (apply 'ee-code-djvu c fname rest)))
(defun ee-code-djvu (c fname &rest rest)
(concat (ee-template0 "\
\(defun find-{c}page (&optional page &rest rest)
(find-djvu-page {(ee-pp0 fname)} page))
") (ee-code-pdftext-rest rest)))
(code-brfile 'find-djvu-page :local 'brdjvul :dired 'brdjvud)
;;;
;;; _ __ ___
;;; | '_ \/ __|
;;; | |_) \__ \
;;; | .__/|___/
;;; |_|
;;
;; (find-pdflikedef-links "ps" "c fname")
;;
;; find-pspage
;; find-ps-page
;; code-ps
;;
(defalias 'find-pspage
'find-ps-page)
(defun find-ps-page (fname &optional page &rest rest)
(find-bgprocess (ee-find-ps-page fname page)))
(defvar ee-find-ps-page-options '())
(defun ee-find-ps-page (fname &optional page)
`("gv"
,@ee-find-ps-page-options
,@(if page `(,(format "--page=%d" page)))
,fname))
(defun code-ps (c fname &rest rest)
(eval (ee-read (apply 'ee-code-ps c fname rest))))
(defun find-code-ps (c fname &rest rest)
(find-estring-elisp (apply 'ee-code-ps c fname rest)))
(defun ee-code-ps (c fname &rest rest)
(concat (ee-template0 "\
\(defun find-{c}page (&optional page &rest rest)
(find-ps-page {(ee-pp0 fname)} page))
") (ee-code-pdftext-rest rest)))
;;; __ _ _ _ _
;;; / _(_)_ __ __| | __ ____ ____ __ | |_ _____ _| |_
;;; | |_| | '_ \ / _` |____\ \/ /\ \/ /\ \/ /____| __/ _ \ \/ / __|
;;; | _| | | | | (_| |_____> < > < > <_____| || __/> <| |_
;;; |_| |_|_| |_|\__,_| /_/\_\/_/\_\/_/\_\ \__\___/_/\_\\__|
;;;
(defun ee-goto-position-page (&optional pos-spec &rest rest)
"Like `ee-goto-position', but interpreting a number as a page number.
\(Note that POS-SPEC is only interpreted as a page if it is a number.)"
(when pos-spec
(cond ((numberp pos-spec)
(goto-char (point-min))
(re-search-forward "[\f]" nil nil (1- pos-spec)))
((stringp pos-spec)
(goto-char (save-excursion ; This used to be just:
(goto-char (point-min)) ; (goto-char (point-min))
(search-forward pos-spec) ; (search-forward pos-spec)
(point)))) ;
(t (error "This is not a valid pos-spec: %S" pos-spec)))
(if rest (ee-goto-rest rest))))
(defun find-sh-page (command &rest pos-spec-list)
"Like `find-sh', but interpreting the car of POS-SPEC-LIST as a page."
(interactive "sShell command: ")
(find-eoutput-reuse
command
`(insert (shell-command-to-string ,command)))
(apply 'ee-goto-position-page pos-spec-list))
;; find-pdf-text
;;
(defalias 'find-pdf-text
'find-pdftotext-text)
(defun find-pdftotext-text (fname &rest rest)
(apply 'find-sh-page (ee-find-pdftotext-text fname) rest))
(defun ee-find-pdftotext-text (fname)
(format "pdftotext -layout -enc Latin1 '%s' -" (ee-expand fname)))
(code-brfile 'find-pdf-text
:local 'brpdftextl
:dired 'brpdftextd)
;; find-djvu-text
;;
(defalias 'find-djvu-text
'find-djvutxt-text)
(defun find-djvutxt-text (fname &rest rest)
(apply 'find-sh-page (ee-find-djvutxt-text fname) rest))
(defun ee-find-djvutxt-text (fname)
(format "djvutxt '%s'" fname))
(code-brfile 'find-djvu-text
:local 'brdjvutextl
:dired 'brdjvutextd)
;; (find-pdflikedef-links "pdf" "c fname")
(defun code-pdf-text (c fname &optional offset &rest rest)
(eval (ee-read (apply 'ee-code-pdf-text c fname offset rest))))
(defun find-code-pdf-text (c fname &optional offset &rest rest)
(find-estring-elisp (apply 'ee-code-pdf-text c fname offset rest)))
(defun ee-code-pdf-text (c fname &optional offset &rest rest)
(setq offset (or offset 0))
(concat (ee-template0 "\
;; {(ee-S `(find-code-pdf-text ,c ,fname ,offset ,@rest))}
\(defun find-{c}text (&optional page &rest rest)
(setq ee-page-c {(ee-pp0 c)})
(setq ee-page-fname {(ee-pp0 fname)})
(setq ee-page-offset {(ee-pp0 offset)})
(apply 'find-pdf-text {(ee-pp0 fname)} page rest))
;; Set the defaults now
;; See: (find-pdf-like-intro \"find-code-pdf-text\")
\(setq ee-page-c {(ee-pp0 c)})
\(setq ee-page-fname {(ee-pp0 fname)})
\(setq ee-page-offset {(ee-pp0 offset)})
")))
(defun code-djvu-text (c fname &optional offset &rest rest)
(eval (ee-read (apply 'ee-code-djvu-text c fname offset rest))))
(defun find-code-djvu-text (c fname &optional offset &rest rest)
(find-estring-elisp (apply 'ee-code-djvu-text c fname offset rest)))
(defun ee-code-djvu-text (c fname &optional offset &rest rest)
(setq offset (or offset 0))
(concat (ee-template0 "\
\(defun find-{c}text (&optional page &rest rest)
(setq ee-page-c {(ee-pp0 c)})
(setq ee-page-fname {(ee-pp0 fname)})
(setq ee-page-offset {(ee-pp0 offset)})
(find-djvu-text {(ee-pp0 fname)} page))
;; Set the defaults now - see (find-pdf-like-intro \"find-code-pdf-text\")
\(setq ee-page-c {(ee-pp0 c)})
\(setq ee-page-fname {(ee-pp0 fname)})
\(setq ee-page-offset {(ee-pp0 offset)})
")))
;; Tests:
;; (find-code-pdf-text "foo" "/tmp/foo.pdf" 3)
;; (code-pdf-text "foo" "/tmp/foo.pdf" 3)
;; (find-footext)
;; (find-footext 2)
;; (find-efunction 'find-page-links)
;; Test:
;; (find-code-xpdf "{c}" "{fname}" :key "{foo}" :key "{bar}")
;; (find-xpdfpage "~/tmp/discussao_proifesgroups.pdf")
;; Garbage?
;; (defun ee-pspage (fname &optional page gvargs)
;; `("gv" ,@gvargs ,@(if page (list (format "--page=%d" page))) ,fname))
;; (defun ee-xpdfpage (fname &optional page xpdfargs)
;; `("xpdf" ,@xpdfargs ,fname ,(format "%s" (or page 1))))
;; (defun ee-djvupage (fname &optional page)
;; `("djview" ,@(if page (list (format "--page=%d" page))) ,fname))
(provide 'eev-pdflike)
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "«%s»"
;; ee-anchor-format: "defun %s "
;; no-byte-compile: t
;; End:
eev-20141011/eev-pkg.el 0000644 0001750 0001750 00000000225 12416240040 013062 0 ustar edrx edrx (define-package "eev" "20141011" "Support for e-scripts (eepitch blocks, elisp hyperlinks, etc)")
;; Local Variables:
;; no-byte-compile: t
;; End:
eev-20141011/eev-plinks.el 0000644 0001750 0001750 00000013073 12207375661 013626 0 ustar edrx edrx ;;; eev-plinks.el -- elisp hyperlinks to invoke external processes.
;; Copyright (C) 2012 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2013aug28
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;;
;; (find-eev-intro)
;; (find-links-intro)
;;; Commentary:
;; See:
;; (find-eev "eepitch.el" "find-comintprocess-ne")
;; (find-eev "eev-blinks.el" "find-sh")
;; (find-node "(libc)Executing a File" "execv")
;; Obvious applications:
;; (find-eev "eev-pdflike.el")
;; (find-eev "eev-audiovideo.el")
;; (find-eev "eev-brxxx.el")
;;;
;;; _ __ _ __ ___ ___ ___ ___ ___ ___ ___
;;; | '_ \| '__/ _ \ / __/ _ \/ __/ __|/ _ \/ __|
;;; | |_) | | | (_) | (_| __/\__ \__ \ __/\__ \
;;; | .__/|_| \___/ \___\___||___/___/\___||___/
;;; |_|
;;
;; 2007sep29: Copied these functions from eev-mini.el to here...
;; In a near future all calls to external processes in eev will happen
;; through these functions... mainly because (1) they accept their
;; "program-and-args" argument as either a string (to be split at
;; whitespace) or as a list of strings, (2) they can either expand
;; each "word" or "program-and-args" with ee-expand or keep all words
;; unchanged, (3) they're short and clean.
;; Sorry, no docstrings yet... some tests:
;; (find-callprocess0 '("lua51" "-e" "print(1+2)"))
;; (find-callprocess00 '("lua51" "-e" "print(1+2)"))
;; Suffixes:
;; "-ne" means "(do) not ee-expand"
;; "0" means "don't display in a temp buffer, just return the string"
;; "00" means "like `0', but more low-level: don't strip the trailing newline".
(defun ee-split (str) (if (stringp str) (split-string str "[ \t\n]+") str))
(defun ee-unsplit (list) (if (listp list) (mapconcat 'identity list " ") list))
(defun ee-split-and-expand (str) (mapcar 'ee-expand (ee-split str)))
(defun ee-no-trailing-nl (str) (replace-regexp-in-string "\n$" "" str))
(defun find-bgprocess-ne (program-and-args)
(let ((argv (ee-split program-and-args)))
(apply 'start-process (car argv) "*Messages*" argv)))
(defun find-callprocess00-ne (program-and-args)
(let ((argv (ee-split program-and-args)))
(with-output-to-string
(with-current-buffer standard-output
(apply 'call-process (car argv) nil t nil (cdr argv))))))
(defun find-callprocess0-ne (program-and-args)
(ee-no-trailing-nl (find-callprocess00 program-and-args)))
(defun find-comintprocess-ne (name 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-bgprocess (program-and-args)
(find-bgprocess-ne (ee-split-and-expand program-and-args)))
(defun find-callprocess00 (program-and-args)
(find-callprocess00-ne (ee-split-and-expand program-and-args)))
(defun find-callprocess0 (program-and-args)
(find-callprocess0-ne (ee-split-and-expand program-and-args)))
(defun find-callprocessregion (program-and-args input)
(find-callprocessregion (ee-split-and-expand program-and-args)))
(defun find-comintprocess (name program-and-args)
(find-comintprocess-ne name (ee-split-and-expand program-and-args)))
;; These two are like `find-sh', but more low-level.
(defun find-callprocess-ne (program-and-args &rest pos-spec-list)
(apply 'find-eoutput-reuse (ee-unsplit program-and-args)
`(insert (find-callprocess00-ne ',program-and-args))
pos-spec-list))
(defun find-callprocess (program-and-args &rest pos-spec-list)
(apply 'find-eoutput-reuse (ee-unsplit program-and-args)
`(insert (find-callprocess00 ',program-and-args))
pos-spec-list))
;; New, 2008jan02
;; Compare with `ee-find-grep'
(defun ee-find-comintprocess-ne (dir name program-and-args)
(switch-to-buffer
(with-temp-buffer
(cd dir)
(find-comintprocess-ne name program-and-args)
(current-buffer))))
(defun ee-find-comintprocess (dir name program-and-args)
(ee-find-comintprocess-ne
(ee-expand dir) name (ee-split-and-expand program-and-args)))
;; find-wget
;;
(defun find-wget00 (url)
(find-callprocess00 `("wget" "-q" "-O" "-" ,url)))
(defun find-wget (url &rest rest)
(setq url (ee-expand url))
(apply 'find-eoutput-reuse (format "*wget: %s*" url)
`(insert (find-wget00 ,url))
rest))
(provide 'eev-plinks)
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "«%s»"
;; ee-anchor-format: "defun %s "
;; no-byte-compile: t
;; End:
eev-20141011/eev-prepared.el 0000644 0001750 0001750 00000022451 12054330353 014115 0 ustar edrx edrx ;;; eev-prepared.el -- eev modules that use temporary dirs and prepared shells.
;; Copyright (C) 2012 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2012nov02
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;; (find-eev-intro)
;;; Commentary:
;; See: (find-eev "eev-env.el")
;; (find-prepared-intro)
(require 'eev-env)
(ee-setenv "EEVTMPDIR" "$HOME/.eev") ; ee.sh and other temp scripts
(ee-setenv "EEVRCDIR" "$EEVDIR/rcfiles")
(ee-setenv "EE" "$EEVTMPDIR/ee.sh")
(ee-setenv "EEG" "$EEVTMPDIR/ee.eeg")
(ee-setenv "EEGDB" "$EEVTMPDIR/ee.gdb")
(ee-setenv "EETEX" "$EEVTMPDIR/ee.tex")
(ee-setenv "EEC" "$EEVTMPDIR/ee.c")
(ee-setenv "EETMPC" "$EEVTMPDIR/tmp.c")
(ee-setenv "EEAOUT" "$EEVTMPDIR/ee.aout")
(defvar ee-eevtmpdir (ee-expand "$EEVTMPDIR/")
"The directory where the temporary script files are put.")
(defvar ee-eevrcdir (ee-expand "$EEVRCDIR/")
"The directory where some auxiliary rcfiles for eev are to be found.")
(defvar ee-file (ee-expand "$EE")
"The temporary script file used by `eev'.")
(defvar ee-file-tex (ee-expand "$EETEX")
"The temporary script file used by `eelatex'.")
(defvar ee-file-gdb (ee-expand "$EEGDB")
"The temporary script file used by `eegdb'.")
(defvar ee-file-generic (ee-expand "$EEG"))
(defvar eelatex-eevscript
"cd $EEVTMPDIR/; latex tmp.tex && xdvi tmp.dvi &" "See `eelatex'.")
(code-c-d "eevtmp" "$EEVTMPDIR/" :anchor) ; (find-eevtmpfile "")
(code-c-d "eevrc" "$EEVRCDIR/" :anchor) ; (find-eevrcfile "")
(code-c-d "eevex" "$EEVDIR/examples/" :anchor) ; (find-eevexfile "")
;; (defvar ee-eevdir (ee-expand "$EEVDIR/")
;; "The directory where the elisp files for eev live.")
;; (code-c-d "eev" "$EEVDIR/" :anchor) ; (find-eev "")
;;; __ __
;;; | \/ | __ __ ___ _____ __
;;; | |\/| | __ \ \/ / / _ \/ _ \ \ / /
;;; | | | ||__| > < | __/ __/\ V /
;;; |_| |_| /_/\_\ \___|\___| \_/
;;;
;;; eev and friends (or: saving regions as temporary scripts)
;;;
(defun ee-se-to-string (s e)
"Convert the pair (S E) to a string.
If S is a number then return the contents of the current buffer
between the positions S and E; if S is a string then return S and
ignore E. See `write-region' - it uses the same convention for
interpreting \"(S E)\"-pairs as this function."
(cond ((numberp s) (buffer-substring-no-properties s e))
((stringp s) s)))
(defun octal-to-num (str)
"Convert STR - a sequence of octal digits - to a number."
(let ((lastv (- (string-to-char (substring str -1)) ?0))
(rest (substring str 0 -1)))
(if (string= "" rest) lastv (+ lastv (* 8 (octal-to-num rest))))))
(defun ee-write-string (str &optional altfile fmode)
"Write STR to ALTFILE, or to ee-file if ALTFILE is nil.
FMODE should be either nil or a string containing a sequence of
octal digits; if it is not nil then do the equivalent of a
\"chmod FMODE file\"."
(let ((fname (substitute-in-file-name (or altfile ee-file))))
(write-region str nil fname) ; a standard kludge
(if fmode (set-file-modes fname (octal-to-num fmode)))))
(defun ee-write (s e pre post &optional altfile fmode)
"Write PRE+(ee-se-to-string S E)+POST to ALTFILE, or to `ee-file'.
PRE and POST must be strings. See `ee-se-to-string' and
`ee-write-string'."
(ee-write-string (concat pre (ee-se-to-string s e) post)
altfile fmode))
(defun ee-se-to-string-with-nl (s e)
"Same as `ee-se-to-string', but force the result to end with a newline."
(let ((str (ee-se-to-string s e)))
(if (string-match "[^\n]\\'" str) (concat str "\n") str)))
(defun ee-write-with-nl (s e pre post &optional altfile fmode)
"Same as `ee-write', but using `ee-se-to-string-with-nl'."
(ee-write-string (concat pre (ee-se-to-string-with-nl s e) post)
altfile fmode))
(defun eev (s &optional e altfile)
"Save the region in `ee-file', or in ALTFILE if it is non-nil.
If S is a string write then write the string instead. See `ee-write'.
This function is mostly used to send blocks of commands to shells via
a temporary script file. The shells do not receive the commands
immediately - we need to tell them to execute the commands stored in
the temporary script.\n
For example, if we mark the block below and type `M-x eev',\n
# A hyperlink: (find-efunction 'eev)
echo $[1+2]
# Temporary scripts can change the
# directory and the environment.
cd /tmp/\n
and then go to a prepared shell and run `ee', we see something like
this:\n
/home/edrx$ ee
# A hyperlink: (find-efunction 'eev)
echo $[1+2]
3
# Temporary scripts can change the
# directory and the environment.
cd /tmp/
/tmp$ \n
Note that this only works in \"prepared shells\", where `ee' has been
defined as a shell function in the correct way; the relevant code for
.bashrc or .zshrc is this:\n
export EEVTMPDIR ;: ${EEVTMPDIR:=~/.eev}
export EE ;: ${EE:=$EEVTMPDIR/ee.sh}
function ee () { set -v; . $EE$*; set +v; }\n
See: (find-eevfile \"INSTALL\")
and: (find-eevfile \"eev-rctool\")"
(interactive "r")
(ee-write-with-nl s e "" "" altfile)
(format "eev: wrote %s" (or altfile ee-file)))
(defun eevs (s &optional e suffix)
"Like `eev', but with a suffix; write the region to `ee-file'+SUFFIX.
For example, if $EE is \"~/.eev/ee.sh\" and SUFFIX is \"0\" then
write the region to the file \"~/.eev/ee.sh0\". The shell
function \"ee\" concatenates its first argument to the value of
$EE, so running \"ee 0\" on a prepared shell executes the
temporary script \"~/.eev/ee.sh0\" instead of \"~/.eev/ee.sh\".
If S is a string write then write the string instead. See `ee-write'."
(interactive "r\nsSuffix: ")
(eev s e (concat ee-file suffix)))
(defun eelatex (s &optional e)
"Save the region to `ee-file-tex', then save `eelatex-eevscript' to `ee-file'.
An example: run `M-x eelatex' on the line below,
Hello! $\\frac{42}{\\sqrt{5}}$
then go to a prepared shell and run \"ee\". A temporary LaTeX
file will be processed by \"latex\" and the resulting dvi file
will be shown on the screen.
If S is a string write then write the string instead. See `eev'."
(interactive "r")
(ee-write s e "" "" ee-file-tex)
(eev eelatex-eevscript nil)
(format "eelatex: wrote %s and %s" ee-file-tex ee-file))
(defun eegdb (s &optional e)
"Save the region to the temporary GDB script file given by `ee-file-gdb'.
After that if your GDB init file was prepared adequately then
running \"ee\" on a GDB prompt will make GDB execute the commands
in the temporary GDB script.
If S is a string write then write the string instead. See `eev'."
(interactive "r")
(ee-write s e "" "" ee-file-gdb)
(format "eegdb: wrote %s" ee-file-gdb))
;; Obsolete, or almost? Used by: (find-eevfile "eeg4")
(defun eeg (s &optional e)
(interactive "r")
(ee-write s e "" "" ee-file-generic)
(format "eeg: wrote %s" ee-file-gdb))
(defun eeeval (s &optional e)
"Like `eev', but instead of saving the region execute it immediately as Lisp.
This function is very similar to `eval-region'."
(interactive "r")
(eval (read (concat "(progn " (ee-se-to-string s e) "\n)"))))
(defun ee-default-directory ()
"Return `default-directory' usually, but behave specially in some modes.
If the current buffer is a w3m buffer that is visiting a local
file (i.e., if the url is like \"file://...\") then extract the
directory from the url instead of returning the value of
`default-directory'.\n
This function is used by `eecd'."
(if (eq major-mode 'w3-mode)
(let ((url (url-view-url 0)))
(if (string-match "^file:\\(.*/\\)[^/]*$" url)
(match-string 1 url)
(error "Current url is %S, which is not a local file" url)))
default-directory))
;; 2005jan10, incompatible change: added "dir"
(defun eecd (&optional dir command)
"Save to $EE a \"cd\" command to `cd' to the current directory.
If DIR is not nil then use DIR; otherwise run `ee-default-directory'.
If COMMAND is not nil then save \"cd DIR; COMMAND\" instead of just
\"cd DIR\".\n
See `eev' for more about $EE and the temporary script file."
(interactive)
(eev (concat "cd " (file-name-directory
(or dir (ee-default-directory)))
"\n" (or command ""))))
(provide 'eev-prepared)
;; Local Variables:
;; coding: raw-text-unix
;; ee-anchor-format: "«%s»"
;; ee-anchor-format: "defun %s "
;; no-byte-compile: t
;; End:
eev-20141011/eev-rcirc.el 0000644 0001750 0001750 00000014525 12245457241 013430 0 ustar edrx edrx ;;; eev-rcirc.el -- rcirc-related elisp hyperlinks.
;; Copyright (C) 2012,2013 Free Software Foundation, Inc.
;;
;; This file is (not yet?) part of GNU eev.
;;
;; GNU eev 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 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev 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. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 2013nov27
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also: