;;; eev-tlinks.el --- hyperlinks to temporary buffers generated by templates

;; Copyright (C) 2013-2019 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 <http://www.gnu.org/licenses/>.
;;
;; Author:     Eduardo Ochs <eduardoochs@gmail.com>
;; Maintainer: Eduardo Ochs <eduardoochs@gmail.com>
;; Version:    2019oct14
;; Keywords:   e-scripts
;;
;; Latest version: <http://angg.twu.net/eev-current/eev-tlinks.el>
;;       htmlized: <http://angg.twu.net/eev-current/eev-tlinks.el.html>
;;       See also: <http://angg.twu.net/eev-current/eev-readme.el.html>
;;                 <http://angg.twu.net/eev-intros/find-eev-intro.html>
;;                 <http://angg.twu.net/eev-intros/find-links-intro.html>
;;                                                (find-eev-intro)
;;                                                (find-links-intro)

;;; Commentary:

;; The functions defined here - `find-latex-links' and other ones -
;; produce buffers made of a series of hyperlinks followed by a
;; templated text. The templated text is usually preceded by a line
;; like `(ee-copy-rest NLINES CODE)'; see the explanation of
;; `ee-copy-rest' below to understand how this is used.
;;
;; The functions here are one complexity step above the functions in:
;;   (find-eev "eev-elinks.el")
;;
;; NOTE (written in 2019mar05): some of the functions here are very
;; old and ugly and I haven't used them in ages. They will be deleted
;; in the next few months.

;; (find-efunctiondescr 'ee-upload-links)
;; (find-eev "eev-wrap.el" "eewrap-eewrap")




;; «.ee-copy-rest»		(to "ee-copy-rest")
;;
;; «.find-find-links-links»	(to "find-find-links-links")
;; «.find-intro-links»		(to "find-intro-links")
;; «.find-pdflikedef-links»	(to "find-pdflikedef-links")
;; «.find-eev-header-links»	(to "find-eev-header-links")
;;
;; «.find-debpkg-links»		(to "find-debpkg-links")
;; «.find-eev-install-links»	(to "find-eev-install-links")
;; «.find-eev-update-links»	(to "find-eev-update-links")
;; «.find-youtubedl-links»	(to "find-youtubedl-links")
;; «.find-psne-links»		(to "find-psne-links")
;; «.find-git-links»		(to "find-git-links")
;; «.find-apt-get-source-links»	(to "find-apt-get-source-links")
;; «.find-eev-video-links»	(to "find-eev-video-links")
;;
;; «.find-latex-links»		(to "find-latex-links")
;; «.find-lua-links»		(to "find-lua-links")
;; «.find-escreenshot-links»	(to "find-escreenshot-links")


(require 'eev-env)
(require 'eev-wrap)    ; For: (find-eev "eev-wrap.el" "ee-template0") 



;;;                                                            _   
;;;   ___  ___        ___ ___  _ __  _   _       _ __ ___  ___| |_ 
;;;  / _ \/ _ \_____ / __/ _ \| '_ \| | | |_____| '__/ _ \/ __| __|
;;; |  __/  __/_____| (_| (_) | |_) | |_| |_____| | |  __/\__ \ |_ 
;;;  \___|\___|      \___\___/| .__/ \__, |     |_|  \___||___/\__|
;;;                           |_|    |___/                         
;;
;; «ee-copy-rest» (to ".ee-copy-rest")
;; Some hyperlinks buffers - for example those generated by:
;;
;;   (find-latex-links)
;;   (find-eev-install-links)
;;
;; are composed of a series of hyperlinks, then a sexp like
;; `(ee-copy-rest NLINES CODE)', then some templated text. When we run
;; the `(ee-copy-rest ...)' the templated text is flashed for a
;; fraction of a second and copied to the kill ring, and the window is
;; split in two like this:
;;
;;    ____________________________
;;   |              |             |
;;   |  hyperlinks  |  target of  |
;;   |    buffer    |    CODE     |
;;   |              |             |
;;   |______________|_____________|
;;
;; For example,
;;
;;   (find-latex-links "/tmp/foo")
;;
;; generates this hyperlinks buffer:
;;
;;    _________________________________________________________________ 
;;   |# (find-latex-links "/tmp/foo")                                  |
;;   |# (find-latex-links "/tmp/teste1")                               |
;;   |# (find-latex-links "~/2019-CLG/teste2")                         |
;;   |# (find-eev-quick-intro "`find-latex-links'")                    |
;;   |# (ee-copy-rest 1 '(find-fline "/tmp/foo.tex"))                  |
;;   |                                                                 |
;;   |% (defun c () (interactive) (find-sh "pdflatex foo.tex"))        |
;;   |% (defun d () (interactive) (find-pdf-page "/tmp/foo.pdf"))      |
;;   |% (defun e () (interactive) (find-fline "/tmp/foo.tex"))         |
;;   |% (defun w () (interactive) (find-texworks "/tmp/foo.tex"))      |
;;   |%                                                                |
;;   |\documentclass{article}                                          |
;;   |\begin{document}                                                 |
;;   |                                                                 |
;;   |\end{document}                                                   |
;;   |                                                                 |
;;   |                                                                 |
;;   |                                                                 |
;;   | -:**-  *Elisp hyperlinks*   All L1     (Fundamental)  ----------|
;;   |_________________________________________________________________|
;;
;; in which CODE is `(find-fline "/tmp/foo.tex")'. When we execute the
;; `ee-copy-rest' line all the material from "% (defun c..." downwards
;; - the "templated text" - is flashed, copied to the kill ring, the
;; file "/tmp/foo.tex" is opened in the right window, and the
;; following message is displayed in the echo area:
;;
;;   "(Copied 9 lines to the kill ring - use C-y to paste)"
;;
;; If the file "/tmp/foo.tex" is empty and we want to initialize it
;; with the templated string we only need to go to the right window
;; and type `C-y'; if it is non-empty its present contents will be
;; displayed and we can decide what to do.
;;
;; TO DO: update the decumentation here:
;;   (find-eev-quick-intro "7.5. `find-latex-links'")
;;   (find-links-intro "10. The rest of the buffer")

