;;; eev-tlinks.el --- hyperlinks to temporary buffers generated by templates  -*- lexical-binding: nil; -*-

;; Copyright (C) 2013-2021 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:    20211201
;; 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")
;;
;; See:
;;   (find-links-conv-intro "3. Classification")
;;   (find-links-conv-intro "3. Classification" "c)")
;;   (find-links-conv-intro "3. Classification" "find-elinks")
;;   (find-links-conv-intro "3. Classification" "eev-tlinks.el")
;;
;; Many of the functions in this file are "five-minute hacks" whose
;; first versions were written in two steps. In the first step I ran
;; `M-x find-find-links-links-new', adjusted the arguments in the
;; first line of the temporary buffer and regenerated the buffer; this
;; gave me a "skeleton" for the real function. In the second step I
;; adjusted the arguments of the `find-elinks' and the string inside
;; the `ee-template0'. Each function here that was written in this way
;; has a "Skel:" line in the comments about its definition, and if you
;; run the sexp in the "Skel:" line you get its skeleton. There is a
;; video explaining this here:
;;
;;   (to "find-find-links-links-new")
;;
;; Some of the functions in this file were written with an ancestor of
;; `find-find-links-links-new' that generated uglier code; they need
;; to be rewritten. Also, some functions here are very old, and I
;; haven't used or tested them in ages; they deserve to be deleted.




;; «.ee-copy-rest»			(to "ee-copy-rest")
;;
;; «.find-find-links-links»		(to "find-find-links-links")
;; «.find-find-links-links-new»		(to "find-find-links-links-new")
;; «.ee-ffll-functions»			(to "ee-ffll-functions")
;;
;; «.find-intro-links»			(to "find-intro-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")
;; «.ee-youtubedl-command»		(to "ee-youtubedl-command")
;; «.find-psne-links»			(to "find-psne-links")
;; «.find-git-links»			(to "find-git-links")
;; «.find-fossil-links»			(to "find-fossil-links")
;; «.find-apt-get-source-links»		(to "find-apt-get-source-links")
;;
;; «.find-eevvideo-links»		(to "find-eevvideo-links")
;; «.find-psnevideo-links»		(to "find-psnevideo-links")
;; «.ee-psne-if-needed»			(to "ee-psne-if-needed")
;; «.code-psnevideo»			(to "code-psnevideo")
;; «.code-eevvideo»			(to "code-eevvideo")
;; «.code-eevvideo-local»		(to "code-eevvideo-local")
;;   «.hardcoded-paths»			(to "hardcoded-paths")
;; «.find-eev-video-links»		(to "find-eev-video-links")
;; «.find-eevshortvideo-links»		(to "find-eevshortvideo-links")
;;
;; «.find-latex-links»			(to "find-latex-links")
;; «.find-lua-links»			(to "find-lua-links")
;; «.find-escreenshot-links»		(to "find-escreenshot-links")
;; «.find-windows-eepitch-lua-links»	(to "find-windows-eepitch-lua-links")
;; «.find-extra-file-links»		(to "find-extra-file-links")
;; «.find-emacs-tangents-links»		(to "find-emacs-tangents-links")
;; «.find-eeit-links»			(to "find-eeit-links")
;; «.find-texlive-links»		(to "find-texlive-links")
;; «.find-newbrowser-links»		(to "find-newbrowser-links")
;; «.ee-0x0-upload-region»		(to "ee-0x0-upload-region")
;; «.find-0x0-links»			(to "find-0x0-links")
;; «.find-eepitch-bullet-links»		(to "find-eepitch-bullet-links")
;; «.find-red-star-links»		(to "find-red-star-links")
;;   «.ee-use-red-stars»		(to "ee-use-red-stars")
;;   «.ee-use-red-bullets»		(to "ee-use-red-bullets")
;; «.find-angg-es-links»		(to "find-angg-es-links")
;; «.find-1stclassvideo-links»		(to "find-1stclassvideo-links")


(require 'eev-env)
(require 'eev-wrap)    ; For: (find-eev "eev-wrap.el" "ee-template0") 
(require 'cl-lib)      ; For `cl-remove-if'



;;;                                                            _   
;;;   ___  ___        ___ ___  _ __  _   _       _ __ ___  ___| |_ 
;;;  / _ \/ _ \_____ / __/ _ \| '_ \| | | |_____| '__/ _ \/ __| __|
;;; |  __/  __/_____| (_| (_) | |_) | |_| |_____| | |  __/\__ \ |_ 
;;;  \___|\___|      \___\___/| .__/ \__, |     |_|  \___||___/\__|
;;;                           |_|    |___/                         
;;
;; «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")
;; Test: (find-find-links-links "u" "find-links" "k stem args")
;; THIS IS OBSOLETE - DON'T USE THIS!
;; Use `find-find-links-links-new' instead.

(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))

(defalias 'find-find-links-links-old 'find-find-links-links)

(defun find-find-links-links (&optional k stem args &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks for foo."
  ;; (interactive)
  ;; ^ Commented out because this is obsolete!
  (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))






;;;   __ _           _       _ _       _       /\ ____                           
;;;  / _(_)_ __   __| |     | (_)_ __ | | ____|/\|___ \      _ __   _____      __
;;; | |_| | '_ \ / _` |_____| | | '_ \| |/ / __|   __) |____| '_ \ / _ \ \ /\ / /
;;; |  _| | | | | (_| |_____| | | | | |   <\__ \  / __/_____| | | |  __/\ V  V / 
;;; |_| |_|_| |_|\__,_|     |_|_|_| |_|_|\_\___/ |_____|    |_| |_|\___| \_/\_/  
;;;                                                                              
;; «find-find-links-links-new»  (to ".find-find-links-links-new")
;; Test: (find-find-links-links-new)
;; Many of the templated functions of eev were written using this.
;; They all have a line saying ";; Skel:" that generates their "skeleton".
;; See: (find-eevgrep "grep --color -nH --null -e Skel: *.el")
;;      (find-eevtemplvideo "0:18" "1. `find-find-links-links-new'")
;;      (find-eevtemplvideo "1:15"   "if I execute (find-emacs-tangents-links)")
;;      (find-eevtemplvideo "1:29"   "generated again with these values")
;;      (find-eevtemplvideo "1:50"   "the implementation is very simple")
;;      (find-eevtemplvideo "2:00"   "in five minutes because")
;;      (find-eevtemplvideo "2:15"   ";; Skel:")
;;      (find-eevtemplvideo "2:32"   "optional arguments, then this field")
;;      (find-eevtemplvideo "2:40"   "temporary variables set by a let*")
;;      (find-eevtemplvideo "3:25"   "to write `find-emacs-tangents-links'")
;;      (find-eevtemplvideo "3:40"   "backslashes in the right places")
;;
(defun find-find-links-links-new (&optional stem args vars &rest pos-spec-list)
"Visit a temporary buffer containing a skeleton of a find-*-links function."
  (interactive)
  (setq stem (or stem "{stem}"))
  (setq args (or args "{args}"))
  (setq vars (or vars "{vars}"))
  (apply 'find-elinks-elisp
   `((find-find-links-links-new ,stem ,args ,vars ,@pos-spec-list)
     (find-find-links-links-new)
     (find-find-links-links-new "mytaskA" "" "")
     (find-find-links-links-new "mytaskB" "foo" "")
     (find-find-links-links-new "mytaskC" "foo bar" "")
     (find-find-links-links-new "mytaskD" "foo bar baz" "plic bletch")
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-find-links-links-new)
     ""
     ,(ee-template0 ";; <find-{stem}-links>")
     ,(concat       ";; Skel: " (ee-S `(find-find-links-links-new ,stem ,args ,vars)))
     ,(ee-template0 ";; Test: (find-{stem}-links)")
     ";;"
     ,(ee-ffll-defun stem args vars)
     )
   pos-spec-list))


;;;                   __  __ _ _ _            
;;;   ___  ___       / _|/ _| | | |     __/\__
;;;  / _ \/ _ \_____| |_| |_| | | |_____\    /
;;; |  __/  __/_____|  _|  _| | | |_____/_  _\
;;;  \___|\___|     |_| |_| |_|_|_|       \/  
;;;                                           
;; «ee-ffll-functions»  (to ".ee-ffll-functions")
;; Low-level functions used by find-find-links-links-new.
;;
;; Tests:
;; (ee-ffll-optional "")
;; (ee-ffll-optional "foo bar")
;; (ee-ffll-comma-args "plic bletch")
;; (find-estring (ee-ffll-setqs "  " "foo bar"))
;; (find-estring (ee-ffll-lets "  " "foo bar"))
;; (find-estring-elisp (ee-ffll-defun-without-lets "mytask" "foo bar"))
;; (find-estring-elisp (ee-ffll-defun-with-lets "mytask" "foo bar" "plc bltch"))
;; (find-estring-elisp (ee-ffll-defun "mytask" "foo bar"))
;; (find-estring-elisp (ee-ffll-defun "mytask" "foo bar" "plic bletch"))
;;
(defun ee-ffll-optional (args)
  (if (< 0 (length (split-string args)))
      (concat "&optional " args " ")
    ""))
	 
(defun ee-ffll-setqs (spaces args)
  (mapconcat (lambda (arg) (format "%s(setq %s (or %s \"{%s}\"))\n"
				   spaces arg arg arg))
	     (split-string args)
	     ""))

(defun ee-ffll-lets (spaces vars)
  (format "let* (%s)"
	  (mapconcat (lambda (var) (format "(%s \"{%s}\")" var var))
		     (split-string vars)
		     (concat "\n" spaces "       "))))

(defun ee-ffll-comma-args (args)
  (mapconcat (lambda (arg) (format ",%s " arg))
	     (split-string args)
	     ""))

(defun ee-ffll-defun-without-lets (stem args)
  (let* ((optional   (ee-ffll-optional args))
	 (setqs      (ee-ffll-setqs "  " args))
	 (comma-args (ee-ffll-comma-args args))
	 )
    (ee-template0 "\
(defun find-{stem}-links ({optional}&rest pos-spec-list)
\"Visit a temporary buffer containing hyperlinks for {stem}.\"
  (interactive)
{setqs}\
  (apply
   'find-elinks
   `((find-{stem}-links {comma-args},@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-{stem}-links)
     \"\"
     ,(ee-template0 \"\\
\")
     )
   pos-spec-list))
")))

(defun ee-ffll-defun-with-lets (stem args vars)
  (let* ((optional   (ee-ffll-optional   args))
	 (setqs      (ee-ffll-setqs "  " args))
	 (comma-args (ee-ffll-comma-args args))
	 (lets       (ee-ffll-lets "  "  vars))
	 )
    (ee-template0 "\
(defun find-{stem}-links ({optional}&rest pos-spec-list)
\"Visit a temporary buffer containing hyperlinks for {stem}.\"
  (interactive)
{setqs}\
  ({lets}
    (apply
     'find-elinks
     `((find-{stem}-links {comma-args},@pos-spec-list)
       ;; Convention: the first sexp always regenerates the buffer.
       (find-efunction 'find-{stem}-links)
       \"\"
       ,(ee-template0 \"\\
\")
       )
     pos-spec-list)))
")))

(defun ee-ffll-defun (stem args &optional vars)
  (if (equal vars "") (setq vars nil))
  (if vars (ee-ffll-defun-with-lets stem args vars)
     (ee-ffll-defun-without-lets stem args)))









;;;  _       _                   _ _       _        
;;; (_)_ __ | |_ _ __ ___       | (_)_ __ | | _____ 
;;; | | '_ \| __| '__/ _ \ _____| | | '_ \| |/ / __|
;;; | | | | | |_| | | (_) |_____| | | | | |   <\__ \
;;; |_|_| |_|\__|_|  \___/      |_|_|_| |_|_|\_\___/
;;;                                                 
;; «find-intro-links»  (to ".find-intro-links")
;; Skel: (find-find-links-links-new "intro" "stem" "")
;; 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>
;; Skel: (find-intro-links \"{stem}\")
;; Test: (find-{stem}-intro)

\(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-eev-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")





;;;                       _                    _           
;;;   ___  _____   __    | |__   ___  __ _  __| | ___ _ __ 
;;;  / _ \/ _ \ \ / /____| '_ \ / _ \/ _` |/ _` |/ _ \ '__|
;;; |  __/  __/\ 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)))

;; Tests: (find-debpkg-links "bash")
;;        (find-debpkg-links "libicu")
;;
(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 showpkg {pkgname}\")
{ee-H}(find-sh \"apt-cache search {pkgname} | sort\")
{ee-H}(find-sh \"apt-cache search '{pkgname}*' | sort\")
{ee-H}(find-sh \"apt search '{pkgname}*'\")
{ee-H}(find-sh \"apt search '{pkgname}*' 2> /dev/null\")
{ee-H}(find-sh \"grep-aptavail -P {pkgname}\")
{ee-H}(find-sh \"dpkg-query -W '{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")
;; Skel: (find-find-links-links-new "youtubedl" "dir title hash ext- stem" "")
;; Test: (find-youtubedl-links nil nil "K6LmZ0A1s9U")
;; See:  (find-audiovideo-intro "6. Youtube-dl")
;;       (find-audiovideo-intro "6.1. Downloading a local copy")
;;       (find-eevtemplvideo "19:23" "5. `find-youtubedl-links'")
;;       (find-eevtemplvideo "19:43"   "if we twist the notion of user enough")
;;       (find-eevtemplvideo "20:02"   "user-friendly to me")
;;       (find-eevtemplvideo "20:05"   "The documentation is in this tutorial:")
;;       (find-eevtemplvideo "21:36"   "its code is here")
;;       (find-eevtemplvideo "21:55"   "Let me show a demo")
;;       (find-eevtemplvideo "22:15"   "I never type these rm -Rv/mkdir/cd by hand")
;;       (find-eevtemplvideo "22:48"   "let me show how to download ... the hash is here")
;;       (find-eevtemplvideo "23:25"   "they regenerate this buffer in slightly different ways")
;;       (find-eevtemplvideo "24:03"   "a video with this hash. If I visit the directory")
;;       (find-eevtemplvideo "24:32"   "my magic functions have to")
;;       (find-eevtemplvideo "24:50"   "if I run this sexp here with nil in the title")
;;       (find-eevtemplvideo "25:00"   "it tries to guess the title")
;;       (find-eevtemplvideo "25:28"   "and if I change this {stem} here I get short links")
;;       (find-eevtemplvideo "26:14"   "has very long lines, but if I type super-w")
;;       (find-eevtemplvideo "26:28"   "I get a buffer that shows the code for")
;;       (find-eevtemplvideo "26:50"   "if I execute this I play the video")
;;       (find-eevtemplvideo "27:15"   "a copy of that points to the right position")
;;       (find-eevtemplvideo "27:53"   "summary: this is how I download videos from youtube")
;;
(defun find-youtubedl-links (&optional dir title hash ext- stem &rest pos-spec-list)
"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
   `((find-youtubedl-links ,dir ,title ,hash ,ext- ,stem ,@pos-spec-list)
    (find-youtubedl-links ,dir nil ,hash nil ,stem)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-youtubedl-links)
     ""
     ,@(ee-youtubedl-dir-links nil hash stem)
     (setq ee-youtubedl-dirs ',ee-youtubedl-dirs)
     (setq ee-youtubedl-dir   ,ee-youtubedl-dir)
     ""
     (find-audiovideo-intro "6. Youtube-dl")
     ""
     ,(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}'
{ee-youtubedl-command}       --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-}\")
# (code-video \"{stem}video\" \"{dir}{title}-{hash}{ext-}\")
# (find-{stem}video)
# (find-{stem}video \"0:00\")

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




;; `find-youtubedl-links' uses LOTS of internal functions and
;; variables. They are defined below.

;; Code for splitting filenames of downloaded videos into components.
;; Test: (ee-youtubedl-split "~/tmp/videos/foo_bar-abF7go7RLTc.flv")
;;       --> ("~/tmp/videos/" "foo_bar" "abF7go7RLTc" ".flv" ".flv")
;;
(defvar ee-youtubedl-ext-re
  "\\(\\.[A-Za-z0-9]\\{2,5\\}\\)\\(\\.part\\)?$")

(defun ee-youtubedl-split (fname)
  "Split FNAME into (dir title hash ext ext-)."
  (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-subtitle-p (fname)
  "Return true if FNAME looks like a subtitle file."
  (string-match "\\.\\(srt\\|vtt\\)$" fname))

(defun ee-youtubedl-not-subtitles (fnames)
  "Return the elements of FNAMES that don't look like subtitle files."
     (cl-remove-if 'ee-youtubedl-subtitle-p fnames))

(defun ee-youtubedl-guess (dir hash n)
  "Return a component of the first file in DIR containing the string HASH.
Files that look like subtitle files are ignored."
  (let* ((fnames0 (ee-youtubedl-guess* dir hash))
	 (fnames1 (ee-youtubedl-not-subtitles fnames0))
	 (fname (car fnames1)))
    (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))

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

;; «ee-youtubedl-command»  (to ".ee-youtubedl-command")
;; The default value is `ee-youtubedl-command' is (still) this one:
;;
(defvar ee-youtubedl-command "youtube-dl -t")
;;
;; but this is outdated in several ways:
;;
;;   1. when we use it we get this warning:
;;      "WARNING: --title is deprecated. Use
;;       -o "%(title)s-%(id)s.%(ext)s" instead."
;;
;;   2. youtube-dl is currently sort of dead. See:
;;      https://old.reddit.com/r/DataHoarder/comments/p9riey/youtubedl_is_possibly_dead/
;;      https://news.ycombinator.com/item?id=28289981 Youtube-dl is possibly dead
;;
;;   3. yt-dlp doesn't support the options `-t' and `--title':
;;      https://github.com/yt-dlp/yt-dlp
;;      https://github.com/yt-dlp/yt-dlp#Removed
;;
;; Suggestion (2021nov26): install yt-dlp and either put this in your .emacs,
;;
;;   (setq ee-youtubedl-command "yt-dlp -o '%(title)s-%(id)s.%(ext)s'")
;;
;; and put a copy of this fake youtube-dl script
;;
;;   http://angg.twu.net/bin/youtube-dl.html
;;   http://angg.twu.net/bin/youtube-dl
;;
;; somewhere in your PATH, and use this:
;;
;;   (setq ee-youtubedl-command "youtube-dl -t")


;; The directories into which we usually download videos.
;; Tests: (find-elinks (ee-youtubedl-dir-links))
;;        (find-elinks (ee-youtubedl-dir-links '("DIR1" "DIR2")))
;;        (let ((ee-youtubedl-dirs '("DIR1" "DIR2"))) (find-youtubedl-links))
;;
(defvar ee-youtubedl-dir "~/videos/")

(defvar ee-youtubedl-dirs
  '("~/videos/" "~/videos/tech/" "/tmp/videos/" "/tmp/"))

(defun ee-youtubedl-dir-links (&optional dirs hash stem)
  (setq dirs (or dirs ee-youtubedl-dirs))
  (setq hash (or hash "{hash}"))
  (setq stem (or stem "{stem}"))
  (mapcar (lambda (dir) `(find-youtubedl-links ,dir nil ,hash nil ,stem))
	  dirs))

;; This is a hack (written in 2013sep10) that plays a local copy of a
;; video from its URL. To easiest way to use it is to put the point on
;; a youtube URL and type `M-x bryl'.
;;
(defun ee-youtubedl-guess** (dirs hash)
  (apply 'append (mapcar (lambda (d) (ee-youtubedl-guess* d hash)) dirs)))

(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")

;; TODO:
;; Redefine this using: (find-eevfile "eev-brxxx.el")
;; and add error handling. Tests:
;;   (setq ee-my-url "http://www.youtube.com/watch?v=tby5aMrMu6Q")
;;   (ee-youtubedl-url-to-hash ee-my-url)
;;   (ee-youtubedl-url-to-fname ee-my-url)
;;   (find-evardescr 'ee-youtubedl-dirs)
;;
;; (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")
;; Skel: (find-find-links-links-new "psne" "url wget-options" "")
;; Test: (find-psne-links "http://foo/bar")
;;  See: (find-psne-intro "3. The new way: `M-x brep'")
;;       (find-psne-intro "3. The new way: `M-x brep'" "find-psne-links")

(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 "-nc"))
  (apply
   'find-elinks
   `((find-psne-links ,url ,wget-options ,@pos-spec-list)
     (find-psne-links ,url "-c" ,@pos-spec-list)
     (find-psne-links ,url "" ,@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-psne-links)
     ""
     ,(ee-adjust-red-stars " (eepitch-shell2)")
     ,(ee-find-psne-core url wget-options)
     )
   pos-spec-list))

;; Test:
;; (find-estring (ee-find-psne-core "http://www.lua.org/start.html"))
;;
(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))
	 (fname0 (file-name-nondirectory 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 \"{localdir}\" \"{fname0}\")
# (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 a script for downloading a git repo."
  (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}

export PAGER=cat
git branch --list -a
git for-each-ref
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-fossil-links»  (to ".find-fossil-links")
;; Skel: (find-find-links-links-new "fossil" "url subdir c" "")
;; Test: (find-fossil-links "http://fossil.0branch.com/oorexx-mode")
;; See:  https://fossil-scm.org/
;;
(defun ee-fossil-url-stem (url) (ee-git-url-stem url))

(defun find-fossil-links (&optional url subdir c &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks for fossil."
  (interactive (list (ee-url-at-point)))
  (setq url (or url "{url}"))
  (setq subdir (or subdir (ee-fossil-url-stem url) "{subdir}"))
  (setq c (or c (replace-regexp-in-string "[-.]" "" subdir) "{c}"))
  (apply
   'find-elinks
   `((find-fossil-links ,url ,subdir ,c ,@pos-spec-list)
     (find-fossil-links "{url}" "{subdir}" "{c}")
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-fossil-links)
     ""
     ,(ee-template0 "\
# (find-sh \"fossil help\")
# (find-sh \"fossil help clone\")
# (find-sh \"fossil help pull\")
# (find-sh \"fossil help all\")
# (find-sh \"fossil help open\")

 (eepitch-shell)
 (eepitch-kill)
 (eepitch-shell)
# rm -fv ~/usrc/fossil-repos/{subdir}.fsl
mkdir -p ~/usrc/fossil-repos/
cd       ~/usrc/fossil-repos/

fossil clone {url}    {subdir}.fsl
fossil pull  {url} -R {subdir}.fsl
fossil all ls

# cd        ~/usrc/{subdir}/ && fossil close
# rm -Rfv   ~/usrc/{subdir}/
mkdir -p    ~/usrc/{subdir}/
cd          ~/usrc/{subdir}/
fossil open ~/usrc/fossil-repos/{subdir}.fsl

# (code-c-d \"{c}\" \"~/usrc/{subdir}/\")
# (find-{c}file \"\")
")
     )
   pos-spec-list))





;;;              _                   _                                     
;;;   __ _ _ __ | |_       __ _  ___| |_      ___  ___  _   _ _ __ ___ ___ 
;;;  / _` | '_ \| __|____ / _` |/ _ \ __|____/ __|/ _ \| | | | '__/ __/ _ \
;;; | (_| | |_) | ||_____| (_| |  __/ ||_____\__ \ (_) | |_| | | | (_|  __/
;;;  \__,_| .__/ \__|     \__, |\___|\__|    |___/\___/ \__,_|_|  \___\___|
;;;       |_|             |___/                                            
;;
;; «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-eevvideo-links»  (to ".find-eevvideo-links")
;; Used by: (find-videos-intro "2. Short links to eev video tutorials")
;;          (find-eev "eev-audiovideo.el" "video-tutorials")
;;     See: (find-audiovideo-intro "7.2. `find-eevvideo-links'")
;;    Skel: (find-find-links-links-new "eevvideo" "c stem youtubeid time" "url")
;;    Test: (find-eevvideo-links "eevnav" "M-x-list-packages-eev-nav" "0:00")
;;
(defun find-eevvideo-links (&optional c stem youtubeid time &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks for eevvideo."
  (interactive)
  (setq c (or c "{c}"))
  (setq stem (or stem "{stem}"))
  (setq youtubeid (or youtubeid "{youtubeid}"))
  (setq time (or time "{time}"))
  (let* ((url (format "http://angg.twu.net/eev-videos/%s.mp4" stem)))
    (apply
     'find-elinks
     `((find-eevvideo-links ,c ,stem ,youtubeid ,time ,@pos-spec-list)
       ;; Convention: the first sexp always regenerates the buffer.
       ;; (find-efunction 'find-eevvideo-links)
       ,(ee-psnevideo-links c url youtubeid time)
       )
     pos-spec-list)))



;;;                             _     _            
;;;  _ __  ___ _ __   _____   _(_) __| | ___  ___  
;;; | '_ \/ __| '_ \ / _ \ \ / / |/ _` |/ _ \/ _ \ 
;;; | |_) \__ \ | | |  __/\ V /| | (_| |  __/ (_) |
;;; | .__/|___/_| |_|\___| \_/ |_|\__,_|\___|\___/ 
;;; |_|                                            
;;
;; «find-psnevideo-links»  (to ".find-psnevideo-links")
;; Skel: (find-find-links-links-new "psnevideo" "c url youtubeid time" "url")
;; Tests: (find-psnevideo-links "C" "http://foo.org/bar.mp4")
;;        (find-psnevideo-links "C" "http://foo.org/bar.mp4" nil "1:23")
;;
(defun find-psnevideo-links (&optional c url youtubeid time &rest pos-spec-list)
"Visit a temporary buffer containing an e-script for downloading and playing URL."
  (interactive)
  (setq c (or c "{c}"))
  (setq url (or url "{url}"))
  (setq youtubeid (or youtubeid "{youtubeid}"))
  (setq time (or time "{time}"))
  (apply
   'find-elinks
   `((find-psnevideo-links ,c ,url ,youtubeid ,time ,@pos-spec-list)
     ,(ee-psnevideo-links c url youtubeid time)
     )
   pos-spec-list))

;; Tests:
;; (find-estring (ee-psnevideo-links "C" "http://foo.org/bar.mp4"))
;; (find-estring (ee-psnevideo-links "C" "http://foo.org/bar.mp4" nil "1:23"))
;; (find-estring (ee-psnevideo-links "C" "http://foo.org/bar.mp4" "YID" "1:23"))
;;
(defun ee-psnevideo-links (c url &optional youtubeid time)
  (setq youtubeid (or youtubeid "{youtubeid}"))
  (setq time      (or time      "{time}"))
  (let* ((fname   (ee-shorten-file-name (ee-url-to-fname url)))
	 (argtime (ee-time-to-arg time)))
    (concat
     ;;
     ;; See:
     ;; (find-audiovideo-intro "7. `code-psnevideo'" "second line")
     ;; (find-audiovideo-intro "7. `code-psnevideo'" "redefine")
     ;; (find-audiovideo-intro "7. `code-psnevideo'" "last part")
     ;;
     (ee-template0 "\
# (find-video \"{fname}\"{argtime})

# (find-audiovideo-intro \"7. `code-psnevideo'\" \"second line\")
# (find-audiovideo-intro \"7. `code-psnevideo'\" \"redefine\")
#   (code-video \"{c}video\" \"{fname}\")
#   (find-{c}video{argtime})

")
     (ee-psnevideo-url-youtube url youtubeid time)
     "\n\n"
     "# (find-audiovideo-intro \"7. `code-psnevideo'\" \"last part\")\n"
     "\n\n"
     (ee-psne-if-needed url)
     )))



;; Tests:
;; (find-estring (ee-psnevideo-url-youtube "http://foo.org/bar.mp4"))
;; (find-estring (ee-psnevideo-url-youtube "http://foo.org/bar.mp4" nil "1:23"))
;;
(defun ee-psnevideo-url-youtube (url &optional youtubeid time)
  (setq youtubeid (or youtubeid "{youtubeid}"))
  (setq time      (or time      "{time}"))
  (let* ((fname       (ee-shorten-file-name (ee-url-to-fname url)))
         (fname0      (file-name-nondirectory fname))
         (dir         (file-name-directory fname))
	 (youtubeurl  (format "http://www.youtube.com/watch?v=%s" youtubeid))
	 (youtubetime (or (ee-time-to-youtube-time time) "")))
    (ee-template0 "\
# URL, local file, and links to the directory of the local file:
#               {url}
#              {fname}
# (find-fline \"{dir}\" \"{fname0}\")
# (find-fline \"{dir}\")

# Youtube:
# (kill-new \"{youtubeurl}{youtubetime}\")
#            {youtubeurl}{youtubetime}")
    ))




;; «ee-psne-if-needed»  (to ".ee-psne-if-needed")
;; Tests:
;; (ee-psne-if-needed "http://www.gnu.org/software/emacs/emacs-paper.html")
;; (find-estring (ee-psne-if-needed "http://www.foo.org/bar.html"))
;; (find-estring (ee-psne-download  "http://www.foo.org/bar.html"))
;; (find-estring (ee-psne-download0 "http://www.foo.org/bar.html"))
;;
(defun ee-psne-if-needed (url)
  (if (ee-psne-downloaded-p url)
      "# Local file found. No need to download it again.\n"
    (ee-adjust-red-stars (ee-psne-download url))))

(defun ee-psne-downloaded-p (url)
  (file-exists-p (ee-expand (ee-url-to-fname url))))

(defun ee-psne-download (url)
  (concat "\
#  Local file not found! 
#  You need to run this: \n
" (ee-psne-download0 url)))

(defun ee-psne-download0 (url)
  (let* ((fname  (ee-shorten-file-name (ee-url-to-fname url)))
         (fname0 (file-name-nondirectory fname))
         (dir    (file-name-directory fname)))
    (ee-template0 "\
 (eepitch-shell)
 (eepitch-kill)
 (eepitch-shell)
mkdir -p {dir}
cd       {dir}
wget -nc '{url}'
echo     '{url}' >> ~/.psne.log

# (find-fline \"{dir}\")
# (find-fline \"{dir}\" \"{fname0}\")
# See: (find-psne-intro)
")))

;; Test: (find-estring (ee-psne-url-comment "http://www.foo.org/bar.html"))
(defun ee-psne-url-comment (url)
  (let* ((fname  (ee-shorten-file-name (ee-url-to-fname url)))
         (fname0 (file-name-nondirectory fname))
         (dir    (file-name-directory fname)))
    (ee-template0 "\
# URL, local file, and links to the directory of the local file:
#               {url}
#              {fname}
# (find-fline \"{dir}\" \"{fname0}\")
# (find-fline \"{dir}\")
")))







;;;                _                                       _     _            
;;;   ___ ___   __| | ___       _ __  ___ _ __   _____   _(_) __| | ___  ___  
;;;  / __/ _ \ / _` |/ _ \_____| '_ \/ __| '_ \ / _ \ \ / / |/ _` |/ _ \/ _ \ 
;;; | (_| (_) | (_| |  __/_____| |_) \__ \ | | |  __/\ V /| | (_| |  __/ (_) |
;;;  \___\___/ \__,_|\___|     | .__/|___/_| |_|\___| \_/ |_|\__,_|\___|\___/ 
;;;                            |_|                                            
;;
;; «code-psnevideo»  (to ".code-psnevideo")
;; See: (find-audiovideo-intro "7. `code-psnevideo'")

(defun      code-psnevideo (c url &optional youtubeid)
  (eval (ee-read (ee-code-psnevideo c url youtubeid))))
(defun find-code-psnevideo (&optional c url youtubeid &rest rest)
  (setq c (or c "{c}"))
  (setq url (or url "{url}"))
  (setq youtubeid (or youtubeid "{youtubeid}"))
  (find-estring-elisp (apply 'ee-code-psnevideo c url youtubeid rest)))
(defun   ee-code-psnevideo (c url youtubeid)
  (ee-template0 "\
;; (find-code-psnevideo \"{c}\" \"{url}\" \"{youtubeid}\")
;;      (code-psnevideo \"{c}\" \"{url}\" \"{youtubeid}\")
;;                 (find-{c}video \"0:00\")

(defun find-{c}video (&optional time &rest rest)
  (interactive)
  (find-psnevideo-links \"{c}\" \"{url}\" \"{youtubeid}\" time))
"))





;; The functions below were totally rewritten, and their new definions
;; are here:

;; ;;;                _                                   _     _            
;; ;;;   ___ ___   __| | ___        ___  _____   ____   _(_) __| | ___  ___  
;; ;;;  / __/ _ \ / _` |/ _ \_____ / _ \/ _ \ \ / /\ \ / / |/ _` |/ _ \/ _ \ 
;; ;;; | (_| (_) | (_| |  __/_____|  __/  __/\ V /  \ V /| | (_| |  __/ (_) |
;; ;;;  \___\___/ \__,_|\___|      \___|\___| \_/    \_/ |_|\__,_|\___|\___/ 
;; ;;;                                                                       
;; ;; «code-eevvideo»  (to ".code-eevvideo")
;; ;; TODO: rewrite this reusing parts of:
;; ;;     (find-eev "eev-videolinks.el" "find-eevlocal-links")
;; ;; See: (find-audiovideo-intro "7.1. `code-eevvideo'")
;; ;; Test: (find-code-eevvideo "eevnav" "M-x-list-packages-eev-nav")
;; ;;            (code-eevvideo "eevnav" "M-x-list-packages-eev-nav")
;; ;;                      (find-eevnavvideo "0:00")
;; ;;
;; (defun      code-eevvideo (c stem &optional youtubeid)
;;   (eval (ee-read (ee-code-eevvideo c stem youtubeid))))
;; (defun find-code-eevvideo (&optional c stem youtubeid &rest rest)
;;   (setq c (or c "{c}"))
;;   (setq stem (or stem "{stem}"))
;;   (setq youtubeid (or youtubeid "{youtubeid}"))
;;   (find-estring-elisp (apply 'ee-code-eevvideo c stem youtubeid rest)))
;; (defun   ee-code-eevvideo (c stem youtubeid)
;;   (ee-template0 "\
;; ;; (find-code-eevvideo \"{c}\" \"{stem}\" \"{youtubeid}\")
;; ;;      (code-eevvideo \"{c}\" \"{stem}\" \"{youtubeid}\")
;; ;;                (find-{c}video \"0:00\")
;; ;;
;; ;; See: (find-audiovideo-intro \"7.1. `code-eevvideo'\")
;; 
;; (defun find-{c}video (&optional time &rest rest)
;;   (interactive)
;;   (find-eevvideo-links \"{c}\" \"{stem}\" \"{youtubeid}\" time))
;; "))
;; 
;; ;; «code-eevvideo-local»  (to ".code-eevvideo-local")
;; ;; Test: (code-eevvideo-local "vlinks" "2021-video-links" "xQqWufQgzVY")
;; ;;  (find-code-eevvideo-local "vlinks" "2021-video-links" "xQqWufQgzVY")
;; ;;
;; (defun      code-eevvideo-local (c stem &optional youtubeid)
;;   (eval (ee-read (ee-code-eevvideo-local c stem youtubeid))))
;; (defun find-code-eevvideo-local (&optional c stem youtubeid &rest rest)
;;   (setq c (or c "{c}"))
;;   (setq stem (or stem "{stem}"))
;;   (setq youtubeid (or youtubeid "{youtubeid}"))
;;   (find-estring-elisp (apply 'ee-code-eevvideo-local c stem youtubeid rest)))
;; (defun   ee-code-eevvideo-local (c stem youtubeid)
;;   (ee-template0 "\
;; ;; (find-code-eevvideo-local \"{c}\" \"{stem}\" \"{youtubeid}\")
;; ;;      (code-eevvideo-local \"{c}\" \"{stem}\" \"{youtubeid}\")
;; ;;
;; ;;                    (find-fline \"$S/http/angg.twu.net/eev-videos/\" \"{stem}\")
;; ;; (find-code-video \"{c}video\" \"$S/http/angg.twu.net/eev-videos/{stem}.mp4\")
;;         (code-video \"{c}video\" \"$S/http/angg.twu.net/eev-videos/{stem}.mp4\")
;; ;;             (find-{c}video \"0:00\")
;; "))



;; «hardcoded-paths»  (to ".hardcoded-paths")
;;
;; The definitions of `find-eevvideo-links' and `code-eevvideo' above
;; have strings like "eev" and "http://angg.twu.net/eev-videos/"
;; hardcoded in several places... it is easy, but not entirely
;; trivial, to create variants of them that point to other sites that
;; stores video tutorials and presentations in ways that are easy to
;; download. If you are aware of sites like that, please get in touch
;; and I'll create functions pointing to them!

;;;                            _     _            
;;;   ___  _____   __   __   _(_) __| | ___  ___  
;;;  / _ \/ _ \ \ / /___\ \ / / |/ _` |/ _ \/ _ \ 
;;; |  __/  __/\ V /_____\ V /| | (_| |  __/ (_) |
;;;  \___|\___| \_/       \_/ |_|\__,_|\___|\___/ 
;;;                                               
;; «find-eev-video-links» (to ".find-eev-video-links")
;; Obsolete?
;; See: (find-audiovideo-intro "7.2. `find-eevvideo-links'")
;; and: (find-video-links-intro)
;;
;; Skel: (find-find-links-links "{k}" "eev-video" "c anggstem youtubehash")
;;       (find-find-links-links-new "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 -nc '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-eevshortvideo-links»  (to ".find-eevshortvideo-links")
;; Skel: (find-find-links-links-new "eevshortvideo" "c stem youtubeid" "")
;; Used in: (find-eev "eev-audiovideo.el" "video-tutorials")
;;
(defun find-eevshortvideo-links (&optional c stem youtubeid &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks for eevshortvideo."
  (interactive)
  (setq c (or c "{c}"))
  (setq stem (or stem "{stem}"))
  (setq youtubeid (or youtubeid "{youtubeid}"))
  (apply
   'find-elinks-elisp
   `((find-eevshortvideo-links ,c ,stem ,youtubeid ,@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-eevshortvideo-links)
     ""
     ,(ee-template0 "\
;; (find-1stclassvideo-links \"{c}\")

;; Skel: (find-eevshortvideo-links \"{c}\" \"{stem}\" \"{youtubeid}\")
;;  See: (find-videos-intro \"1. Some videos\" \"{stem}\")
;; Index: http://angg.twu.net/.emacs.videos.html#{c}
;;  Test: (find-{c}video \"0:00\")
(defun find-{c}video (&optional time &rest rest)
  \"Play one of the video tutorials of eev starting at TIME.
See: (find-videos-intro \\\"1. Some videos\\\" \\\"{stem}\\\")
     http://angg.twu.net/{stem}.html
     for more info on this particular video,
and: (find-video-links-intro \\\"7. `find-eev-video'\\\")
 or: http://angg.twu.net/eev-intros/find-video-links-intro.html#7
     for more info on these video tutorials.\"
  (interactive)
  (find-eev-video \"{stem}\" \"{youtubeid}\" time))
")
     )
   pos-spec-list))






;;;   __ _           _       _       _                 _ _       _        
;;;  / _(_)_ __   __| |     | | __ _| |_ _____  __    | (_)_ __ | | _____ 
;;; | |_| | '_ \ / _` |_____| |/ _` | __/ _ \ \/ /____| | | '_ \| |/ / __|
;;; |  _| | | | | (_| |_____| | (_| | ||  __/>  <_____| | | | | |   <\__ \
;;; |_| |_|_| |_|\__,_|     |_|\__,_|\__\___/_/\_\    |_|_|_| |_|_|\_\___/
;;;                                                                       
;; «find-latex-links» (to ".find-latex-links")
;; Skel: (find-find-links-links-new "latex" "stem" "stem-")
;; Tests: (find-latex-links)
;;        (find-latex-links "/tmp/foo")
;;        (find-latex-links "/tmp/foo" 2)
;;        (find-latex-links "/tmp/foo" 2 "copy-rest")
;;   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)))







;;;   __ _           _       _                   _ _       _        
;;;  / _(_)_ __   __| |     | |_   _  __ _      | (_)_ __ | | _____ 
;;; | |_| | '_ \ / _` |_____| | | | |/ _` |_____| | | '_ \| |/ / __|
;;; |  _| | | | | (_| |_____| | |_| | (_| |_____| | | | | |   <\__ \
;;; |_| |_|_| |_|\__,_|     |_|\__,_|\__,_|     |_|_|_| |_|_|\_\___/
;;;                                                                 
;; «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))





;; «find-windows-eepitch-lua-links»  (to ".find-windows-eepitch-lua-links")
;; Skel: (find-find-links-links-new "windows-eepitch-lua" "dir" "")
;; Test: (find-windows-eepitch-lua-links "/tmp/")
;;
;; THIS IS OBSOLETE!
;; The new way is this one:
;;   (find-windows-beginner-intro "7.3. Lua")
;;
(defun find-windows-eepitch-lua-links (&optional dir &rest pos-spec-list)
"Visit a temporary buffer that helps in setting up `eepitch-lua52's on M$ Windows."
  (interactive)
  ;; (setq dir (or dir "{dir}"))
  (setq dir (or dir default-directory))
  (apply
   'find-elinks-elisp
   `((find-windows-eepitch-lua-links ,dir ,@pos-spec-list)
     (find-windows-eepitch-lua-links "{dir}" ,@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     ;; (find-efunction 'find-windows-eepitch-lua-links)
     ""
     ,(ee-template0 "\
;; Instructions:
;; To configure the `eepitch-lua52' function on M$ Windows, do this:
;;
;; 1) Install ZeroBrane from:
;;      https://studio.zerobrane.com/
;;
;; 2) Find the directory inside the ZeroBrane installation that
;;    has the file lua52.exe.
;;
;; 3) Open that directory in Emacs using Dired - see:
;;      (find-node \"(emacs)Dired\")
;;    Hints: use RET to enter into a subdirectory; use M-k to go back;
;;    you may start here:
;;      (find-fline \"C:/\")
;;
;; 4) Run `M-x find-windows-eepitch-lua-links' there. You should get
;;    a buffer like this one, but with that directory in the first line.
;;    This is like adjusting the parameter of `find-latex-links',
;;    but the value of \"{<}dir{>}\" is set to the current directory. See:
;;      (find-eev-quick-intro \"7.5. `find-latex-links'\")
;;
;; 5) Test if you've got the correct \"{<}dir{>}\". If you got it
;;    right then the sexp below should open that directory and go to
;;    line where the \"lua52.exe\" is:
;;      (find-fline \"{dir}\" \"lua52.exe\")
;;
;; 6) Try the sexp below - it is a low-level test to see a) if our
;;    current path to \"lua52.exe\" is the right one AND b) if we can run
;;    that \"lua52.exe\" as a \"shell-like program\" in a target buffer.
;;    These ideas are explained here,
;;      (find-eev-quick-intro \"6.1. The main key: <F8>\")
;;      (find-eepitch-intro \"1.1. Another target\")
;;    and the test sexp is:
;;      (eepitch-comint \"lua52\" \"{dir}lua52.exe\")
;;
;; 7) If you got a prompt like this one
;;
;;      Lua 5.2.4  ... 1994-2015 Lua.org, PUC-Rio
;;      > 
;;
;;    in the right window in the test in item (6) then everything is
;;    working. If you didn't get a prompt like that then you NEED to run
;;    this before performing another test:
;;      (eepitch-kill)
;;      
;; 8) Override the current definition of eepitch-lua52 by running this:

(defun eepitch-lua52 () (interactive)
  (eepitch-comint \"lua52\"
     \"{dir}lua52.exe\"))

;;    Note that it is a 3-line sexp! If you execute it with `M-e'
;;    the result in the echo area should be \"eepitch-lua52\".
;;
;; 9) Test if the eepitch block below works: run it by typing
;;    `<f8>'s on its three red star lines, and then `<f8>'s on its three
;;    non-red star lines.

 (eepitch-lua52)
 (eepitch-kill)
 (eepitch-lua52)
print(2+3)
for i=2,20,3 do print(i) end
os.exit()

")
     )
   pos-spec-list))





;; «find-extra-file-links»  (to ".find-extra-file-links")
;; Skel: (find-find-links-links-new "extra-file" "fname c" "dir")
;; Docs: (find-audiovideo-intro "4.1. `find-extra-file-links'")
;;
(defun find-extra-file-links (&optional fname c &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks for extra-file."
  (interactive (list (if (eq major-mode 'dired-mode)
			 (ee-dired-to-fname)
		       buffer-file-name)))
  (if fname (setq fname (ee-shorten-file-name fname)))
  (setq fname (or fname "{fname}"))
  (setq c (or c "{c}"))
  (let* ((dir (file-name-directory fname))
	 (fname0 (file-name-nondirectory fname)))
    (apply
     'find-elinks-elisp
     `((find-extra-file-links ,fname ,c ,@pos-spec-list)
       ;; Convention: the first sexp always regenerates the buffer.
       ;; (find-efunction 'find-extra-file-links)
       ;; ""
       ,(ee-template0 "\
;; See: (find-eev-quick-intro \"9.1. `code-c-d'\")
;;      (find-audiovideo-intro \"4.1. `find-extra-file-links'\")
;;      (find-pdf-like-intro \"9. Generating three pairs\" \"`M-h M-p'\")

;; Links to this file and directory:
;; (find-fline {(ee-S dir)} {(ee-S fname0)})
;; (find-fline {(ee-S fname)})
;; (find-fline {(ee-S dir)})
\(code-c-d \"{c}\" \"{dir}\")
;; (find-{c}file \"\")

;; Links to a PDF file:
;; (find-pdf-page \"{fname}\")
;; (find-pdf-text \"{fname}\")
\(code-pdf-page \"{c}\" \"{fname}\")
\(code-pdf-text \"{c}\" \"{fname}\")
;; (find-{c}page)
;; (find-{c}text)

;; Links to an audio file:
;; (find-audio \"{fname}\")
\(code-audio \"{c}audio\" \"{fname}\")
;; (find-{c}audio)
;; (find-{c}audio \"0:00\")

;; Links to a video file:
;; (find-video \"{fname}\")
\(code-video \"{c}video\" \"{fname}\")
;; (find-{c}video)
;; (find-{c}video \"0:00\")
;;
;; (eev-avadj-mode 0)
;; (eev-avadj-mode)

;; Links to an shell-like program (for eepitch):
;; (eepitch-comint \"{c}\" \"{fname}\")

(defun eepitch-{c} () (interactive)
  (eepitch-comint \"{c}\"
     \"{fname}\"))

;; Test:

 (eepitch-{c})
 (eepitch-kill)
 (eepitch-{c})
")
       )
     pos-spec-list)))

;; Tests:
;; (find-extra-file-links "~/eev-videos/three-keys-2.mp4")





;; «find-emacs-tangents-links»  (to ".find-emacs-tangents-links")
;; Skel: (find-find-links-links-new "emacs-tangents" "yyyy mm dd msg txtstem" "")
;; Test: (find-emacs-tangents-links "2020" "10" "05")
;;
(defun find-emacs-tangents-links (&optional yyyy mm dd msg txtstem &rest pos-spec-list)
"Visit a temporary buffer with hyperlinks to a post in emacs-tangents."
  (interactive)
  (setq yyyy (or yyyy "{yyyy}"))
  (setq mm (or mm "{mm}"))
  (setq dd (or dd "{dd}"))
  (setq msg (or msg "{msg}"))
  (setq txtstem (or txtstem "{txtstem}"))
  (apply
   'find-elinks
   `((find-emacs-tangents-links ,yyyy ,mm ,dd ,msg ,txtstem ,@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-emacs-tangents-links "2020" "10" "05" "msg00000" "txts2ETp920ql")
     (find-emacs-tangents-links "2018" "01" "29" "msg00025" "txtJ1ftXqItdm")
     (find-efunction 'find-emacs-tangents-links)
     ""
     ,(ee-template0 "\
# https://sachachua.com/blog/{yyyy}/
# https://sachachua.com/blog/{yyyy}/{mm}/
# https://sachachua.com/blog/{yyyy}/{mm}/{yyyy}-{mm}-{dd}-emacs-news/
# https://lists.gnu.org/archive/html/emacs-tangents/{yyyy}-{mm}/
# https://lists.gnu.org/archive/html/emacs-tangents/{yyyy}-{mm}/{msg}.html

 (eepitch-shell)
 (eepitch-kill)
 (eepitch-shell)
# (find-fline \"~/usrc/emacs-tangents/\")
# (find-fline \"~/usrc/emacs-tangents/{yyyy}-{mm}-{dd}-emacs-news.org\")

mkdir -p ~/usrc/emacs-tangents/
cd       ~/usrc/emacs-tangents/
# rm -v     {yyyy}-{mm}-{dd}-emacs-news.org
wget -nc -O {yyyy}-{mm}-{dd}-emacs-news.org \\
  https://lists.gnu.org/archive/html/emacs-tangents/{yyyy}-{mm}/{txtstem}.txt
")
     )
   pos-spec-list))




;; «find-eeit-links»  (to ".find-eeit-links")
;; Skel: (find-find-links-links-new "eeit" "majormode" "majormodestr eeitfunstr eeitfun")
;; See:  (find-eepitch-intro "3.1. `find-eeit-links'")
;; Test: (find-eeit-links 'lua-mode)
;;
(defun find-eeit-links (&optional majormode &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks for eeit."
  (interactive)
  (setq majormode (or majormode major-mode))
  (let* ((majormodestr (symbol-name majormode))
         (eeitfunstr (concat "ee-insert-test-" majormodestr))
         (eeitfun (intern eeitfunstr)))
    (apply
     'find-elinks-elisp
     `((find-eeit-links ',majormode ,@pos-spec-list)
       ;; Convention: the first sexp always regenerates the buffer.
       ;; ""
       ,(ee-template0 "\
;; (find-efunction 'find-eeit-links)
;; (find-eepitch-intro \"3. Test blocks\")
;; (find-eepitch-intro \"3.1. `find-eeit-links'\")
;; (find-eev \"eev-testblocks.el\" \"examples\")

;; Current definition:
;; (find-efunction              '{eeitfun})
;; (find-efunctionpp            '{eeitfun})
;; (find-epp (ee-defun-sexp-for '{eeitfun}))


;; <{eeitfunstr}>
;;
(defun {eeitfunstr} ()
  (interactive)
  (insert (ee-adjust-red-stars (format \"
--[[
 (eepitch-lua51)
 (eepitch-kill)
 (eepitch-lua51)
dofile \\\"%s\\\"

--]]
\" (buffer-name)))))

;; Test:
;; ({eeitfunstr})

")
       )
     pos-spec-list)))




;;;  _____   __  ___     _           
;;; |_   _|__\ \/ / |   (_)_   _____ 
;;;   | |/ _ \\  /| |   | \ \ / / _ \
;;;   | |  __//  \| |___| |\ V /  __/
;;;   |_|\___/_/\_\_____|_| \_/ \___|
;;;                                  
;; «find-texlive-links»  (to ".find-texlive-links")

(defun find-texlive-links (&optional date &rest pos-spec-list)
"Visit a temporary buffer containing an e-script for installing texlive from upstream."
  (interactive)
  (setq date (or date "{date}"))
  (apply 'find-elinks
   `((find-texlive-links ,date ,@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-texlive-links "20210816")
     (find-efunction 'find-texlive-links)
     ""
     ,(ee-template0 "\
# https://www.tug.org/texlive/
# https://www.tug.org/texlive/acquire-netinstall.html
# https://www.tug.org/texlive/quickinstall.html
# http://mirror.ctan.org/systems/texlive/tlnet/install-tl-unx.tar.gz
#   (find-fline \"$S/http/mirror.ctan.org/systems/texlive/tlnet/\")
#   (find-fline \"$S/http/mirror.ctan.org/systems/texlive/tlnet/install-tl-unx.tar.gz\")
# https://www.tug.org/texlive/doc/install-tl.html
# (find-fline \"~/usrc/\" \"install-tl-\")
# (find-fline \"~/.texlive2018/\")
# (find-fline \"~/.texlive2019/\")
# (find-fline \"~/.texlive2021/\")
# (find-fline \"/usr/local/texlive/2018/\")
# (find-fline \"/usr/local/texlive/2019/\")
# (find-fline \"/usr/local/texlive/2019/\" \"install-tl.log\")
# (find-fline \"/usr/local/texlive/2019/release-texlive.txt\")

 (eepitch-shell2)
 (eepitch-kill)
 (eepitch-shell2)
# rm -rfv ~/.texlive2021/
# sudo rm -rfv /usr/local/texlive/2021/

mkdir -p $S/http/mirror.ctan.org/systems/texlive/tlnet/
cd       $S/http/mirror.ctan.org/systems/texlive/tlnet/
rm -fv   $S/http/mirror.ctan.org/systems/texlive/tlnet/install-tl-unx.tar.gz
wget      http://mirror.ctan.org/systems/texlive/tlnet/install-tl-unx.tar.gz
echo      http://mirror.ctan.org/systems/texlive/tlnet/install-tl-unx.tar.gz >> ~/.psne.log
# (find-fline \"$S/http/mirror.ctan.org/systems/texlive/tlnet/install-tl-unx.tar.gz\")
# ^ Check the date here and adjust the {<}date{>} parameter of the template

rm -Rfv ~/usrc/install-tl-{date}/
mkdir   ~/usrc/
tar  -C ~/usrc/ -xvzf \
  $S/http/mirror.ctan.org/systems/texlive/tlnet/install-tl-unx.tar.gz
cd      ~/usrc/install-tl-{date}/
# sudo ./install-tl
sudo ./install-tl -select-repository

# (code-c-d \"tlinstall\" \"~/usrc/install-tl-{date}/\")
# (find-tlinstallfile \"\")
# (find-tlinstallfile \"install-tl.log\")
# (find-tlinstallfile \"install-tl\")
# https://www.tug.org/texlive/doc/install-tl.html

")
     )
   pos-spec-list))

;; Test: (find-texlive-links)




;;;                      _                                     
;;;  _ __   _____      _| |__  _ __ _____      _____  ___ _ __ 
;;; | '_ \ / _ \ \ /\ / / '_ \| '__/ _ \ \ /\ / / __|/ _ \ '__|
;;; | | | |  __/\ V  V /| |_) | | | (_) \ V  V /\__ \  __/ |   
;;; |_| |_|\___| \_/\_/ |_.__/|_|  \___/ \_/\_/ |___/\___|_|   
;;;                                                            
;; «find-newbrowser-links»  (to ".find-newbrowser-links")
;; Skel: (find-find-links-links-new "newbrowser" "browser binary b" "")
;; Test: (find-newbrowser-links "googlechrome" "google-chrome" "g")
;;
(defun find-newbrowser-links (&optional browser binary b &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks for newbrowser."
  (interactive)
  (setq browser (or browser "{browser}"))
  (setq binary (or binary "{binary}"))
  (setq b (or b "{b}"))
  (apply
   'find-elinks-elisp
   `((find-newbrowser-links ,browser ,binary ,b ,@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-newbrowser-links)
     ""
     ,(ee-template0 "\
;; This block defines `find-{browser}', `br{b}', `br{b}l', and `br{b}d'.
;; See: (find-eev-quick-intro \"3.1. Non-elisp hyperlinks\")
;;      (find-brxxx-intro \"3. The `d' variants\")
;;      (find-brxxx-intro \"5. `code-brurl'\")
;;      (find-eev \"eev-brxxx.el\" \"code-brxxxs\")
;;
(defun find-{browser} (url) (find-bgprocess `(\"{binary}\" ,url)))
;;
;; (find-code-brurl 'find-{browser}  :remote 'br{b}  :local 'br{b}l  :dired 'br{b}d)
        (code-brurl 'find-{browser}  :remote 'br{b}  :local 'br{b}l  :dired 'br{b}d)



;; This block defines `find-{browser}-page'.
;; See: (find-eev \"eev-pdflike.el\" \"find-googlechrome-page\")
;;
(defun ee-find-{browser}-page (fname &optional page)
  `(\"{binary}\" ,(ee-fname-page-to-url fname page)))
;;
;; (find-code-pdfbackend \"{browser}-page\")
        (code-pdfbackend \"{browser}-page\")



;; Run the `defalias' below if you want to make
;; `find-pdf-page' use `find-{browser}-page'.
;; See: (find-eev \"eev-pdflike.el\" \"change-default-viewer\")
;;
(defalias 'find-pdf-page 'find-{browser}-page)



;; Tests:
;; (find-{browser} \"http://angg.twu.net/#eev\")
;; (find-{browser}-page \"~/Coetzee99.pdf\")
;; (find-{browser}-page \"~/Coetzee99.pdf\" 3)
;; (find-pdf-page \"~/Coetzee99.pdf\" 3)
")
     )
   pos-spec-list))




;;;   ___        ___  
;;;  / _ \__  __/ _ \ 
;;; | | | \ \/ / | | |
;;; | |_| |>  <| |_| |
;;;  \___//_/\_\\___/ 
;;;                   
;; «ee-0x0-upload-region»  (to ".ee-0x0-upload-region")
;; Needs: https://melpa.org/#/0x0
;;   See: https://lists.gnu.org/archive/html/eev/2021-08/msg00000.html
;;
(defvar ee-0x0-url nil
  "The last URL generated by a call to `ee-0x0-upload-region'.")

(defun ee-0x0-upload (&rest rest)
  "This should work like `0x0-upload'. Redefine if needed."
  (apply '0x0-upload rest))

;; If you are using a version of 0x0 that doesn't have `0x0-upload'
;; then try using the hack below. See:
;;   https://gitlab.com/willvaughn/emacs-0x0/-/issues/2
;;
;; Based on: (find-efunction '0x0-upload-kill-ring)
' (defun ee-0x0-upload (b e server-old)
    "This is a hack. See the source code."
    (let ((server (0x0--choose-server))
	  (region-contents (buffer-substring-no-properties b e)))
      (with-temp-buffer
	(insert region-contents)
	(let* ((file-name (or (buffer-file-name) (buffer-name) "kill-ring.txt"))
               (bounds (0x0--make-bounds))
               (size (0x0--bounds-size bounds))
               (resp (0x0--send server file-name bounds)))
	  (0x0--handle-resp server size resp)))))

(defun ee-0x0-upload-region (b e)
  "Upload the current region to 0x0 and show some elisp hyperlinks.
I use this mainly on IRC chats, to send elisp snippets to people
who use eev. I use this function aliased to `u0', with:

  (defalias 'u0 'ee-0x0-upload-region)

If I mark the region with the snippet and run `M-x u0', `u0'
uploads the snippet to https://0x0.st/ and shows some sexps in a
temporary buffer; the two main sexps in that temporary buffer
there will be things like:

  (find-wget \"https://0x0.st/-J1W.el\")
  (find-wget-elisp \"https://0x0.st/-J1W.el\")

The one that starts with `find-wget-elisp' downloads the URL with
wget and runs `emacs-lisp-mode' on the resulting \"*wget: URL*\"
buffer. If the other person on IRC is using some IRC client that
runs in Emacs I can send the find-wget-elisp sexp to her and she
only needs to type `M-e' on it to access the elisp code that I
sent."
  (interactive "r")
  (ee-0x0-upload b e '0x0)
  (setq ee-0x0-url (ee-last-kill))
  (find-0x0-links))

;; «find-0x0-links»  (to ".find-0x0-links")
;; Skel: (find-find-links-links-new "0x0" "url" "")
;;
(defun find-0x0-links (&optional url &rest pos-spec-list)
"Visit a temporary buffer containing hyperlinks to an upload to 0x0.st.
This function is used by `ee-0x0-upload-region'."
  (interactive)
  (setq url (or url ee-0x0-url))
  (apply
   'find-elinks
   `((find-0x0-links ,url ,@pos-spec-list)
     (find-0x0-links "{url}" ,@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-0x0-links)
     ""
     ,(ee-template0 "\
{url}
(find-wget \"{url}\")
(find-wget-elisp \"{url}\")
")
     )
   pos-spec-list))




;; «find-eepitch-bullet-links»  (to ".find-eepitch-bullet-links")
;; «find-red-star-links»        (to ".find-red-star-links")
;; Skel: (find-find-links-links-new "red-star" "" "")
;; Test: (find-red-star-links)
;;
(defalias 'find-eepitch-bullet-links 'find-red-star-links)
(defun find-red-star-links (&rest pos-spec-list)
"Show code that makes eepitch use red bullets instead of red stars."
  (interactive)
  (apply
   'find-elinks-elisp
   `((find-red-star-links ,@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-red-star-links)
     ;; ""
     ,(ee-template0 "\
;; The code below was based on:
;;   https://lists.gnu.org/archive/html/help-gnu-emacs/2021-05/msg01080.html
;;   https://lists.gnu.org/archive/html/help-gnu-emacs/2021-05/msg01079.html
;; Note that the default regexes for eepitch accept both the red
;; stars and the bullets - chars 15 and 8226 respectively...
;; See: (find-eev \"eepitch.el\" \"glyphs\")
;;      (find-eev \"eepitch.el\" \"eepitch\" \"eepitch-regexp\")
;;      (find-eev-quick-intro \"6.3. Creating eepitch blocks: `M-T'\")
;; And try: (insert \"\\n;; \" 15 8226)



;; Run this to make the bullets use the default face:
\(eepitch-set-glyph0 ?• nil)
;;
;; Run this to make the bullets appear in the same face as the red stars:
\(eepitch-set-glyph0 ?• ?• 'eepitch-star-face)
;;
;; You'll need to force a redisplay to see the change.
;; One way to do that is with `C-l' (`recenter-top-bottom').


;; Most of the functions in eev that generate text with red stars
;; use the function `ee-adjust-red-stars' to replace the red
;; stars in the generated text by some non-default character if
;; needed. Use the first defun below to use red stars, and use
;; the second one to use bullets.
;;  See: (find-eev \"eepitch.el\" \"ee-adjust-red-stars\")
;;       (find-eval-intro \"3. What to execute, and in what order\")
;; Test: (ee-adjust-red-stars \"foobar\")
;;
\(defun ee-adjust-red-stars (str) str)
\(defun ee-adjust-red-stars (str) (replace-regexp-in-string \"\" \"•\" str))



;; To make eepitch blocks use the red bullets by default,
;; add this block to your ~/.emacs.  Note that this will make
;; bullets appear in red in other places too, like in info manuals -
;; for example here: (find-enode \"Using Region\")
;; See: (find-red-star-links)
;;
\(eepitch-set-glyph0 ?• ?• 'eepitch-star-face)
\(defun ee-adjust-red-stars (str) (replace-regexp-in-string \"\" \"•\" str))
")
     )
   pos-spec-list))

;; «ee-use-red-stars»  (to ".ee-use-red-stars")
;; «ee-use-red-bullets»  (to ".ee-use-red-bullets")

(defun ee-use-red-stars ()
  "See: (find-red-star-links)"
  (interactive)
  (eepitch-set-glyph0 ?• nil)
  (defun ee-adjust-red-stars (str) str))

(defun ee-use-red-bullets ()
  "See: (find-red-star-links)"
  (interactive)
  (eepitch-set-glyph0 ?• ?• 'eepitch-star-face)
  (defun ee-adjust-red-stars (str) (replace-regexp-in-string "" "•" str)))





;; «find-angg-es-links»  (to ".find-angg-es-links")
;; Skel: (find-find-links-links-new "angg-es" "" "")
;; Test: (find-angg-es-links)
;;
(defun find-angg-es-links (&rest pos-spec-list)
"Show an e-script for configuring `find-angg' and `find-es'."
  (interactive)
  (apply
   'find-elinks-elisp
   `((find-angg-es-links ,@pos-spec-list)
     ;; Convention: the first sexp always regenerates the buffer.
     (find-efunction 'find-angg-es-links)
     (find-eev-quick-intro "9. Shorter hyperlinks")
     (find-eev-quick-intro "9.1. `code-c-d'")
     (find-eev-quick-intro "9.2. Extra arguments to `code-c-d'" "to anchors")
     ""
     ,(ee-template0 "\


;; The `progn' below is how I (edrx) define `find-angg' and
;; `find-es' in my machine to point to local files. Note that the
;; sexps
;;
;;   (find-angg \"foo\" \"anchor\")
;;   (find-es   \"foo\" \"anchor\")
;;
;; search for anchor \"anchor\" in the files \"~/foo\" and
;; \"~/e/foo.e\" respectively... in 1996, when I wrote `find-es',
;; I had several functions like it, that appended arbitrary
;; prefixes _and suffixes_ to their first arguments. I stopped
;; using all of them except `find-es' - that is a kind of
;; living fossil.
;;
(progn

  (code-c-d \"angg\" \"~/\" :anchor :grep)
  (code-c-d \"es\"   \"$ES/\")
  (defun find-es (stem &rest rest)
    (apply 'find-anchor (ee-esfile (concat stem \".e\")) rest))

)



;; The `progn' below defines versions of `find-angg' and
;; `find-es' that use `find-wget' to access the
;; public copies of my files at angg.twu.net:
;;
(progn

  (defun find-angg (fname &rest rest)
    (apply 'find-wgeta (format \"http://angg.twu.net/%s\" fname) rest))
  (defun find-es (fname &rest rest)
    (apply 'find-wgeta (format \"http://angg.twu.net/e/%s.e\" fname) rest))

)



;; Tests:
;; (find-angg \"e/bullseye.e\")
;; (find-angg \"e/bullseye.e\" \"2021aug16\")
;; (find-es     \"bullseye\")
;; (find-es     \"bullseye\"   \"2021aug16\")
")
     )
   pos-spec-list))



;; «find-1stclassvideo-links»  (to ".find-1stclassvideo-links")
;; Skel: (find-find-links-links-new "1stclassvideo" "c" "")
;; Skel: (find-find-links-links-new "1stclassvideo" "c" "title mp4 yp page lang")
;;  See: (find-eev "eev-videolinks.el" "first-class-videos")
;;       (find-eev "eev-videolinks.el" "second-class-videos")
;; Tests: (find-1stclassvideo-links "eev2019")
;;        (find-1stclassvideo-links "eev2020")
;;
(defun find-1stclassvideo-links (&optional c &rest pos-spec-list)
  "Visit a temporary buffer containing hyperlinks for eevvideo-1stclass."
  (interactive (list (ee-1stclassvideo-around-point-ask)))
  (setq c (or c "{c}"))
  (let* ((title   (ee-1stclassvideos-field c :title))
	 (mp4     (ee-1stclassvideos-field c :mp4))
	 (yt      (ee-1stclassvideos-field c :yt))
	 (page    (ee-1stclassvideos-field c :page))
	 (lang    (ee-1stclassvideos-field c :lang))
	 (mp4stem (ee-1stclassvideos-mp4stem c))
	 (hash    (ee-1stclassvideos-hash c)))
    (apply
     'find-elinks-elisp
     `((find-1stclassvideo-links ,c ,@pos-spec-list)
       ;; Convention: the first sexp always regenerates the buffer.
       (find-efunction 'find-1stclassvideo-links)
       ""
       ,(ee-template0 "\
;; Title: {title}
;; MP4:   {mp4}
;; YT:    {yt}
;; Page:  {page}
;; Info:  (find-eev \"eev-videolinks.el\" \"{c}\")
;;            (find-1stclassvideo-links \"{c}\")
;;
;; Index: http://angg.twu.net/.emacs.videos.html#{c}
;;         (find-angg        \".emacs.videos\"    \"{c}\")

;; See:
;; (find-eev \"eev-videolinks.el\" \"first-class-videos\")
;; (find-eev \"eev-videolinks.el\" \"second-class-videos\")

;; Play:
;; (find-{c}video \"0:00\")

;; Other places with info about this video:
;; (find-angg \".emacs.templates\" \"eev-videos-data\" \"{c}\")
;; http://angg.twu.net/.emacs.templates.html#eev-videos-data
;; (find-videos-intro \"1. Some videos\" \"{c}\")

;; Definition of the function:
;; (find-eev \"eev-videolinks.el\" \"first-class-videos\")
;; (find-eev \"eev-videolinks.el\" \"find-{c}video\")
;;               (find-efunction 'find-{c}video)

;; <find-{c}video>
;; Skel: (find-1stclassvideo-links \"{c}\")
;; Tests: (find-{c}video \"0:00\")
;;        (find-efunctiondescr 'find-{c}video)
(defun find-{c}video (&optional time &rest rest)
  \"Play one of the video tutorials of eev starting at TIME.
See: (find-eev \\\"eev-videolinks.el\\\" \\\"{c}\\\")
     http://angg.twu.net/eev-current/eev-videolinks.el.html#eev2020
     for more info on this particular video,
and: (find-video-links-intro \\\"7. \\\" \\\"find-eev-video\\\")
 or: http://angg.twu.net/eev-intros/find-video-links-intro.html#7
     for more info on these video tutorials.\"
  (interactive)
  (find-eev-video \"{mp4stem}\" \"{hash}\" time))
")
       )
     pos-spec-list)))







(provide 'eev-tlinks)



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