(defvar eeflash-copy '(highlight 0.5))

(defun ee-count-lines (str)
  "Count the number of lines in STR (which should be newline-terminated)."
  (length (replace-regexp-in-string "[^\n]" "" str)))

(defun ee-copy-rest0 (skip code)
  "Copy the rest of this buffer to the kill ring and execute CODE.
The rest of this buffer is everything from the beginning of the next line -
optionally moving down SKIP lines - to the end of the buffer."
  ;; (setq nlines (+ 1 (or nlines 0)))
  (setq skip (or skip 0))
  (let* ((start (save-excursion (move-beginning-of-line (+ 2 skip)) (point)))
	 (end   (point-max))
	 (str   (buffer-substring start end))
	 (len   (ee-count-lines str))
	 (msg   `(Copied ,len lines to the kill ring - use C-y to paste)))
    (eeflash+ start end eeflash-copy)
    (kill-new str)
    (eval code)
    msg))

(defun ee-copy-rest  (skip code)
  "Copy the rest of this buffer to the kill ring and execute CODE.
See: (find-eev \"eev-tlinks.el\" \"ee-copy-rest\")"
  (ee-copy-rest0 skip `(find-2a nil ',code)))


;; Obsolete:
;;
;; (defun ee-copy-after-and (nlines code)
;;   "Copy into the kill ring everything from NLINES down on, and run CODE."
;;   (move-beginning-of-line (- nlines 1))
;;   (kill-new (buffer-substring (point) (point-max)))
;;   (eval code)
;;   (let ((n (ee-count-lines (ee-last-kill))))
;;     `(Copied ,n lines to the kill ring - use C-y to paste)))
;; 
;; (defun ee-copy-after-and-2b (nlines code)
;;   "Copy into the kill ring everything from NLINES down on, and run CODE.
;; The target of the hyperlink in CODE is opened in the right-side window."
;;   (ee-copy-after-and nlines `(find-2b nil ',code)))




;;;   __ _           _       _ _       _       /\ ____  
;;;  / _(_)_ __   __| |     | (_)_ __ | | ____|/\|___ \ 
;;; | |_| | '_ \ / _` |_____| | | '_ \| |/ / __|   __) |
;;; |  _| | | | | (_| |_____| | | | | |   <\__ \  / __/ 
;;; |_| |_|_| |_|\__,_|     |_|_|_| |_|_|\_\___/ |_____|
;;;                                                     
;;
;; «find-find-links-links» (to ".find-find-links-links")
;; See:
;; (find-eev "eev-template.el" "find-find-links-links")
;; (find-find-links-links "u" "find-links" "k stem args")

(defun ee-prepend-commas (str)
  (save-match-data
    (replace-regexp-in-string "\\([^ ]+\\)" ",\\1" str)))
(defun ee-if-nil-setq (str)
  (format "(setq %s (or %s \"{%s}\"))" str str str))
(defun ee-if-nil-setqs (vars sep)
  (mapconcat 'ee-if-nil-setq (save-match-data (ee-split vars)) sep))

(defun find-find-links-links (&optional k stem args &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks for foo."
  (interactive)
  (setq k    (or k    "{k}"))
  (setq stem (or stem "{stem}"))
  (setq args (or args "{args}"))
  (apply 'find-elinks-elisp
   `((find-find-links-links ,k ,stem ,args ,@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-find-links-links)
     ""
     ,(ee-template0 "\
;; See: (find-links-intro)
;;      (find-templates-intro)

;; <find-{stem}-links>
;; {(ee-S `(find-find-links-links ,k ,stem ,args))}
;; A test: (find-{stem}-links ___)
\(define-key eev-mode-map \"\\M-h{k}\" 'find-{stem}-links)

\(defun find-{stem}-links (&optional {args} &rest pos-spec-list)
\"Visit a temporary buffer containing hyperlinks for foo.\"
  (interactive)
  {(ee-if-nil-setqs args \"\n  \")}
  (apply 'find-elinks
   `((find-{stem}-links {(ee-prepend-commas args)} ,@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-{stem}-links)
     \"\"
     ,(ee-template0 \"\\
\")
     )
   pos-spec-list))

;; Test: (find-{stem}-links ___)


;;   ,@(ee-find-{stem}-links {args})
;;
\(defun ee-find-{stem}-links ({args})
  \"Return a list of sexps and strings for {stem}.
This is an internal function used by `find-{stem}-links'.\"
  `(
    ))")
     ) pos-spec-list))



;;;  _       _                   _ _       _        
;;; (_)_ __ | |_ _ __ ___       | (_)_ __ | | _____ 
;;; | | '_ \| __| '__/ _ \ _____| | | '_ \| |/ / __|
;;; | | | | | |_| | | (_) |_____| | | | | |   <\__ \
;;; |_|_| |_|\__|_|  \___/      |_|_|_| |_|_|\_\___/
;;;                                                 
;; «find-intro-links»  (to ".find-intro-links")
;; (find-find-links-links "i" "intro" "stem")
;; A test: (find-intro-links)

(defun find-intro-links (&optional stem &rest pos-spec-list)
"Visit a temporary buffer with a skeleton for defining `find-<STEM>-intro'.
All `find-*-intro' functions in eev-intro.el were written using this.
See: (find-eev \"eev-intro.el\")"
  (interactive)
  (setq stem (or stem "{stem}"))
  (apply 'find-elinks-elisp
   `((find-intro-links ,stem    ,@pos-spec-list)
     (find-intro-links "{stem}" ,@pos-spec-list)
     (find-intro-links "foo"    ,@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-intro-links)
    ,(ee-template0 "\
;; (ee-copy-rest 1 '(find-eev \"eev-intro.el\"))
;; (find-{stem}-intro)

;; <find-{stem}-intro>
;; (find-intro-links \"{stem}\")

\(defun find-{stem}-intro (&rest pos-spec-list) (interactive)
  (let ((ee-buffer-name \"*(find-{stem}-intro)*\"))
    (apply 'find-eintro \"\\
\\(Re)generate: (find-{stem}-intro)
Source code:  (find-efunction 'find-{stem}-intro)
More intros:  (find-eev-quick-intro)
              (find-eval-intro)
              (find-eepitch-intro)
This buffer is _temporary_ and _editable_.
It is meant as both a tutorial and a sandbox.

Hello
=====
\" pos-spec-list)))

;; (find-{stem}-intro)
")) pos-spec-list))

;; (find-intro-links)
;; (find-intro-links "emacs")





;;;            _  __ _ _ _            _       __ 
;;;  _ __   __| |/ _| (_) | _____  __| | ___ / _|
;;; | '_ \ / _` | |_| | | |/ / _ \/ _` |/ _ \ |_ 
;;; | |_) | (_| |  _| | |   <  __/ (_| |  __/  _|
;;; | .__/ \__,_|_| |_|_|_|\_\___|\__,_|\___|_|  
;;; |_|                                          
;;
;; «find-pdflikedef-links» (to ".find-pdflikedef-links")
;; Obsolete! Was used in: (find-eev "eev-pdflike-old.el")
;;   e.g. (find-eev "eev-pdflike-old.el" "defalias 'find-xdvipage")
;; (find-find-links-links "pdflikedef" "stem firstargs")
;;
(defun find-pdflikedef-links (&optional stem firstargs &rest rest)
  "Visit a temporary buffer containing hyperlinks for pdflikedef."
  (interactive)
  (setq stem (or stem "{stem}"))
  (setq firstargs (or firstargs "{firstargs}"))
  (apply 'find-elinks-elisp `(
    ;; Convention: the first sexp always regenerates the buffer.
    (find-pdflikedef-links ,stem ,firstargs ,@rest)
    (find-efunction 'find-pdflikedef-links)
    (emacs-lisp-mode)
    ;; Body:
    ""
    ,(ee-template0 "\
;; (find-efunction 'code-{stem})

;; find-{stem}page
;; find-{stem}-page
;; code-{stem}
;;
\(defalias 'find-{stem}page
          'find-{stem}-page)
\(defun     find-{stem}-page (fname &optional page &rest rest)
  (find-bgprocess (ee-find-{stem}-page fname page)))
\(defvar ee-find-{stem}-page-options '())
\(defun  ee-find-{stem}-page (fname &optional page)
  `(\"{stem}\"
    ,@ee-find-{stem}-page-options
    ,@(if page `(,(format \"--page=%d\" page)))
    ,fname))

\(defun      code-{stem} ({firstargs} &rest rest)
  (eval (ee-read      (apply 'ee-code-{stem} {firstargs} rest))))
\(defun find-code-{stem} ({firstargs} &rest rest)
  (find-estring-elisp (apply 'ee-code-{stem} {firstargs} rest)))
\(defun   ee-code-{stem} ({firstargs} &rest rest)
  (concat (ee-template0 \"\\
\\(defun find-{<}c{>}page (&optional page &rest rest)
  (find-{stem}-page {<}(ee-pp0 fname){>} page))
{<}(ee-code-pdftext-rest rest){>}
\")  (ee-code-pdftext-rest rest)))

\(code-brfile 'find-xpdf-page :local 'brxpdfl :dired 'brxpdfl)


;; Tests:
;; (find-epp (ee-find-{stem}-page \"/tmp/foo.pdf\"))
;; (find-epp (ee-find-{stem}-page \"/tmp/foo.pdf\" 2))
;;           (find-{stem}-page    \"/tmp/foo.pdf\")
;;           (find-{stem}-page    \"/tmp/foo.pdf\" 2)
;;
;;      (find-code-{stem} \"foo\"   \"/tmp/foo.pdf\")
;;           (code-{stem} \"foo\"   \"/tmp/foo.pdf\")
;;                 (find-foopage)
;;                 (find-foopage 2)
;;      (code-pdftotext \"foo\"   \"/tmp/foo.pdf\")
")
    ) rest))

;; (find-pdflikedef-links "djvu" "c fname")
;; (find-efunctionpp 'find-pdflikedef-links)




;;;                       _                    _           
;;;   ___  _____   __    | |__   ___  __ _  __| | ___ _ __ 
;;;  / _ \/ _ \ \ / /____| '_ \ / _ \/ _` |/ _` |/ _ \ '__|
;;; |  __/  __/\ V /_____| | | |  __/ (_| | (_| |  __/ |   
;;;  \___|\___| \_/      |_| |_|\___|\__,_|\__,_|\___|_|   
;;;                                                        
;; «find-eev-header-links» (to ".find-eev-header-links")
;; (find-find-links-links "<none>" "eev-header" "stem-el date")
;; A test: (find-eev-header-links "eev-audiovideo.el")

(defun find-eev-header-links (&optional stem-el date &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks for foo."
  (interactive)
  (setq stem-el (or stem-el "{stem-el}"))
  (setq date    (or date (downcase (format-time-string "%Y%b%d"))))
  (apply 'find-elinks-elisp
   `((find-eev-header-links ,stem-el ,date ,@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-eev-header-links)
     (find-eev ,stem-el)
     (wrobak 2 '(find-eev ,stem-el))
     ,(ee-template0 "
;;; {stem-el} -- ???.

;; Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
;;
;; Author:     Eduardo Ochs <eduardoochs@gmail.com>
;; Maintainer: Eduardo Ochs <eduardoochs@gmail.com>
;; Version:    {date}
;; Keywords:   e-scripts
;;
;; Latest version: <http://angg.twu.net/eev-current/{stem-el}>
;;       htmlized: <http://angg.twu.net/eev-current/{stem-el}.html>
;;       See also: <http://angg.twu.net/eev-current/eev-readme.el.html>
;;                 <http://angg.twu.net/eev-intros/find-eev-intro.html>
;;                                                (find-eev-intro)

;;; Commentary:


;; Local Variables:
;; coding:            utf-8-unix
;; ee-anchor-format:  \"defun %s \"
;; no-byte-compile:   t
;; End:
")) pos-spec-list))




;;;   __ _           _           _      _           _         
;;;  / _(_)_ __   __| |       __| | ___| |__  _ __ | | ____ _ 
;;; | |_| | '_ \ / _` |_____ / _` |/ _ \ '_ \| '_ \| |/ / _` |
;;; |  _| | | | | (_| |_____| (_| |  __/ |_) | |_) |   < (_| |
;;; |_| |_|_| |_|\__,_|      \__,_|\___|_.__/| .__/|_|\_\__, |
;;;                                          |_|        |___/ 
;;
;; «find-debpkg-links»  (to ".find-debpkg-links")

(defun ee-links-for-debpkg (pkgname)
  "Return the three main links for the debian package PKGNAME."
  (list (ee-template0 "\
{ee-H}(find-status   \"{pkgname}\")
{ee-H}(find-vldifile \"{pkgname}.list\")
{ee-H}(find-udfile   \"{pkgname}/\")")))

(defun ee-dfs0 (pkg ext)
  "If the file /var/lib/dpkg/info/PKG.EXT exists, return a link to it."
  (let ((fname (concat pkg "." ext)))
    (if (file-exists-p (ee-vldifile fname))
	`(find-vldifile ,fname))))

(defun ee-links-for-debpkg-extra-vldi (pkg)
  "Return a list of links for files in /var/lib/dpkg/info/ belonging to PKG.
This is an internal function used by `find-debpkg-links'."
   (list (ee-dfs0 pkg "preinst")   (ee-dfs0 pkg "postinst")
	 (ee-dfs0 pkg "prerm")     (ee-dfs0 pkg "postrm")
	 (ee-dfs0 pkg "conffiles") (ee-dfs0 pkg "config")
	 (ee-dfs0 pkg "templates")
	 (ee-dfs0 pkg "md5sums")   (ee-dfs0 pkg "shlibs")
	 ))

(defun ee-debian-pooldir (pkg)
  "Used by `find-debpkg-links'; \"foo\" -> \"f\", \"libfoo\" -> \"libf\"."
  (if (string-match "^\\(lib\\)?." pkgname)
      (match-string 0 pkgname)))

(defun find-debpkg-links (&optional pkgname &rest rest)
  "Visit a temporary buffer containing hyperlinks related to a Debian package.
Try this: (find-debpkg-links \"bash\")"
  (interactive (list (ee-debpkgname-ask)))
  (setq pkgname (or pkgname "{pkgname}"))
  (let ((p (ee-debian-pooldir pkgname)))
    (apply 'find-elinks `(
      ;; Convention: the first sexp always regenerates the buffer.
      (find-debpkg-links ,pkgname ,@rest)
      (find-available ,pkgname)
      ""
      ,@(ee-links-for-debpkg pkgname)
      ""
      ,@(ee-links-for-debpkg-extra-vldi pkgname)
      ""
      ,(ee-template0 "\
{ee-H}(find-sh \"apt-file search {pkgname}\")
{ee-H}(find-sh \"apt-cache dump | grep-dctrl -P {pkgname}\")
{ee-H}(find-sh \"apt-cache search {pkgname} | sort\")
{ee-H}(find-sh \"apt-cache showpkg {pkgname}\")
{ee-H}(find-sh \"grep-aptavail -P {pkgname}\")

http://packages.debian.org/{pkgname}
http://packages.debian.org/sid/{pkgname}
http://packages.debian.org/source/sid/{pkgname}
http://packages.debian.org/src:{pkgname}
http://ftp.debian.org/debian/pool/main/{p}/{pkgname}/
http://backports.org/debian/pool/main/{p}/{pkgname}/
http://bugs.debian.org/cgi-bin/pkgreport.cgi?which=pkg&data={pkgname}&archive=no

http://packages.ubuntu.org/{pkgname}

 (eepitch-shell2)
sudo apt-get install    {pkgname}
sudo apt-get install -y {pkgname}

 (eepitch-shell)
 (eepitch-kill)
 (eepitch-shell)
# (find-man \"8 apt-cache\")
apt-cache show {pkgname}
apt-cache search {pkgname}
apt-cache depends {pkgname}
apt-cache rdepends {pkgname}

apt-cache showpkg {pkgname}

# (find-man \"1 dpkg-query\")
apt-file search {pkgname}
dpkg-query --search {pkgname}
")
      ) rest)))



;;;   __ _           _           _          _           _ _     _ 
;;;  / _(_)_ __   __| |       __| |___  ___| |__  _   _(_) | __| |
;;; | |_| | '_ \ / _` |_____ / _` / __|/ __| '_ \| | | | | |/ _` |
;;; |  _| | | | | (_| |_____| (_| \__ \ (__| |_) | |_| | | | (_| |
;;; |_| |_|_| |_|\__,_|      \__,_|___/\___|_.__/ \__,_|_|_|\__,_|
;;;                                                               
;; This is a VERY EARLY prototype (hi Marc!)
;; of a rewrite of something that was very ugly.

;; (find-angg ".emacs" "find-dpkg-build-escript")

(defun ee-dsc-url-split (dsc-url)
  "Example:
  (ee-dsc-url-split
   \"http://ftp.debian.org/debian/pool/main/i/imagemagick/imagemagick_6.2.4.5.dfsg1-0.9.dsc\")
  -> (\"http\" \"ftp.debian.org/debian/pool/main/i/imagemagick/\"
      \"imagemagick\" \"6.2.4.5.dfsg1\" \"-0.9\")"
  (let ((prot://dir/ (file-name-directory dsc-url))
	(fname-dsc (file-name-nondirectory dsc-url))
	prot dir/ xxx vvv -sv)
    (if (string-match "^\\([a-z]+\\)://\\(.*\\)" prot://dir/)
	(setq prot (match-string 1 prot://dir/)
	      dir/ (match-string 2 prot://dir/)))
    (if (string-match "^\\([^_]+\\)_\\([^-]+\\)\\(-.*\\)?\\.dsc$" fname-dsc)
	(setq xxx (match-string 1 fname-dsc)
	      vvv (match-string 2 fname-dsc)
	      -sv (or (match-string 3 fname-dsc) "")))
    (list prot dir/ xxx vvv -sv)))

(defun ee-links-for-dscbuild (dsc-url)
  (apply 'ee-links-for-dscbuild0
	 (downcase (format-time-string "%Y%b%d"))
	 (ee-dsc-url-split dsc-url)))

(defun ee-links-for-dscbuild0 (date prot dir/ xxx vvv -sv)
  (ee-template
   '(date prot dir/ xxx vvv -sv) "\
#####
#
# {xxx} (from the debian sources)
# {date}
#
#####

# <{xxx}-deb-src>
# {prot}://{dir/}
# {prot}://{dir/}{xxx}_{vvv}{-sv}.dsc
# {prot}://{dir/}{xxx}_{vvv}{-sv}.diff.gz
# {prot}://{dir/}{xxx}_{vvv}.orig.tar.gz
#
rm -Rv ~/usrc/{xxx}/
mkdir  ~/usrc/{xxx}/
cd $S/{prot}/{dir/}
cp -v {xxx}_{vvv}* ~/usrc/{xxx}/
cd     ~/usrc/{xxx}/
dpkg-source -sn -x {xxx}_{vvv}{-sv}.dsc
cd     ~/usrc/{xxx}/{xxx}-{vvv}/
dpkg-buildpackage -us -uc -b -rfakeroot     2>&1 | tee odb

#
# (find-fline \"~/usrc/{xxx}/\")
 (eepitch-shell)
cd ~/usrc/{xxx}/
sudo dpkg -i *.deb

#
# (code-c-d \"{xxx}\" \"~/usrc/{xxx}/{xxx}-{vvv}/\")
# (find-{xxx}file \"\")"))



;;;                       _           _        _ _ 
;;;   ___  _____   __    (_)_ __  ___| |_ __ _| | |
;;;  / _ \/ _ \ \ / /____| | '_ \/ __| __/ _` | | |
;;; |  __/  __/\ V /_____| | | | \__ \ || (_| | | |
;;;  \___|\___| \_/      |_|_| |_|___/\__\__,_|_|_|
;;;                                                

;; «find-eev-install-links» (to ".find-eev-install-links")
;; (find-find-links-links "{k}" "eev-install" "dir script comment")
;; A test: (find-eev-install-links)

(defun find-eev-install-links (&optional dir script comment &rest pos-spec-list)
"Visit a temporary buffer containing an e-script for installing eev."
  (interactive)
  (setq dir (or dir "~/eev2/"))
  (setq script (or script "~/eev"))
  (setq comment (or comment ""))
  (apply 'find-elinks
   `((find-eev-install-links ,dir ,script ,comment ,@pos-spec-list)
     (find-eev-install-links "~/eev2/" "~/eev")
     (find-eev-install-links "~/eev2/" "~/eev" "#")
     (find-eev-install-links "/tmp/eev2/" "/tmp/eev")
     (find-eev-install-links "/tmp/eev2/" "/tmp/eev" "#")
     (find-eev-install-links "{dir}" "{script}" "{comment}")
     (find-eev-install-links)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-eev-install-links)
     ""
     (find-eev-install-intro)
     ""
     ,(ee-template0 "\
# This function is explained at:
#   (find-eev-install-intro \"2. Running `(find-eev-install-links)'\")
#
# The default way to use it to install eev in your home directory is with:
#   (find-eev-install-links \"~/eev2/\" \"~/eev\" \"#\")
#
# The default way to use it to install eev in /tmp/ for tests is with:
#   (find-eev-install-links \"/tmp/eev2/\" \"/tmp/eev\" \"#\")



# The script below downloads eev2.tgz and unpacks it into {dir}
# and creates a shell script {script}
# that can be used to start emacs+eev.

 (eepitch-shell)
 (eepitch-kill)
 (eepitch-shell)
{comment}{<}
  rm -Rv {script}
  rm -Rv {dir}
  mkdir  {dir}
  cd     {dir}
  rm -fv eev2.tgz
  wget http://angg.twu.net/eev-current/eev2.tgz
  tar -xvzf eev2.tgz
  {<}
    echo '#!/bin/sh'
    echo 'cd {dir} && emacs -l eev-beginner.el --eval=\"(find-eev-quick-intro)\" $*'
  {>} > {script}
  chmod 755 {script}
{comment}{>}

# Test:
{script}



;; If you have unpacked eev2.tgz into some permanent place you can
;; put this is your .emacs to load eev when Emacs starts. Don't
;; copy this to your .emacs if either 1) you have only unpacked
;; eev in /tmp/, or 2) if you don't know how to use Lisp well
;; enough!
;;
;; See: (find-eev-install-intro \"3. Changing your .emacs\")

;; (ee-copy-rest 0 '(find-fline \"~/.emacs\"))

;; Load eev.
;; Generated by: (find-eev-install-links \"{dir}\" \"{script}\" \"{comment}\")
;;        Check: (find-fline \"{dir}\")
;;          See: (find-eev-install-intro \"3. Changing your .emacs\")
;;
\(add-to-list 'load-path \"{dir}\")
\(require 'eev-load)                 ; (find-eev \"eev-load.el\")
\(eev-mode 1)                        ; (find-eev \"eev-mode.el\")

")
     )
   pos-spec-list))

;; A test: (find-eev-install-links)
;;         (find-eev-install-links "~/eev2/" "~/eev" "#" 60)


;;;                                       _       _       
;;;   ___  _____   __     _   _ _ __   __| | __ _| |_ ___ 
;;;  / _ \/ _ \ \ / /____| | | | '_ \ / _` |/ _` | __/ _ \
;;; |  __/  __/\ V /_____| |_| | |_) | (_| | (_| | ||  __/
;;;  \___|\___| \_/       \__,_| .__/ \__,_|\__,_|\__\___|
;;;                            |_|                        
;;
;; «find-eev-update-links» (to ".find-eev-update-links")
;; A test: (find-eev-update-links)
;; TODO: Check that this has been superseded by
;;   (find-eev-install-links)
;; and flag this as obsolete.

(defun find-eev-update-links (&optional dir script &rest pos-spec-list)
"Visit a temporary buffer with scripts for installing and updating eev."
  (interactive)
  (setq dir (or dir ee-eevdir))
  (setq script (or script "~/e"))
  (apply 'find-elinks
   `((find-eev-update-links ,dir ,script)
     (find-eev-update-links "/tmp/eev/" ,script)
     (find-eev-update-links "~/eev2/" ,script)
     (find-eev-update-links "~/eev/" ,script)
     (find-eev-update-links "{dir}" "{script}")
     (find-eev-update-links)
     ,(ee-template0 "\

# NOTE! This function is obsolete and has been superseded by:
# (find-eev-install-links)



# Download , unpack and create a script \"~/e\"
# ============================================
# See: (find-eev-quick-intro \"1. Installing eev\")

{
  rm -Rv {dir}
  mkdir  {dir}
  cd     {dir}
  rm -v eev2.tgz
  wget http://angg.twu.net/eev-current/eev2.tgz
  tar -xvzf eev2.tgz
  {
    echo '#!/bin/sh'
    echo 'cd {dir} && emacs -l eev-readme.el --eval=\"(find-eev-quick-intro)\"'
  } > {script}
  chmod 755 {script}
}



# Download / unpack the tarball (an older way)
# ============================================
# See: (find-eepitch-intro)
#      (find-eev \"eev-readme.el\")

 (eepitch-shell)
 (eepitch-kill)
 (eepitch-shell)
#rm -Rv {dir}
mkdir   {dir}
cd      {dir}
rm -v eev2.tgz
wget http://angg.twu.net/eev-current/eev2.tgz
tar -xvzf eev2.tgz

# Tests:
emacs -Q -fg bisque -bg black -l eev-readme.el eev-readme.el
emacs -Q -fg bisque -bg black                  eev-readme.el
emacs    -fg bisque -bg black                  eev-readme.el



# Tell Emacs to load eev2 by default
# ==================================
# Emacs executes the file ~/.emacs when it starts up - see:
#   (find-enode \"Init File\")
# The easiest way to make Emacs load eev2 by default is to
# open your ~/.emacs in another window with the sexp below,
# and then copy the block below to it with `C-y'.
#   (ee-copy-rest 0 '(find-fline \"~/.emacs\"))

;; Load eev2.
;; See:  (find-file \"{dir}\")
;;       (find-file \"{dir}eev-readme.el\")
;; Generated by: (find-eev-update-links \"{dir}\")
;;
\(add-to-list 'load-path \"{dir}\")
\(require 'eev2-all)                 ; (find-eev \"eev2-all.el\")
\(eev-mode 1)                        ; (find-eev \"eev-mode.el\")
")) pos-spec-list))

;; (find-eev-update-links)




;;;                    _         _                    _ _ 
;;;  _   _  ___  _   _| |_ _   _| |__   ___        __| | |
;;; | | | |/ _ \| | | | __| | | | '_ \ / _ \_____ / _` | |
;;; | |_| | (_) | |_| | |_| |_| | |_) |  __/_____| (_| | |
;;;  \__, |\___/ \__,_|\__|\__,_|_.__/ \___|      \__,_|_|
;;;  |___/                                                
;;
;; «find-youtubedl-links»  (to ".find-youtubedl-links")

;; Code for splitting filenames of downloaded videos into components.
;;
(defvar ee-youtubedl-ext-re
  "\\(\\.[A-Za-z0-9]\\{2,5\\}\\)\\{0,2\\}$")

(setq ee-youtubedl-ext-re
  "\\(\\.[A-Za-z0-9]\\{2,5\\}\\)\\(\\.part\\)?$")

(defun ee-youtubedl-split (fname)
"Split FNAME into (dir title hash ext).
Example:
\(ee-youtubedl-split \"~/tmp/videos/foo_bar-abF7go7RLTc.flv\")
   --> (\"~/tmp/videos/\" \"foo_bar\" \"abF7go7RLTc\" \".flv\")"
  (string-match ee-youtubedl-ext-re fname)
  (let (dir title hash ext- ext dth dt)
    (setq ext-  (match-string 1 fname))
    (setq ext   (match-string 0 fname))
    (setq dth   (substring fname 0 (match-beginning 0)))
    (setq hash  (substring dth -11))
    (setq dt    (substring dth 0 -12))
    (setq title (file-name-nondirectory dt))
    (setq dir   (file-name-directory dt))
    (list dir title hash ext- ext)))

(defun ee-youtubedl-dir   (fname) (nth 0 (ee-youtubedl-split fname)))
(defun ee-youtubedl-title (fname) (nth 1 (ee-youtubedl-split fname)))
(defun ee-youtubedl-hash  (fname) (nth 2 (ee-youtubedl-split fname)))
(defun ee-youtubedl-ext-  (fname) (nth 3 (ee-youtubedl-split fname)))
(defun ee-youtubedl-ext   (fname) (nth 4 (ee-youtubedl-split fname)))

;; Code for guessing the "title" and the "ext" parts of a video from
;; the "dir" and "hash" parts (in case the video has already been
;; downloaded).
;;
(defun ee-youtubedl-guess* (dir hash)
  "Return all the files in DIR containing the string HASH."
  (file-expand-wildcards (format "%s*%s*" dir hash)))

(defun ee-youtubedl-guess (dir hash n)
  "Return a component of the first file in DIR containing the string HASH."
  (let ((fname (car (ee-youtubedl-guess* dir hash))))
    (if fname (nth n (ee-youtubedl-split fname)))))

(defun ee-youtubedl-guess-title (dir hash) (ee-youtubedl-guess dir hash 1))
(defun ee-youtubedl-guess-ext-  (dir hash) (ee-youtubedl-guess dir hash 3))

;; The function `find-youtubedl-links' itself.
;; It will try to guess "dir", "title", "hash", and "ext" if they are nil.
;; Its ancestor: (find-angg ".emacs.templates" "find-youtubedl-links")
;;
(defvar ee-youtubedl-dir     "~/videos/")
(defvar ee-youtubedl-dir2    "~/videos/tech/")
(defvar ee-youtubedl-dir3    "/tmp/videos/")
(defvar ee-youtubedl-dir4    "/tmp/")
(defvar ee-youtubedl-command "youtube-dl -t")

(defun ee-youtubedl-hash-around-point ()
  (let ((hash (ee-stuff-around-point "-0-9A-Za-z_")))
    (if (>= (length hash) 11)
	(substring hash -11))))

;; Test: (find-youtubedl-links nil nil "K6LmZ0A1s9U")
;;
(defun find-youtubedl-links (&optional dir title hash ext- stem &rest rest)
  "Visit a temporary buffer containing hyperlinks for youtube-dl."
  (interactive)
  (setq dir   (or dir   ee-youtubedl-dir "{dir}"))
  (setq hash  (or hash  (ee-youtubedl-hash-around-point)    "{hash}"))
  (setq title (or title (ee-youtubedl-guess-title dir hash) "{title}"))
  (setq ext-   (or ext-   (ee-youtubedl-guess-ext-   dir hash) "{ext-}"))
  (setq stem  (or stem "{stem}"))
  (apply 'find-elinks `(
    ;; Convention: the first sexp always regenerates the buffer.
    (find-youtubedl-links ,dir ,title ,hash ,ext- ,stem)
    (find-youtubedl-links ,dir nil ,hash nil ,stem)
    ""
    (find-youtubedl-links ,ee-youtubedl-dir  nil ,hash nil ,stem)
    (find-youtubedl-links ,ee-youtubedl-dir2 nil ,hash nil ,stem)
    (find-youtubedl-links ,ee-youtubedl-dir3 nil ,hash nil ,stem)
    (find-youtubedl-links ,ee-youtubedl-dir4 nil ,hash nil ,stem)
    (find-efunction 'find-youtubedl-links)
    ;;
    ;; (find-youtubedl-links ee-youtubedl-dir ,title ,hash ,ext- ,stem)
    ;; (setq ee-youtubedl-dir ,ee-youtubedl-dir)
    ""
    (find-ydbgrep ,(format "grep --color -nH -e %s db.lua" hash))
    ;;
    ;; Body:
    ""
    ,(ee-template0 "\
 (eepitch-shell2)
 (eepitch-kill)
 (eepitch-shell2)
# http://www.youtube.com/watch?v={hash}
# http://www.youtube.com/watch?v={hash}#t=0m00s
# http://www.youtube.com/watch?v={hash}#t=0h00m00s
cd {dir}
{ee-youtubedl-command} -f 18 --restrict-filenames 'http://www.youtube.com/watch?v={hash}'

# Or:
{ee-youtubedl-command}       'http://www.youtube.com/watch?v={hash}'
{ee-youtubedl-command} -F    'http://www.youtube.com/watch?v={hash}'
{ee-youtubedl-command} -f 18 'http://www.youtube.com/watch?v={hash}'
{ee-youtubedl-command} -f 18 --restrict-filenames --all-subs 'http://www.youtube.com/watch?v={hash}'

# (find-es \"video\" \"youtube-dl\")
# (find-fline \"{dir}\" \"{hash}\")
# (find-fline \"{dir}\" \"{title}-{hash}\")
# (find-fline \"{dir}\" \"{title}-{hash}{ext-}\")
# (find-video \"{dir}{title}-{hash}{ext-}\")
# (find-video \"{dir}{title}-{hash}{ext-}.part\")
# (code-video \"{stem}video\" \"{dir}{title}-{hash}{ext-}\")
# (code-video \"{stem}video\" \"{dir}{title}-{hash}{ext-}.part\")
# (find-{stem}video)
# (find-{stem}video \"0:00\")

# Error messages (for the player):
# (find-ebuffer \"*Messages*\")
")
    ) rest))


;; Bonus (2013sep10): play a local copy of a video from its URL.
;; I need to document this!
;;
(defun ee-youtubedl-guess** (dirs hash)
  (apply 'append (mapcar (lambda (d) (ee-youtubedl-guess* d hash)) dirs)))

(defun ee-youtubedl-dirs ()
  (list ee-youtubedl-dir
	ee-youtubedl-dir2
	ee-youtubedl-dir3
	ee-youtubedl-dir4))

(defun ee-youtubedl-hash-to-fname (hash)
  (and hash (car (ee-youtubedl-guess** (ee-youtubedl-dirs) hash))))

(defun ee-youtubedl-url-to-hash (url)
  (if (and url (string-match "[&?]v=\\([^&?#]+\\)" url))
      (match-string 1 url)
    url))

(defun ee-youtubedl-url-to-fname (url)
  (ee-youtubedl-hash-to-fname
   (ee-youtubedl-url-to-hash url)))

(autoload 'browse-url-url-at-point "browse-url")

(defun bryl (url)
  "Play a local copy of a video downloaded from youtube."
  (interactive (list (browse-url-url-at-point)))
  (let ((fname (and url (ee-youtubedl-url-to-fname url))))
    (if fname (find-video fname))))





;;;                       
;;;  _ __  ___ _ __   ___ 
;;; | '_ \/ __| '_ \ / _ \
;;; | |_) \__ \ | | |  __/
;;; | .__/|___/_| |_|\___|
;;; |_|                   
;;
;; «find-psne-links» (to ".find-psne-links")
;; (find-find-links-links "<none>" "psne" "url wget-options")
;; A test: (find-psne-links "http://foo/bar")

(defun find-psne-links (&optional url wget-options &rest pos-spec-list)
"See: (find-psne-intro)"
  (interactive)
  (setq url (or url "{url}"))
  (setq wget-options (or wget-options ""))
  (apply 'find-elinks
   `((find-psne-links ,url ,wget-options ,@pos-spec-list)
     (find-psne-links ,url "-c" ,@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-psne-links)
     ""
     " (eepitch-shell2)"
     ,(ee-find-psne-core url wget-options)
     )
   pos-spec-list))

(defun ee-find-psne-core (url &optional wget-options)
  "This is an internal function used by `find-psne-links'."
  (let* ((localurl (ee-url-to-fname0 url))
	 (localdir (file-name-directory localurl))
	 (o (format "%3s" (or wget-options ""))))
    (ee-template0 "\
mkdir -p {localdir}
cd       {localdir}
wget {o} '{url}'
echo     '{url}' >> ~/.psne.log

# (find-fline \"{localdir}\")
# (find-fline \"{localurl}\")
")))

;; Links to the old version:
;; (find-eev "eev-browse-url.el" "find-psne-links")
;; (find-eev "eev-browse-url.el" "brep")





;;;        _ _   
;;;   __ _(_) |_ 
;;;  / _` | | __|
;;; | (_| | | |_ 
;;;  \__, |_|\__|
;;;  |___/       

;; «find-git-links» (to ".find-git-links")
;; (find-find-links-links "g" "git" "usrc/ git/ gitname")
;; (find-find-links-links "g" "git" "url c")
(define-key eev-mode-map "\M-hg" 'find-git-links-1)
(define-key eev-mode-map "\M-hg" 'find-git-links)

(defun ee-git-url-stem (url)
  (replace-regexp-in-string "^\\(.*/\\)\\([^/]+?\\)\\(\\.git\\)?$" "\\2" url))

(defun ee-git-url-at-point ()
  (require 'thingatpt)
  (let ((thing-at-point-url-regexp
	 (concat "\\<\\(https?:\\|git:\\)"
		 thing-at-point-url-path-regexp)))
    (thing-at-point 'url)))

(setq ee-git-dir "~/usrc/") ;; Used by find-git-links

(defun find-git-links (&optional url c &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks for foo."
  (interactive)
  (let (gitstem dir)
    (setq url (or url (ee-git-url-at-point) "{url}"))
    (setq gitstem (or gitstem (ee-git-url-stem url)))
    (setq c (or c (replace-regexp-in-string "\\." "" gitstem)))
    (setq dir (format "%s%s/" ee-git-dir gitstem))
    (apply 'find-elinks
     `((find-git-links ,url ,c)
       ;; Convention: the first sexp always regenerates the buffer.
       (find-efunction 'find-git-links)
       ""
       (setq ee-git-dir ,ee-git-dir)
       (setq ee-git-dir "~/usrc/")
       (setq ee-git-dir "~/bigsrc/")
       (setq ee-git-dir "/tmp/")
       ""
       (find-fline ,ee-git-dir)
       (find-fline ,dir)
       ""
       ,(ee-template0 "\
# {url}

 (eepitch-shell)
 (eepitch-kill)
 (eepitch-shell)
# rm -Rfv {dir}
cd      {ee-git-dir}
git clone {url}
cd      {dir}

git branch --list -a
git for-each-ref
PAGER=cat git log --oneline --graph --all -20

# (find-fline \"{ee-git-dir}\")
# (find-fline \"{dir}\")
# (find-gitk  \"{dir}\")

# (code-c-d \"{c}\" \"{dir}\")
# (find-{c}file \"\")

# git pull --depth 1
# git pull
# git reset
# git clean -dfx
# git reset --hard
")
     )
   pos-spec-list)))

;; Test:
;; (find-git-links "https://github.com/kikito/inspect.lua" "inspectlua")



;;;              _                   _                                     
;;;   __ _ _ __ | |_       __ _  ___| |_      ___  ___  _   _ _ __ ___ ___ 
;;;  / _` | '_ \| __|____ / _` |/ _ \ __|____/ __|/ _ \| | | | '__/ __/ _ \
;;; | (_| | |_) | ||_____| (_| |  __/ ||_____\__ \ (_) | |_| | | | (_|  __/
;;;  \__,_| .__/ \__|     \__, |\___|\__|    |___/\___/ \__,_|_|  \___\___|
;;;       |_|             |___/                                            
;;
;; «find-apt-get-source-links»  (to ".find-apt-get-source-links")
;; (find-find-links-links "{k}" "apt-get-source" "pkg")
;; A test: (find-apt-get-source-links)

(defun find-apt-get-source-links (&optional pkg &rest pos-spec-list)
"Visit a temporary buffer containing a script for apt-get source."
  (interactive)
  (setq pkg (or pkg "{pkg}"))
  (let ((letter (replace-regexp-in-string "^\\(\\(lib\\)?.\\).*" "\\1" pkg)))
    (apply 'find-elinks
     `((find-apt-get-source-links ,pkg ,@pos-spec-list)
       (find-apt-get-source-links "lua5.1")
       ;; Convention: the first sexp always regenerates the buffer.
       (find-efunction 'find-apt-get-source-links)
       ""
       ,(ee-template0 "\
# https://packages.debian.org/search?searchon=sourcenames&keywords={pkg}
# https://packages.debian.org/source/sid/{pkg}
# http://deb.debian.org/debian/pool/main/{letter}/{pkg}/

 (eepitch-shell)
 (eepitch-kill)
 (eepitch-shell)
# (find-sh \"apt-cache show    {pkg}\")
# (find-sh \"apt-cache showsrc {pkg}\")
rm -Rv /tmp/d/
mkdir  /tmp/d/
cd     /tmp/d/
sudo apt-get build-dep -y   {pkg}
     apt-get source         {pkg}   2>&1 | tee osource
     apt-get source --build {pkg}   2>&1 | tee osourceb

# (find-fline \"/tmp/d/\")

")
       )
     pos-spec-list)))

;; Test: (find-apt-get-source-links)






;;;             _            _        _            _   
;;;  _ __   ___| |_ ___ __ _| |_     | |_ ___  ___| |_ 
;;; | '_ \ / _ \ __/ __/ _` | __|____| __/ _ \/ __| __|
;;; | | | |  __/ || (_| (_| | ||_____| ||  __/\__ \ |_ 
;;; |_| |_|\___|\__\___\__,_|\__|     \__\___||___/\__|
;;;                                                    

;; «find-netcat-test-links» (to ".find-netcat-test-links")
;; (find-find-links-links "{k}" "netcat-test" "eesrc eetgt tgtname tgtport")
;; A test: (find-netcat-test-links)

(defun find-netcat-test-links (&optional eesrc eetgt tgtname tgtport &rest pos-spec-list)
"Visit a temporary buffer with a script to test sending data though netcat."
  (interactive)
  (setq eesrc (or eesrc "{eesrc}"))
  (setq eetgt (or eetgt "{eetgt}"))
  (setq tgtname (or tgtname "{tgtname}"))
  (setq tgtport (or tgtport "{tgtport}"))
  (apply 'find-elinks
   `((find-netcat-test-links ,eesrc ,eetgt ,tgtname ,tgtport)
     (find-netcat-test-links "shell" "shell2" "localhost" "1234")
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-netcat-test-links)
     ""
     ,(ee-template0 "\
 (find-3EE '(eepitch-{eesrc}) '(eepitch-{eetgt}))
 (find-3ee '(eepitch-{eesrc}) '(eepitch-{eetgt}))
 (eepitch-{eetgt})
# listen on port {tgtport}
netcat -l -p {tgtport}

 (eepitch-{eesrc})
# Send things to port {tgtport} (on {tgtname})
{<}
  echo hi
  sleep 1
  echo bye
  sleep 1
{>} | netcat -q 0 {tgtname} {tgtport}

")
     )
   pos-spec-list))

;; Test: (find-netcat-test-links)






;;;                            _     _            
;;;   ___  _____   __   __   _(_) __| | ___  ___  
;;;  / _ \/ _ \ \ / /___\ \ / / |/ _` |/ _ \/ _ \ 
;;; |  __/  __/\ V /_____\ V /| | (_| |  __/ (_) |
;;;  \___|\___| \_/       \_/ |_|\__,_|\___|\___/ 
;;;                                               
;; «find-eev-video-links» (to ".find-eev-video-links")

;; (find-find-links-links "{k}" "eev-video" "c anggstem youtubehash")

(defun find-eev-video-links (&optional c anggstem youtubehash &rest pos-spec-list)
"Visit a temporary buffer containing a script for downloading an eev video.
See: (find-videos-intro)
Examples:
  (find-eev-video-links \"eepitchvideo\" \"video4-eepitch\" \"Lj_zKC5BR64\")
  (find-eev-video-links \"eevvideo2\"    \"video2\"         \"doeyn5MOaB8\")
  (find-eev-video-links \"eevvideo2-pt\" \"video2pt\"       \"yztYD9Y7Iz4\")
Warning: the last one is in Portuguese..."
  (interactive)
  (setq c (or c "{c}"))
  (setq anggstem (or anggstem "{anggstem}"))
  (setq youtubehash (or youtubehash "{youtubehash}"))
  (let ((s (replace-regexp-in-string "." " " c)))
    (apply 'find-elinks
     `((find-eev-video-links ,c ,anggstem ,youtubehash)
       ;; Convention: the first sexp always regenerates the buffer.
       (find-efunction 'find-eev-video-links)
       ""
       ,(ee-template0 "\
 Download (or make sure we have) a local copy of the video:
 (eepitch-shell2)
 (eepitch-kill)
 (eepitch-shell2)
mkdir -p $S/http/angg.twu.net/eev-videos/
cd       $S/http/angg.twu.net/eev-videos/
wget  -c 'http://angg.twu.net/eev-videos/{anggstem}.mp4'
echo     'http://angg.twu.net/eev-videos/{anggstem}.mp4' >> ~/.psne.log

# Test:
# (find-fline  {s}  \"$S/http/angg.twu.net/eev-videos/\")
# (find-video  {s}  \"$S/http/angg.twu.net/eev-videos/{anggstem}.mp4\")
# (code-video \"{c}\" \"$S/http/angg.twu.net/eev-videos/{anggstem}.mp4\")
# (find-{c})
# Error messages:
# (find-ebuffer \"*Messages*\")

# See: (find-audiovideo-intro \"eev-avadj-mode\")
#      (find-audiovideo-intro \"The time-from-bol\")
# (eev-avadj-mode 1)
# (find-{c} t)
# 0:00

# Links to the version at youtube:
# http://www.youtube.com/watch?v={youtubehash}
# http://www.youtube.com/watch?v={youtubehash}&t=0m00s
# http://www.youtube.com/watch?v={youtubehash}&t=0h00m00s
")
       )
     pos-spec-list)))

;; Links to all the eev videos (best ones first):
;;   (find-eev-video-links "eepitchvideo" "video4-eepitch" "Lj_zKC5BR64")
;;   (find-eev-video-links "eevvideo2"    "video2"         "doeyn5MOaB8")
;;   (find-eev-video-links "eevvideo2-pt" "video2pt"       "yztYD9Y7Iz4")
;; The ones with "pt" are in Portuguese, the other ones are in English.

;; (find-eepitchvideo "0:18" "Demonstration (first time, very quickly)")




;;;   __ _           _       _       _                 _ _       _        
;;;  / _(_)_ __   __| |     | | __ _| |_ _____  __    | (_)_ __ | | _____ 
;;; | |_| | '_ \ / _` |_____| |/ _` | __/ _ \ \/ /____| | | '_ \| |/ / __|
;;; |  _| | | | | (_| |_____| | (_| | ||  __/>  <_____| | | | | |   <\__ \
;;; |_| |_|_| |_|\__,_|     |_|\__,_|\__\___/_/\_\    |_|_|_| |_|_|\_\___/
;;;                                                                       
;; «find-latex-links» (to ".find-latex-links")
;; See:
;;   (find-eev-quick-intro "7.5. `find-latex-links'")

(defun find-latex-links (&optional stem &rest pos-spec-list)
"Visit a temporary buffer containing a template for creating a LaTeX document."
  (interactive)
  (setq stem (or stem "{stem}"))
  (let ((stem- (file-name-nondirectory stem)))
    (apply 'find-elinks
     `((find-latex-links ,stem ,@pos-spec-list)
       (find-latex-links "/tmp/test")
       ;; Convention: the first sexp always regenerates the buffer.
       ;; (find-efunction 'find-latex-links)
       (find-eev-quick-intro "7.5. `find-latex-links'")
       (find-eev-quick-intro "7.5. `find-latex-links'" "change the \"{stem}\"")
       (find-eev-quick-intro "7.5. `find-latex-links'" "top line")
       (find-eev-quick-intro "7.5. `find-latex-links'" "(ee-copy-rest ...)")
       (find-eev-quick-intro "7.5. `find-latex-links'" "`C-y'")
       (find-eev-quick-intro "7.5. `find-latex-links'" "save the file foo.tex")
       (find-eev-quick-intro "7.5. `find-latex-links'" "execute the three defuns")
       ""
       (ee-copy-rest 1 '(find-fline ,(concat stem ".tex")))
       ""
       ,(ee-template0 "\
% (defun c () (interactive) (find-sh \"pdflatex {stem-}.tex\"))
% (defun d () (interactive) (find-pdf-page \"{stem}.pdf\"))
% (defun e () (interactive) (find-fline    \"{stem}.tex\"))
% (defun w () (interactive) (find-texworks \"{stem}.tex\"))
%
\\documentclass{<}article{>}
\\begin{<}document{>}

\\end{<}document{>}")
       )
     pos-spec-list)))

;; Tests: (find-latex-links)
;;        (find-latex-links "/tmp/foo")






;;;   __ _           _       _                   _ _       _        
;;;  / _(_)_ __   __| |     | |_   _  __ _      | (_)_ __ | | _____ 
;;; | |_| | '_ \ / _` |_____| | | | |/ _` |_____| | | '_ \| |/ / __|
;;; |  _| | | | | (_| |_____| | |_| | (_| |_____| | | | | |   <\__ \
;;; |_| |_|_| |_|\__,_|     |_|\__,_|\__,_|     |_|_|_| |_|_|\_\___/
;;;                                                                 
;; «find-lua-links» (to ".find-lua-links")
;; (find-find-links-links "{k}" "lua" "fname")
;;
;; Test: (find-sh0 "rm -v /tmp/foo.lua")
;;       (find-lua-links "/tmp/foo.lua")
;;
(defun find-lua-links (&optional fname &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks for foo."
  (interactive)
  (setq fname (or fname "{fname}"))
  (let ((dir    (file-name-directory    fname))
	(fname0 (file-name-nondirectory fname)))
    (find-elinks
     `((find-lua-links ,fname ,@pos-spec-list)
       (find-lua-links "~/LUA/foo.lua")
       ;; Convention: the first sexp always regenerates the buffer.
       (find-efunction 'find-lua-links)
       ""
       (find-fline ,dir ,fname0)
       (find-fline ,fname)
       (find-sh0 ,(format "touch %s && chmod 755 %s" fname fname))
       ""
       (ee-copy-rest 1 '(find-fline ,fname))
       ""
       ,(ee-template0 "\
#!/usr/bin/env lua5.1
-- (defun c () (interactive) (find-sh \"cd {dir}; ./{fname0}\"))
-- (defun d () (interactive) (find-fline \"{dir}\"))
-- (defun e () (interactive) (find-fline \"{fname}\"))
--
-- (find-sh \"./{fname0} arg1 arg2\")
--
-- (find-lua51manual \"\")
-- (find-pil2page 8 \"Contents\")
-- (find-pil2text 8 \"Contents\")
-- (find-fline \"~/LUA/lua50init.lua\")

print(\"Hello from {fname}\")

--[[
 (eepitch-lua51)
 (eepitch-kill)
 (eepitch-lua51)
dofile \"{fname0}\"

--]]\
")
     ))))




;;;                                         _           _   
;;;   ___  ___  ___ _ __ ___  ___ _ __  ___| |__   ___ | |_ 
;;;  / _ \/ __|/ __| '__/ _ \/ _ \ '_ \/ __| '_ \ / _ \| __|
;;; |  __/\__ \ (__| | |  __/  __/ | | \__ \ | | | (_) | |_ 
;;;  \___||___/\___|_|  \___|\___|_| |_|___/_| |_|\___/ \__|
;;;                                                         
;; «find-escreenshot-links» (to ".find-escreenshot-links")
;; Produce an ascii screenshot of an emacs window.
;; To test this, copy a block of lines to the kill ring and do:
;;
;;   (setq ee-ss-width 80)
;;   (find-escreenshot-links)
;;
;; Tests: (ee-ss-string-pad "" "_" " ")
;;        (ee-ss-string-pad "foo")
;;        (ee-ss-string-pad ee-ss-mode-line "-")
;;        (ee-ss-string-pad "M-x foo" "_")
;;        (find-estring (ee-ss-screenshot ";;  %s\n"))
;;        (find-escreenshot0-links)
;;        (find-escreenshot-links)
;;
(defun ee-untabify-string (string)
  (with-temp-buffer
    (insert string)
    (untabify 0 (point-max))
    (buffer-substring 0 (point-max))))

(defvar ee-ss-strings '("foo" "bar") "A list of strings, for screenshots.")
(defvar ee-ss-width 70 "The intended width of the screenshot.")
(defvar ee-ss-mode-line "-:**-" "The mode line of the screenshot.")
(defvar ee-ss-echo-area "" "The acho area or mode line of the screenshot.")
(defvar ee-ss-linefmt ";; %s\n" "??")

(defun ee-ss-string-pad (str &optional padchar barchar)
  (setq barchar (or barchar "|"))
  (let* ((padc   (if padchar (aref padchar 0) 32))
         (padlen (- ee-ss-width (length str)))
	 (padstr (make-string padlen padc)))
    (concat barchar str padstr barchar)))

(defun ee-ss-screenshot0 ()
  `(,(ee-ss-string-pad "" "_" " ")
    ,@(mapcar 'ee-ss-string-pad ee-ss-strings)
    ,(ee-ss-string-pad ee-ss-mode-line "-")
    ,(ee-ss-string-pad ee-ss-echo-area "_")
    ))

(defun ee-ss-screenshot (linefmt)
  (mapconcat (lambda (li) (format linefmt li))
	     (ee-ss-screenshot0) ""))

(defun find-escreenshot0-links (&rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks for an ascii screenshot."
  ;; (interactive)
  (apply 'find-elinks
   `((find-escreenshot0-links ,@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-escreenshot0-links)
     (setq ee-ss-strings '(split-string (ee-last-kill) "\n"))
     (setq ee-ss-width ,ee-ss-width)
     (setq ee-ss-mode-line ,ee-ss-mode-line)
     (setq ee-ss-echo-area ,ee-ss-echo-area)
     (setq ee-ss-linefmt ,ee-ss-linefmt)
     ""
     ,(ee-ss-screenshot ee-ss-linefmt))
   pos-spec-list))

(defun find-escreenshot-links (&rest pos-spec-list)
  (interactive)
  (setq ee-ss-mode-line (format-mode-line mode-line-format 0))
  (setq ee-ss-strings (split-string (ee-last-kill) "\n"))
  (apply 'find-escreenshot0-links pos-spec-list))



(provide 'eev-tlinks)



;; Local Variables:
;; coding:            utf-8-unix
;; no-byte-compile:   t
;; End:
