Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- This file:
--   http://anggtwu.net/blogme3/sandwiches-defs.lua.html
--   http://anggtwu.net/blogme3/sandwiches-defs.lua
--          (find-angg "blogme3/sandwiches-defs.lua")
-- Author: Eduardo Ochs <[email protected]>
-- Version: 2022nov05

-- This file defines how many kinds of sexp hyperlinks are to be
-- htmlized, using the classes SexpIntervals, SexpTarget, SexpHead,
-- and HtmlizeLine of:
--
--   (find-blogme3 "sandwiches.lua")
--
-- This file supersedes my older methods of htmlizing lines of
-- e-scripts, but it not yet default. To use it, run this:
--
--   require "sandwiches-defs"
--   use_sand_htmlizeline()


-- «.get_1stclassvideo_field»		(to "get_1stclassvideo_field")
-- «.get_1stclassvideo_field-tests»	(to "get_1stclassvideo_field-tests")
-- «.sexp_to_target»			(to "sexp_to_target")
-- «.sexp_to_target-tests»		(to "sexp_to_target-tests")
-- «.code_c_m_bs»			(to "code_c_m_bs")
-- «.code_c_d_anggs»			(to "code_c_d_anggs")
-- «.code_c_d_remotes»			(to "code_c_d_remotes")
-- «.code_intros»			(to "code_intros")
-- «.code_intros-tests»			(to "code_intros-tests")
-- «.code_helponlys»			(to "code_helponlys")
-- «.find-node»				(to "find-node")
-- «.find-node-test»			(to "find-node-test")
-- «.to»				(to "to")
-- «.to-test»				(to "to-test")
-- «.code-pdf-page»			(to "code-pdf-page")
-- «.code-pdf-page-tests»		(to "code-pdf-page-tests")
-- «.code-ytvideo»			(to "code-ytvideo")
-- «.code-ytvideo-tests»		(to "code-ytvideo-tests")
-- «.find-youtubedl-links»		(to "find-youtubedl-links")
-- «.find-youtubedl-links-tests»	(to "find-youtubedl-links-tests")
--
-- «.code-eevvideo»			(to "code-eevvideo")
-- «.code-eevvideo-tests»		(to "code-eevvideo-tests")
-- «.code_eevshortvideo»		(to "code_eevshortvideo")
-- «.code_eevshortvideos»		(to "code_eevshortvideos")
-- «.code_eevshortvideo-tests»		(to "code_eevshortvideo-tests")
-- «.find-eevvideo-links»		(to "find-eevvideo-links")
-- «.find-1stclassvideos»		(to "find-1stclassvideos")
-- «.find-1stclassvideo-links»		(to "find-1stclassvideo-links")
-- «.find-1stclassvideo-links-tests»	(to "find-1stclassvideo-links-tests")
-- «.find-1stclassvideolsubs»		(to "find-1stclassvideolsubs")
-- «.find-1stclassvideolsubs-tests»	(to "find-1stclassvideolsubs-tests")
-- «.find-wgeteevsubtitles-links»	(to "find-wgeteevsubtitles-links")
-- «.find-wgeteevsubtitles-links-tests»	(to "find-wgeteevsubtitles-links-tests")
--
-- «.code_1stclassvideo»		(to "code_1stclassvideo")
-- «.code_1stclassvideo-tests»		(to "code_1stclassvideo-tests")
--
-- «.find-TH»				(to "find-TH")
-- «.find-TH-tests»			(to "find-TH-tests")
-- «.find-maximamsg»			(to "find-maximamsg")
-- «.find-maximamsg-tests»		(to "find-maximamsg-tests")
-- «.rstdoc»				(to "rstdoc")
-- «.find-pydoc»			(to "find-pydoc")
-- «.find-pydoc-tests»			(to "find-pydoc-tests")
-- «.use_sand_htmlizeline»		(to "use_sand_htmlizeline")
-- «.use_sand_htmlizeline-tests»	(to "use_sand_htmlizeline-tests")
-- «.Short_»				(to "Short_")
-- «.Short_-tests»			(to "Short_-tests")
-- «.code_helponly2»			(to "code_helponly2")
-- «.code_helponly2-tests»		(to "code_helponly2-tests")
-- «.agda»				(to "agda")
-- «.agda-tests»			(to "agda-tests")
-- «.find-hoogle»			(to "find-hoogle")
-- «.find-hoogle-tests»			(to "find-hoogle-tests")
-- «.find-cabal-links»			(to "find-cabal-links")
-- «.find-cabal-unpack»			(to "find-cabal-unpack")
-- «.find-cabal-links-tests»		(to "find-cabal-links-tests")
-- «.find-cabal-unpack-tests»		(to "find-cabal-unpack-tests")
-- «.code_helponly2_lines»		(to "code_helponly2_lines")
-- «.find-maximanode»			(to "find-maximanode")
-- «.find-maximanode-tests»		(to "find-maximanode-tests")
-- «.find-yttranscript-links»		(to "find-yttranscript-links")
-- «.find-yttranscript-links-tests»	(to "find-yttranscript-links-tests")
-- «.find-gitk»				(to "find-gitk")
-- «.find-gitk-tests»			(to "find-gitk-tests")
-- «.code_lsubs»			(to "code_lsubs")
-- «.code_lsubs-tests»			(to "code_lsubs-tests")
-- «.code-lsubs»			(to "code-lsubs")
-- «.code-lsubs-tests»			(to "code-lsubs-tests")
-- «.find-clhsdoci»			(to "find-clhsdoci")
-- «.find-clhsdoci-tests»		(to "find-clhsdoci-tests")
-- «.find-anchor»			(to "find-anchor")
-- «.find-anchor-tests»			(to "find-anchor-tests")
-- «.code-etex-tla»			(to "code-etex-tla")
-- «.code-etex-tla-tests»		(to "code-etex-tla-tests")
-- «.code-etex-tlas-load»		(to "code-etex-tlas-load")



require "sandwiches"        -- (find-blogme3 "sandwiches.lua")
require "sandwiches-videos" -- (find-blogme3 "sandwiches-videos.lua")
require "cruft-jan2024"     -- (find-blogme3 "cruft-jan2024.lua")

get_mp4stem = function (c)
    local video = sandwiches_videos[c]
    local mp4   = video and video.mp4
    return mp4 and mp4:match("/([^/]+)%.mp4")
  end

-- «get_1stclassvideo_field»  (to ".get_1stclassvideo_field")
get_1stclassvideo_field = function (c, field)
    local entry = sandwiches_videos[c]
    return entry and entry[field]
  end

get_1stclassvideo_hash = function (c)
    local yturl = get_1stclassvideo_field(c, "yt")
    return yturl and (yturl:gsub("^.-v=", ""))
  end

get_1stclassvideo_yturl = function (c, time)
    local hash = get_1stclassvideo_hash(c)
    if not hash then return end
    return youtube_make_url(hash, time)
  end

get_1stclassvideo_hsubs = function (c, time)
    local baseurl = get_1stclassvideo_field(c, "hsubs")
    if not baseurl then return end
    if time then return baseurl:match("^.-#")..time end
    return baseurl
  end

get_1stclassvideo_lsubs = function (c)
    local mp4stem = get_mp4stem(c)
    if not mp4stem then return end
    return format("http://anggtwu.net/SUBTITLES/%s.lua.html", mp4stem)
  end

get_1stclassvideo_def = function (c)
    if sandwiches_videos[c] then 
      return "http://anggtwu.net/eev-current/eev-videolinks.el.html#" .. c
    end
  end

get_1stclassvideo_index = function (c)
    if get_1stclassvideo_field(c, "index") then
      return "http://anggtwu.net/.emacs.videos.html#" .. c
    end
  end


-- «get_1stclassvideo_field-tests»  (to ".get_1stclassvideo_field-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
Path.addLUAtopath()
require "Tos3"               -- (find-angg "LUA/Tos3.lua")
dofile "sandwiches-defs.lua"
PPI(sandwiches_videos)
PPI(sandwiches_videos.oficina2021a)
PPI(sandwiches_videos.oficina2021a.mp4)
= get_1stclassvideo_field("foo", "mp4")
= get_1stclassvideo_field("eev2021", "mp4")
= get_1stclassvideo_field("eev2021", "hsubs")
= get_1stclassvideo_hsubs("eev2021")
= get_1stclassvideo_hsubs("eev2021", "02:34")
= get_1stclassvideo_lsubs("eev2021", "02:34")
= get_1stclassvideo_yturl("eev2021")
= get_1stclassvideo_yturl("eev2021", "02:34")
= get_1stclassvideo_hsubs("foo", "02:34")
= get_1stclassvideo_lsubs("foo", "02:34")
= get_1stclassvideo_def  ("2022tikz")
= get_1stclassvideo_index("2022tikz")
= _SH["find-eev2021video"]
PPI(_SH["find-eev2021video"])


--]]





-- «sexp_to_target»  (to ".sexp_to_target")
-- (find-blogme3 "sandwiches.lua")
-- (find-blogme3 "sandwiches.lua" "SexpIntervals")
-- (find-blogme3 "sandwiches.lua" "SexpIntervals" "target_st =")
--
sexp_to_target_si0 = function (linestr)    -- for debugging
    local si = SexpIntervals.from(linestr)
    return si
  end
sexp_to_target_si = function (linestr)     -- for debugging
    local si = SexpIntervals.from(linestr)
    if not si then print("Bad linestr: "..linestr) end
    si:head_apply()
    return si
  end
sexp_to_target_st = function (linestr)     -- for debugging
    local si = SexpIntervals.from(linestr)
    local retval
    if not pcall(function ()
        si:head_apply()
        retval = si:target_st()
      end)
    then error("Bad linestr: "..linestr)
    end
    return retval
  end
sexp_to_target = function (linestr, altname)
    return sexp_to_target_st(linestr, altname):url()
  end

-- «sexp_to_target-tests»  (to ".sexp_to_target-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
-- (find-blogme3 "sandwiches.lua" "SexpIntervals")
-- (find-blogme3 "sandwiches.lua" "SexpIntervals" "target_st =")

code_intro("foobar")
= sexp_to_target_st  [[ (foo)                            ]]    --> error
= sexp_to_target_si0 [[ (find-foobar-intro "42.3. plic") ]]
= sexp_to_target_si  [[ (find-foobar-intro "42.3. plic") ]]
= sexp_to_target_st  [[ (find-foobar-intro "42.3. plic") ]]
= sexp_to_target     [[ (find-foobar-intro "42.3. plic") ]]
= sexp_to_target_si  [[ (find-lua51manual "#dofile") ]]
= sexp_to_target_st  [[ (find-lua51manual "#dofile") ]]
= sexp_to_target     [[ (find-lua51manual "#dofile") ]]
= sexp_to_target     [[ (eepitch-shell) ]]

--]==]




-- «code_c_m_bs»  (to ".code_c_m_bs")
-- See: (find-blogme3 "sandwiches.lua" "code_c_m_b")
-- Some tests:
--   (find-node "(emacs)Lisp Eval")
--         (find-enode "Lisp Eval")
--   (find-node "(elisp)Lisp Data Types")
--        (find-elnode "Lisp Data Types")
--   (find-node "(eshell)Built-ins")
--     (find-eshellnode "Built-ins")
--   (find-node "(cl)Loop Facility")
--     (find-clnode "Loop Facility")
--   (find-node "(org)Publishing")
--     (find-orgnode "Publishing")

code_c_m_b("e",   "emacs", "https://www.gnu.org/software/emacs/manual/html_node/emacs/")
code_c_m_b("el",  "elisp", "https://www.gnu.org/software/emacs/manual/html_node/elisp/")
code_c_m_b("eli", "eintr", "https://www.gnu.org/software/emacs/emacs-lisp-intro/html_node/")
code_c_m_b("efaq", "efaq", "https://www.gnu.org/software/emacs/manual/html_node/efaq/")
code_c_m_b("cl",   "cl",   "https://www.gnu.org/software/emacs/manual/html_node/cl/")
code_c_m_b("calc", "calc", "https://www.gnu.org/software/emacs/manual/html_node/calc/")
code_c_m_b("eshell", "eshell", "https://www.gnu.org/software/emacs/manual/html_node/eshell/")
code_c_m_b("eieio",  "eieio",  "https://www.gnu.org/software/emacs/manual/html_node/eieio/")

code_c_m_b("gnus", "gnus", "http://www.gnu.org/software/emacs/manual/html_node/gnus/")
code_c_m_b("message",  "message",  "http://www.gnu.org/software/emacs/manual/html_node/message/")
code_c_m_b("woman",    "woman",    "http://www.gnu.org/software/emacs/manual/html_node/woman/")
code_c_m_b("rcirc",    "rcirc",    "http://www.gnu.org/software/emacs/manual/html_node/rcirc/")
code_c_m_b("erc",      "erc",      "https://www.gnu.org/software/emacs/manual/html_node/erc/")
code_c_m_b("org",      "org",      "http://www.gnu.org/software/emacs/manual/html_node/org/")

code_c_m_b("gst",      "gst",      "http://www.gnu.org/software/smalltalk/manual/html_node/")
code_c_m_b("gstbase",  "gst-base", "http://www.gnu.org/software/smalltalk/manual-base/html_node/")
code_c_m_b("gstlibs",  "gst-libs", "http://www.gnu.org/software/smalltalk/manual-libs/html_node/")

code_c_m_b("pclcvs",   "pcl-cvs",  "http://www.gnu.org/software/emacs/manual/html_node/pcl-cvs/")
code_c_m_b("autotype", "autotype", "http://www.gnu.org/software/emacs/manual/html_node/autotype/")
code_c_m_b("libc", "libc", "http://www.gnu.org/software/libc/manual/html_node/")
code_c_m_b("make", "make", "http://www.gnu.org/software/make/manual/html_node/")
code_c_m_b("grub", "grub", "https://www.gnu.org/software/grub/manual/grub/html_node/")
code_c_m_b("gawk", "gawk", "http://www.gnu.org/software/gawk/manual/html_node/")
code_c_m_b("texi", "texinfo", "http://www.gnu.org/software/texinfo/manual/texinfo/html_node/")
code_c_m_b("gcc",  "gcc-4.1", "http://gcc.gnu.org/onlinedocs/gcc-4.2.2/gcc/")
code_c_m_b("coreutils", "coreutils", "http://www.gnu.org/software/coreutils/manual/html_node/")
code_c_m_b("bash", "bash",    "http://www.gnu.org/software/bash/manual/html_node/")
code_c_m_b("bash", "bashref", "http://www.gnu.org/software/bash/manual/html_node/")
code_c_m_b("wget", "wget",    "http://www.gnu.org/software/wget/manual/html_node/")
code_c_m_b("slime", "slime",  "http://common-lisp.net/project/slime/doc/html/")
code_c_m_b("slime", "slime",  "https://slime.common-lisp.dev/doc/html/")
code_c_m_b("bison", "bison",  "http://www.gnu.org/software/bison/manual/html_node/")
code_c_m_b("octave", "octave",  "https://docs.octave.org/interpreter/")
code_c_m_b("rcirc",  "rcirc",   "http://www.gnu.org/software/emacs/manual/html_node/rcirc/")
code_c_m_b("binutils", "binutils", "http://sourceware.org/binutils/docs/binutils/")
code_c_m_b("gdb", "gdb", "http://sourceware.org/gdb/download/onlinedocs/gdb/")
code_c_m_b("parted", "parted",  "https://www.gnu.org/software/parted/manual/html_node/")

-- «code_c_d_anggs»  (to ".code_c_d_anggs")
-- (find-blogme3 "angglisp.lua" "code_c_d_angg")

code_c_d_angg("angg",       "")
code_c_d_angg("es",         "e/", ".e.html")
code_c_d_angg("LATEX",      "LATEX/")
code_c_d_angg("dednat4",    "dednat4/")
code_c_d_angg("dn4",        "dednat4/")
code_c_d_angg("dn4ex",      "dednat4/examples/")
code_c_d_angg("dn5",        "dednat5/")
code_c_d_angg("dn6",        "LATEX/dednat6/")
code_c_d_angg("dednat6",    "dednat6/")
code_c_d_angg("dednat6lua", "dednat6/dednat6/")
code_c_d_angg("blogme",     "blogme/")
code_c_d_angg("blogme3",    "blogme3/")
code_c_d_angg("blogme4",    "blogme4/")
code_c_d_angg("eev",        "eev-current/")
code_c_d_angg("eevgit",     "GIT/")
code_c_d_angg("flua",       "flua/")
code_c_d_angg("rubyforth",  "rubyforth/")
code_c_d_angg("vtutil",     "vtutil/")
code_c_d_angg("vtutil4",    "vtutil4/")
code_c_d_angg("RETRO",      "RETRO/")
code_c_d_angg("gab",        "gab/")
code_c_d_angg("eevvideos",  "eev-videos/")
code_c_d_angg("quadr",      "quadradinho/")
code_c_d_angg("ydb",        "youtube-db/")
code_c_d_angg("fbcache",    "fbcache/")
code_c_d_angg("clg",        "2019-CLG/")
code_c_d_angg("books",      "books/")
code_c_d_angg("SUBS",       "SUBTITLES/")
code_c_d_angg("emlua",      "emlua/")
code_c_d_angg("repl3",      "LUA/")
code_c_d_angg("showconses", "show-conses/")
code_c_d_angg("lisptree",   "lisptree/")
code_c_d_angg("myqdraw",    "myqdraw/")


-- «code_c_d_remotes»  (to ".code_c_d_remotes")
-- (find-blogme3 "angglisp.lua" "code_c_d_remotes")
--
code_c_d_remote("lua40manual", "http://www.lua.org/manual/4.0/manual.html")
code_c_d_remote("lua50manual", "http://www.lua.org/manual/5.0/manual.html")
code_c_d_remote("lua51manual", "http://www.lua.org/manual/5.1/manual.html")
code_c_d_remote("lua52manual", "http://www.lua.org/manual/5.2/manual.html")
code_c_d_remote("lua53manual", "http://www.lua.org/manual/5.3/manual.html")
code_c_d_remote("lua54manual", "http://www.lua.org/manual/5.4/manual.html")
code_c_d_remote("luamanual",   "http://www.lua.org/manual/5.1/manual.html")
code_c_d_remote("lpegmanual",  "http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html")



-- «code_intros»  (to ".code_intros")
--
ee_intro_stems = [[
    anchors audiovideo bounded brxxx channels code-c-d debootstrap
    defun dot-emacs edit-index eejump eepitch eev eev-exercises
    eev-install eev-levels eev-quick elisp emacs emacs-keys escripts
    eval git here-links kl-here kla lean4 lexical links-conv links
    lua-tutorial multiwindow org pdf-like prepared psne rcirc refining
    rstdoc saving-links show2 strange-functions templates
    three-main-keys try-sly videos video-links windows-beginner wrap

    lisptree show-conses
  ]]

for _,stem in ipairs(split(ee_intro_stems)) do
  code_intro(stem)
end

-- «code_intros-tests»  (to ".code_intros-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target [[ (find-elisp-intro) ]]
= sexp_to_target [[ (find-elisp-intro "2.34.") ]]

--]==]



-- «code_helponlys»  (to ".code_helponlys")
-- (to "code_morehelponlys")

code_helponly_lines [[
  eelatex-bounded (find-bounded-intro)
  eev-bounded     (find-bounded-intro)
  eev-beginner    (find-eev-quick-intro "1. Installing eev")
  ee-use-red-bullets   (find-eev-quick-intro "6.4. Red stars")
  ee-use-red-stars     (find-eev-quick-intro "6.4. Red stars")
  eek                  (find-eev-quick-intro "3. Elisp hyperlinks")
  find-efunction       (find-eev-quick-intro "3. Elisp hyperlinks")
  find-efunctiondescr  (find-eev-quick-intro "3. Elisp hyperlinks")
  find-efunctionpp     (find-elisp-intro "11. Byte-compiled functions")
  find-elongkey-links  (find-eev-quick-intro "4.2. `find-ekey-links' and friends")
  find-fline      (find-eev-quick-intro "3. Elisp hyperlinks")
  find-man        (find-eev-quick-intro "3. Elisp hyperlinks")
  find-node       (find-eev-quick-intro "3. Elisp hyperlinks")
  find-sh         (find-eev-quick-intro "3. Elisp hyperlinks")
  find-sh0        (find-eev-quick-intro "3. Elisp hyperlinks")
  brg             (find-eev-quick-intro "3.1. Non-elisp hyperlinks")
  eepitch         (find-eev-quick-intro "6. Controlling shell-like programs")
  eepitch-kill    (find-eev-quick-intro "6. Controlling shell-like programs")
  eepitch-shell   (find-eev-quick-intro "6. Controlling shell-like programs")
  eepitch-bash    (find-eev-quick-intro "6.2. Other targets")
  eepitch-ghci    (find-eev-quick-intro "6.2. Other targets")
  eepitch-lua51   (find-eev-quick-intro "6.2. Other targets")
  eepitch-python  (find-eev-quick-intro "6.2. Other targets")
  eepitch-maxima  (find-eev-quick-intro "6.2. Other targets")
  eepitch-tcl     (find-eev-quick-intro "6.2. Other targets")
  eepitch         (find-eepitch-intro "2.3. `eepitch'")
  eepitch-kill    (find-eepitch-intro "2.2. `(eepitch-kill)'")
  find-3EE        (find-eepitch-intro "1.2. Two targets")
  code-c-d        (find-eev-quick-intro "9. Shorter hyperlinks")
  find-pdf-page   (find-pdf-like-intro "4. Hyperlinks to pages of PDF files")
  find-pdf-text   (find-pdf-like-intro "4. Hyperlinks to pages of PDF files")
  find-xpdfpage   (find-pdf-like-intro "4. Hyperlinks to pages of PDF files")
  code-pdf-page   (find-pdf-like-intro "7. Shorter hyperlinks to PDF files")
  code-pdf-text   (find-pdf-like-intro "7. Shorter hyperlinks to PDF files")
  find-audio      (find-audiovideo-intro "1. Time offsets")
  find-video      (find-audiovideo-intro "1. Time offsets")
  code-audio      (find-audiovideo-intro "4. Short hyperlinks to audio and video files")
  code-video      (find-audiovideo-intro "4. Short hyperlinks to audio and video files")
  find-anchor     (find-eev-quick-intro "8.5. Hyperlinks to anchors in other files")
]]




-- «find-node»  (to ".find-node")
--
_SH["find-node"] = SexpHead {
  head = "find-node",
  help = sexp_to_target_st [[ (find-eev-quick-intro "3. Elisp hyperlinks") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local ab = si:sexp_strarg(2)
      if not ab then return end
      local a, b = ab:match("^%(([^()]+)%)(.*)$")
      if not a then return end
      local target = SexpTarget {f="find_node", manual=a, node=b}
      if target then si:add_filling("e", nil, "target", target) end
    end,
}

-- «find-node-test»  (to ".find-node-test")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target [[ (find-node "(emacs)Keys") ]]

linestr = [[ (find-node "(PATATA)Keys") ]]
si = SexpIntervals.from(linestr)
si:head_apply()
= si
= si:tosandwich()
= si:target_st()
= si:target_st():url()

hl = HtmlizeLine {}
= hl:line(linestr)

--]==]





-- «to»  (to ".to")
--
_SH["to"] = SexpHead {
  head = "to",
  help = sexp_to_target_st [[ (find-eev-quick-intro "8.1. Introduction: `to'") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local a = si:sexp_strarg(2)
      if not a then return end
      local target = SexpTarget.from("#"..a)
      if target then si:add_filling("e", nil, "target", target) end
    end,
}

-- «to-test»  (to ".to-test")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target [[ (find-node "(emacs)Keys") ]]

linestr = [[ (find-node "(PATATA)Keys") ]]
si = SexpIntervals.from(linestr)
si:head_apply()
= si
= si:tosandwich()
= si:target_st()
= si:target_st():url()

hl = HtmlizeLine {}
= hl:line(linestr)

--]==]





-- «code-pdf-page»  (to ".code-pdf-page")
--
_SH["code-pdf-page"] = SexpHead {
  head = "code-pdf-page",
  help = sexp_to_target_st [[ (find-pdf-like-intro "7. Shorter hyperlinks to PDF files") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local c     = si:sexp_strarg(2)
      local fname = si:sexp_strarg(3)
      if c and fname then
	local pdfurl = code_pdf_geturl(fname)
        if pdfurl then
          si:add_filling(3, 1, "pdf", pdfurl)
	  code_pdf(c, pdfurl)
	end
      end
    end,
}

code_pdf_geturl = function (fname)
    local prot,rest = fname:match("^%$S/(https?)/(.*)$")
    if prot then return prot.."://"..rest end
    local LATEXrest = fname:match("^~/(LATEX/.*)$")
    if LATEXrest then return "http://anggtwu.net/"..LATEXrest end
    local dednat6rest = fname:match("^~/(dednat6/.*)$")
    if dednat6rest then return "http://anggtwu.net/"..dednat6rest end
  end

code_pdf = function (c, pdfurl)
    local find_cpage = "find-"..c.."page"
    _SH[find_cpage] = SexpHead {
      head = find_cpage,
      help = sexp_to_target_st [[ (find-pdf-like-intro "7. Shorter hyperlinks to PDF files") ]],
      f = function (sh, si)
          si:add_filling(1, nil, "help", sh.help)
          local page = si:sexp_numericarg(2)
	  if page then
            local target = SexpTarget {f="find_pdf", pdfurl=pdfurl, page=page}
            si:add_filling(2, 0, "target", target)
          end
        end,
    }
  end



-- «code-pdf-page-tests»  (to ".code-pdf-page-tests")
-- 
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
linestr = [[ (code-pdf-page "foo" "$S/https/www2.cs.arizona.edu/icon/ftp/doc/lb1up.pdf") ]]
linestr = [[ (code-pdf-page "foo" "~/LATEX/foo.pdf") ]]
si = SexpIntervals.from(linestr)
si:head_apply()
= si
= si:tosandwich()

= _SH["find-foopage"]

linestr = [[ (find-foopage (+ 2 3)) ]]
si = SexpIntervals.from(linestr)
si:head_apply()
= si
= si:tosandwich()
= si:name_to_st("2")
= si:name_to_st("2"):url()

* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-maximawbpage (+ 20 19) "foo") ]]
= sexp_to_target_si  [[ (code-pdf-page "maximawb" "$S/http/roland-salz.de/Maxima_Workbook.pdf") ]]
= sexp_to_target_si  [[ (find-maximawbpage (+ 20 19) "foo") ]]
linestr =            [[ (find-maximawbpage (+ 20 19) "foo") ]]
si = SexpIntervals.from(linestr)
= si
si:head_apply()
= si
= si:name_to_st("2")
= si:name_to_st("2"):url()

--]==]




-- «code-ytvideo»  (to ".code-ytvideo")
-- Experimental, 2021dec13
--
_SH["code-ytvideo"] = SexpHead {
  head = "code-ytvideo",
  help = sexp_to_target_st
         [[ (find-audiovideo-intro "4. Short hyperlinks to audio and video files") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local c         = si:sexp_strarg(2)
      local localfile = si:sexp_strarg(3)
      if localfile then
        local hash = to_youtube_hash(localfile)
        PP(c, localfile, hash)
        si:add_filling(3, 1, "localfile", youtube_make_url(hash))
        code_youtube(c, hash)
      end
    end,
}

-- «code-ytvideo-tests»  (to ".code-ytvideo-tests")
--
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_st  [[ (find-orglinks1video "5:00" "#MyID123") ]] --> err
= sexp_to_target_si  [[ (code-ytvideo "orglinks1video" "foo-eoIfLS4zMa8.mkv") ]]
= sexp_to_target_st  [[ (find-orglinks1video "5:00" "#MyID123") ]]

--]==]


-- «find-youtubedl-links»  (to ".find-youtubedl-links")
--
_SH["find-youtubedl-links"] = SexpHead {
  head = "find-youtubedl-links",
  help = sexp_to_target_st [[ (find-eev "eev-tlinks.el" "find-youtubedl-links") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local hash = si:sexp_strarg(4)
      if hash then
        si:add_filling(4, 1, "yt", youtube_make_url(hash))
      end
    end,
}


-- «find-youtubedl-links-tests»  (to ".find-youtubedl-links-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-youtubedl-links "/sda5/videos/" nil "eoIfLS4zMa8" nil "orglinks1") ]]

--]==]




--                _                                   _     _            
--   ___ ___   __| | ___        ___  _____   ____   _(_) __| | ___  ___  
--  / __/ _ \ / _` |/ _ \_____ / _ \/ _ \ \ / /\ \ / / |/ _` |/ _ \/ _ \ 
-- | (_| (_) | (_| |  __/_____|  __/  __/\ V /  \ V /| | (_| |  __/ (_) |
--  \___\___/ \__,_|\___|      \___|\___| \_/    \_/ |_|\__,_|\___|\___/ 
--                                                                       
-- «code-eevvideo»  (to ".code-eevvideo")
--
_SH["code-eevvideo"] = SexpHead {
  head = "code-eevvideo",
  help = sexp_to_target_st [[ (find-audiovideo-intro "7.1. `code-eevvideo'") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local c       = si:sexp_strarg(2)
      local mp4stem = si:sexp_strarg(3)
      local hash    = si:sexp_strarg(4)
      if mp4stem then
        mp4url = "http://anggtwu.net/eev-videos/"..mp4stem..".mp4"
        si:add_filling(3, 1, "mp4", mp4url)
      end
      if c and hash then
	-- 2022may21: do not override
        local f_cvideo = format("find-%svideo", c)
	if not f_cvideo then
          code_youtube(c.."video", hash)
	end
        si:add_filling(4, 1, "yt", youtube_make_url(hash))
      end
    end,
}

-- «code-eevvideo-tests»  (to ".code-eevvideo-tests")
-- 
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
linestr = [[ (code-eevvideo  "eev2019" "emacsconf2019" "86yiRG8YJD0") ]]
si = SexpIntervals.from(linestr)
si:head_apply()
= si
= si:tosandwich()

linestr = [[ (find-eev2019video) ]]
si = SexpIntervals.from(linestr)
si:head_apply()
= si
= si:tosandwich()

linestr = [[ (find-eev2019video "1:23") ]]
si = SexpIntervals.from(linestr)
si:head_apply()
= si
= si:tosandwich()

--]==]



-- «code_eevshortvideo»  (to ".code_eevshortvideo")
-- Similar to "code-eevvideo", but the help link points to:
--   (find-video-links-intro "2. From the HTML")
-- and the set of "code-eevshortvideo"s is small and hardcoded.
--
-- TODO: rename this, as the "eevshortvideos" are now "1stclassvideos"...
--
code_eevshortvideo = function (stem, mp4stem, hash)
    local head = "find-"..stem.."video"
    -- local help = sexp_to_target_st
    --             [[ (find-videos-intro "2. Short links to eev video tutorials") ]]
    local help = sexp_to_target_st [[ (find-video-links-intro "2. From the HTML") ]]
    _SH[head] = SexpHead {
      ORIG = "code_eevshortvideo",
      head = head,
      help = help,
      f = function (sh, si)
          si:add_filling(1, nil, "help", sh.help)
          local time = si:sexp_strarg(2)
	  if time then
            si:add_filling(2, 1, "yt", youtube_make_url(hash, time))
          end
        end,
    }
  end

-- «code_eevshortvideos»  (to ".code_eevshortvideos")
code_eevshortvideo("2021ffll", "2021-ffll", "h1CEL2fmkyc")
code_eevshortvideo("2021orgfornonusers", "2021-org-for-non-users", "Eh5Wz9Vh_XM")
code_eevshortvideo("2021workshop1", "2021-workshop-1", "HuqJFPD871E")
code_eevshortvideo("2021workshop2", "2021-workshop-2", "hqqIlZBXNhk")
code_eevshortvideo("2021workshop3", "2021-workshop-3", "r83inf9s8zo")
code_eevshortvideo("2021workshop4", "2021-workshop-4", "lhpHHjBUxv8")
code_eevshortvideo("2021workshop5", "2021-workshop-5", "VzRsterVSXs")
code_eevshortvideo("2021workshop6", "2021-workshop-6", "-gi15-liGaU")
code_eevshortvideo("2022eevmake0", "2022-eev-make-0", "Iql5C-yQk5c")
code_eevshortvideo("2022findeevangg", "2022-find-eev-angg", "FoAzpGzFCSE")
code_eevshortvideo("2022findelispintro", "2022-find-elisp-intro", "WowDSciGs1A")
code_eevshortvideo("eev2019", "emacsconf2019", "86yiRG8YJD0")
code_eevshortvideo("eev2020", "emacsconf2020", "hOAqBc42Gg8")
code_eevshortvideo("eev2021", "emacsconf2021", "qM0Luz78qGw")
code_eevshortvideo("eev2021b", "emacsconf2021-dednat6", "QUMo7vgkHJI")
code_eevshortvideo("eev2022kla", "emacsconf2022-kla", "KRobfwXd7Cw")
code_eevshortvideo("eev2022py", "emacsconf2022-py", "QeqCYQSlz-I")
code_eevshortvideo("eev2023repls", "emacsconf2023-repls", "IDBQo_YYfA8")
code_eevshortvideo("eev2023replsb", "emacsconf2023-repls-b", "s3enXsuXyNg")
code_eevshortvideo("eevfherel", "2020-find-here-links", "8jtiBlaDor4")
code_eevshortvideo("eevnav",  "2020-list-packages-eev-nav", "kxBjiUo88_U")
code_eevshortvideo("eevtempl", "2020-some-template-based", "91-9YfRPsuk")
code_eevshortvideo("eevtestbls", "2021-test-blocks", "fpsF_M55W4o")
code_eevshortvideo("eevvlinks", "2021-video-links", "xQqWufQgzVY")
code_eevshortvideo("oficina20210", "2021projeto-de-ensino", "OW6WRnSQwc0")
code_eevshortvideo("oficina2021a", "2021-oficina-1", "acFPMuZ5Jf4")
code_eevshortvideo("oficina2021b", "2021-oficina-2", "XbuDnkfizYs")
code_eevshortvideo("2022pict2elua", "2022-pict2e-lua", "hiHsUhGVLGM")
code_eevshortvideo("2022eevwconfig", "2022-eev-wconfig", "Rm29XSdGCXw")
code_eevshortvideo("2022eevwconfigpt1", "2022-eev-wconfig-pt-1", "bdLbocmo3r8")
code_eevshortvideo("2022eevwconfigpt2", "2022-eev-wconfig-pt-2", "ZAAxrJX-Am8")
code_eevshortvideo("2022yttranscript", "2022-yttranscript", "SW3Tx-lHX3o")
code_eevshortvideo("2022tikz", "2022-eev-tikz", "d7nIzpXcV6c")
code_eevshortvideo("2024git", "2024-eev-git", "lsVvokjqMY0")
code_eevshortvideo("2024luaso", "2024-find-luaso-links", "zUW-6atPvUQ")

code_eevshortvideo("cae0", "2023-caepro0", "XxnfW90kbZU")
code_eevshortvideo("caev", "2023-caepro-VR", "JoAQ6TsFlto")
code_eevshortvideo("caes", "2023-caepro-o-que-sobra", "sZq2PgbLN5k")
code_eevshortvideo("c2m211somas1d", "2021-1-C2-somas-1-dicas", "pCD1p9FZYdI")
code_eevshortvideo("2021saptleg", "2021aulas-por-telegram", "OofZQYkNVhg")
code_eevshortvideo("calceasy", "mathologer-calculus-easy", "kuOxDh3egN0")
code_eevshortvideo("c3m211cn", "2021-1-C3-curvas-de-nivel", "mrNyBAMOyqo")
code_eevshortvideo("c3m211cn2", "2021-1-C3-curvas-de-nivel-2", "usBNtNyZRCA")
code_eevshortvideo("c3cd", "2021-2-c3-cabos-na-diagonal", "nxsIK0tPWAI")
code_eevshortvideo("visaud", "2023-visual-vs-auditivo", "vVNpWTYR4wE")
code_eevshortvideo("slogans", "2023-precisamos-de-mais-slogans", "qwTqIBlu9CM")
code_eevshortvideo("2024algpergs",   "2024-algumas-perguntas", "FjhyhTxN_-o")
code_eevshortvideo("2024lean4of0",   "2024-lean4-oficina-0", "vBkxGIrv2Q0")
code_eevshortvideo("2024lean4of0a2", "2024-lean4-oficina-0-aula-2", "MXUJ8YLp5dU")
code_eevshortvideo("2024convite",    "2024-convite-maxima", "wVwxugy15cU")

-- «code_eevshortvideo-tests»  (to ".code_eevshortvideo-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= _SH
= _SH["find-2021workshop3video"]
linestr = [[ (find-eev2019video "1:23") ]]
linestr = [[ (find-2021workshop3video "1:23") ]]
si = SexpIntervals.from(linestr)
si:head_apply()
= si
= si:tosandwich()

--]==]





-- «find-eevvideo-links»  (to ".find-eevvideo-links")
--
_SH["find-eevvideo-links"] = SexpHead {
  head = "find-eevvideo-links",
  help = sexp_to_target_st [[ (find-audiovideo-intro "7.2. `find-eevvideo-links'") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local c       = si:sexp_strarg(2)
      local mp4stem = si:sexp_strarg(3)
      local hash    = si:sexp_strarg(4)
      if mp4stem then
        local mp4url = "http://anggtwu.net/eev-videos/"..mp4stem..".mp4"
        si:add_filling(3, 1, "mp4", mp4url)
      end
      if c and hash then
        code_youtube(c.."video", hash)
        si:add_filling(4, 1, "yt", youtube_make_url(hash))
      end
    end,
}


-- «find-1stclassvideos»  (to ".find-1stclassvideos")
--
_SH["find-1stclassvideos"] = SexpHead {
  head = "find-1stclassvideos",
  help = sexp_to_target_st [[ (find-video-links-intro "9. First-class videos") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
    end,
}

_SH["find-1stclassvideoindex"] = SexpHead {
  head = "find-1stclassvideoindex",
  help = sexp_to_target_st [[ (find-video-links-intro "9. First-class videos") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local c = si:sexp_strarg(2)
      if c then
        local moreinfo = "http://anggtwu.net/.emacs.videos.html#"..c
        si:add_filling(2, 1, "moreinfo", moreinfo)
      end
    end,
}

_SH["find-1stclassvideodef"] = SexpHead {
  head = "find-1stclassvideodef",
  help = sexp_to_target_st [[ (find-video-links-intro "9. First-class videos") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local c = si:sexp_strarg(2)
      if c then
        local moreinfo = "http://anggtwu.net/eev-current/eev-videolinks.el.html#"..c
        si:add_filling(2, 1, "moreinfo", moreinfo)
      end
    end,
}

-- «find-1stclassvideo-links»  (to ".find-1stclassvideo-links")
-- Skel: (find-sandwiches-def-links "find-1stclassvideo-links")
--
_SH["find-1stclassvideo-links"] = SexpHead {
  head = "find-1stclassvideo-links",
  help = sexp_to_target_st [[ (find-video-links-intro "9. First-class videos") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local c = si:sexp_strarg(2)
      if c then
        -- local moreinfo = "http://anggtwu.net/.emacs.videos.html#"..c
        local moreinfo = "http://anggtwu.net/eev-current/eev-videolinks.el.html#"..c
        si:add_filling(2, 1, "moreinfo", moreinfo)
      end
    end,
}

-- «find-1stclassvideo-links-tests»  (to ".find-1stclassvideo-links-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-1stclassvideo-links "eev2019") ]]
= sexp_to_target_st  [[ (find-1stclassvideo-links "eev2019") ]]

--]==]




-- «find-1stclassvideolsubs»  (to ".find-1stclassvideolsubs")
-- Skel: (find-sandwiches-def-links "find-1stclassvideolsubs")
--
_SH["find-1stclassvideolsubs"] = SexpHead {
  head = "find-1stclassvideolsubs",
  help = "http://anggtwu.net/eev-videos.html#subed",
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local c = si:sexp_strarg(2)
      local mp4stem = c and get_mp4stem(c)
      local fmt = "http://anggtwu.net/SUBTITLES/%s.lua.html"
      local tgt = mp4stem and format(fmt, mp4stem)
      if mp4stem then
        si:add_filling(2, 1, "mp4stem", tgt)
      end
    end,
}

-- «find-1stclassvideolsubs-tests»  (to ".find-1stclassvideolsubs-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-1stclassvideolsubs "eev2019") ]]
= sexp_to_target_st  [[ (find-1stclassvideolsubs "eev2019") ]]
PPPV(_SH["find-1stclassvideolsubs"])
PPPV(_SH["find-1stclassvideolsubs"].help)

--]==]



-- «find-wgeteevsubtitles-links»  (to ".find-wgeteevsubtitles-links")
--
_SH["find-wgeteevsubtitles-links"] = SexpHead {
  head = "find-wgeteevsubtitles-links",
  help = sexp_to_target_st [[ (find-eev "eev-tlinks.el" "find-wgeteevsubtitles-links") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local hash = si:sexp_strarg(4)
      if hash then
        si:add_filling(4, 1, "yt", youtube_make_url(hash))
      end
    end,
}

-- «find-wgeteevsubtitles-links-tests»  (to ".find-wgeteevsubtitles-links-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-wgeteevsubtitles-links "foo" "bar") ]]

--]==]





--  _     _       _                     _     _                
-- / |___| |_ ___| | __ _ ___ _____   _(_) __| | ___  ___  ___ 
-- | / __| __/ __| |/ _` / __/ __\ \ / / |/ _` |/ _ \/ _ \/ __|
-- | \__ \ || (__| | (_| \__ \__ \\ V /| | (_| |  __/ (_) \__ \
-- |_|___/\__\___|_|\__,_|___/___/ \_/ |_|\__,_|\___|\___/|___/
--                                                             
-- Written in 2024feb25.
-- This should replace several of the functions above.
--
-- «code_1stclassvideo»  (to ".code_1stclassvideo")
-- Skel: (find-sandwiches-def-links "code_1stclassvideo")

code_1stclassvideo = function (c)
    local headvideo = "find-"..c.."video"
    local headlsubs = "find-"..c.."lsubs"
    local headhsubs = "find-"..c.."hsubs"
    local has_lsubs = get_1stclassvideo_field(c, "subs")
    local has_hsubs = get_1stclassvideo_field(c, "hsubs")
    local help = sexp_to_target_st [[ (find-video-links-intro "2. From the HTML") ]]
    local help = "http://anggtwu.net/eev-videos.html#first-class-videos"
    --
    _SH[headvideo] = SexpHead {
      ORIG = "code_1stclassvideo",
      head = headvideo,
      help = help,
      f = function (sh, si)
          si:add_filling(1, nil, "help", sh.help)
          local time = si:sexp_strarg(2)
	  if time then
            si:add_filling(2, 1, "yt", get_1stclassvideo_yturl(c, time))
          end
        end,
    }
    --
    if has_lsubs then
      _SH[headlsubs] = SexpHead {
        ORIG = "code_1stclassvideo",
        head = headlsubs,
        help = help,
        f = function (sh, si)
            si:add_filling(1, nil, "help", sh.help)
            local time = si:sexp_strarg(2)
	    if time then
              si:add_filling(2, 1, "lsubs", get_1stclassvideo_lsubs(c, time))
            end
          end,
      }
    end
    --
    if has_hsubs then
      _SH[headhsubs] = SexpHead {
        ORIG = "code_1stclassvideo",
        head = headhsubs,
        help = help,
        f = function (sh, si)
            si:add_filling(1, nil, "help", sh.help)
            local time = si:sexp_strarg(2)
	    if time then
              si:add_filling(2, 1, "hsubs", get_1stclassvideo_hsubs(c, time))
            end
          end,
      }
    end
  end

code_1stclassvideos = function ()
    for _,c in ipairs(sortedkeys(sandwiches_videos)) do
      code_1stclassvideo(c)
    end
  end

code_1stclassvideos()

-- «code_1stclassvideo-tests»  (to ".code_1stclassvideo-tests")
-- (find-2022tikzvideo "12:33")
-- (find-2022tikzhsubs "12:33")
-- (find-2022tikzlsubs "12:33")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-2022tikzvideo "12:33") ]]
= sexp_to_target_st  [[ (find-2022tikzvideo "12:33") ]]
= sexp_to_target_si  [[ (find-2022tikzhsubs "12:33") ]]
= sexp_to_target_st  [[ (find-2022tikzhsubs "12:33") ]]
= sexp_to_target_si  [[ (find-2022tikzlsubs "12:33") ]]
= sexp_to_target_st  [[ (find-2022tikzlsubs "12:33") ]]

--]==]






-- «find-TH»  (to ".find-TH")
-- Skel: (find-sandwiches-def-links "find-TH")
--
_SH["find-TH"] = SexpHead {
  head = "find-TH",
  -- help = sexp_to_target_st [[ (find-eev "eev-tlinks.el" "find-TH") ]],
  f = function (sh, si)
      -- si:add_filling(1, nil, "help", sh.help)
      local fmt        = "http://anggtwu.net/%s.html%s"
      local stem       = si:sexp_strarg(2)
      local anchor     = si:sexp_strarg(3)
      local hashanchor = anchor and "#"..anchor or ""
      local target     = stem and format(fmt, stem, hashanchor)
      if stem then
        si:add_filling("e", nil, "target", target)
      end
    end,
}

-- «find-TH-tests»  (to ".find-TH-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-TH "eev-videos") ]]
= sexp_to_target_st  [[ (find-TH "eev-videos") ]]
= sexp_to_target_si  [[ (find-TH "eev-videos" "mpv-keys") ]]
= sexp_to_target_st  [[ (find-TH "eev-videos" "mpv-keys") ]]

--]==]



-- «find-maximamsg»  (to ".find-maximamsg")
-- (find-angg ".emacs.templates" "find-maximamsg")
--
_SH["find-maximamsg"] = SexpHead {
  head = "find-maximamsg",
  help = sexp_to_target_st [[ (find-TH "find-maximamsg") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local msgspec = si:sexp_strarg(2)
      if msgspec then
	local yyyymm = split(msgspec)[1] or ""
        local url = "https://sourceforge.net/p/maxima/mailman/message/"..yyyymm.."/"
        si:add_filling(2, 1, "mml", url)
      end
    end,
}

-- «find-maximamsg-tests»  (to ".find-maximamsg-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-maximamsg "37675653 202207 1" "structural") ]]
= sexp_to_target_st  [[ (find-maximamsg "37675653 202207 1" "structural") ]]

--]==]



-- «rstdoc»  (to ".rstdoc")
-- (find-eev "eev-rstdoc.el")
rstdoc_help          = "http://anggtwu.net/eev-current/eev-rstdoc.el.html"
rstdoc_base_py       = "https://docs.python.org/3/"
rstdoc_base_sympy    = "https://docs.sympy.org/latest/"
rstdoc_base_mpl      = "https://matplotlib.org/stable/"
rstdoc_base_ghcug    = "https://downloads.haskell.org/ghc/latest/docs/users_guide/"
rstdoc_base_h98      = "https://www.haskell.org/onlinereport/"
rstdoc_base_h98t     = "https://www.haskell.org/tutorial/"
rstdoc_base_clhs     = "http://www.lispworks.com/documentation/HyperSpec/"
rstdoc_base_fennel   = "https://fennel-lang.org/"
rstdoc_base_gd3      = "https://docs.godotengine.org/en/3.5/"
rstdoc_base_J        = "https://www.jsoftware.com/help/"
rstdoc_base_penlight = "https://lunarmodules.github.io/Penlight/"
rstdoc_base_nodejs   = "https://nodejs.org/dist/latest-v20.x/docs/api/"
rstdoc_base_leanref  = "https://leanprover.github.io/reference/"
rstdoc_base_leanmeta = "https://leanprover-community.github.io/lean4-metaprogramming-book/"
rstdoc_base_lean4    = "https://lean-lang.org/lean4/doc/"
rstdoc_base_leantpil = "https://lean-lang.org/theorem_proving_in_lean4/"
rstdoc_base_fplean4  = "https://lean-lang.org/functional_programming_in_lean/"
rstdoc_base_leanmaths = "https://leanprover-community.github.io/mathematics_in_lean/"
rstdoc_base_mechprf   = "https://hrmacbeth.github.io/math2001/"
rstdoc_base_tclean4   = "https://ammkrn.github.io/type_checking_in_lean4/"
rstdoc_base_tpil4     = "https://lean-lang.org/theorem_proving_in_lean4/"
rstdoc_base_sqlite3   = "https://www.sqlite.org/"
-- (find-blogme3-rstdoc-links "sqlite3")

rstdoc_url = function (base, str, htm)
    local a,b = str:match("^([^#]*)(#?.*)$")
    return base..a..(htm or ".html")..b
  end

rstdoc_f = function (sh, si)
    si:add_filling(1, nil, "help", sh.help)
    local str = si:sexp_strarg(2)
    if str then
      si:add_filling(2, 1, "tgt", rstdoc_url(sh.base, str, sh.htm))
    end
  end

-- «find-pydoc»  (to ".find-pydoc")
-- (find-pydocw "index")
-- (find-sympydocw "index")
-- (find-pydoc "tutorial/index")
--
_SH["find-pydoc"] = SexpHead {
  head = "find-pydoc",
  help = rstdoc_help,
  base = rstdoc_base_py,
  f    = rstdoc_f,
}

_SH["find-sympydoc"] = SexpHead {
  head = "find-sympydoc",
  help = rstdoc_help,
  base = rstdoc_base_sympy,
  f    = rstdoc_f,
}

_SH["find-mpldoc"] = SexpHead {
  head = "find-mpldoc",
  help = rstdoc_help,
  base = rstdoc_base_mpl,
  f    = rstdoc_f,
}

_SH["find-ghcugdoc"] = SexpHead {
  head = "find-ghcugdoc",
  help = rstdoc_help,
  base = rstdoc_base_ghcug,
  f    = rstdoc_f,
}

_SH["find-h98doc"] = SexpHead {
  head = "find-h98doc",
  help = rstdoc_help,
  base = rstdoc_base_h98,
  f    = rstdoc_f,
}

_SH["find-h98tdoc"] = SexpHead {
  head = "find-h98tdoc",
  help = rstdoc_help,
  base = rstdoc_base_h98t,
  f    = rstdoc_f,
}

_SH["find-clhsdoc"] = SexpHead {
  head = "find-clhsdoc",
  help = rstdoc_help,
  base = rstdoc_base_clhs,
  htm  = ".htm",
  f    = rstdoc_f,
}

_SH["find-fenneldoc"] = SexpHead {
  head = "find-fenneldoc",
  help = rstdoc_help,
  base = rstdoc_base_fennel,
  f    = rstdoc_f,
}
_SH ["find-fenneldocw"] =
 _SH["find-fenneldoc"]

_SH["find-gd3doc"] = SexpHead {
  head = "find-gd3doc",
  help = rstdoc_help,
  base = rstdoc_base_gd3,
  f    = rstdoc_f,
}

_SH["find-Jdoc"] = SexpHead {
  head = "find-Jdoc",
  help = rstdoc_help,
  base = rstdoc_base_J,
  htm  = ".htm",
  f    = rstdoc_f,
}

_SH["find-penlightdoc"] = SexpHead {
  head = "find-penlightdoc",
  help = rstdoc_help,
  base = rstdoc_base_penlight,
  htm  = ".html",
  f    = rstdoc_f,
}

_SH["find-nodejsdoc"] = SexpHead {
  head = "find-nodejsdoc",
  help = rstdoc_help,
  base = rstdoc_base_nodejs,
  htm  = ".html",
  f    = rstdoc_f,
}

_SH["find-leanrefdoc"] = SexpHead {
  head = "find-leanrefdoc",
  help = rstdoc_help,
  base = rstdoc_base_leanref,
  htm  = ".html",
  f    = rstdoc_f,
}

_SH["find-leanmetadoc"] = SexpHead {
  head = "find-leanmetadoc",
  help = rstdoc_help,
  base = rstdoc_base_leanmeta,
  htm  = ".html",
  f    = rstdoc_f,
}

_SH["find-lean4doc"] = SexpHead {
  head = "find-lean4doc",
  help = rstdoc_help,
  base = rstdoc_base_lean4,
  htm  = ".html",
  f    = rstdoc_f,
}

_SH["find-leantpildoc"] = SexpHead {
  head = "find-leantpildoc",
  help = rstdoc_help,
  base = rstdoc_base_leantpil,
  htm  = ".html",
  f    = rstdoc_f,
}

_SH["find-fplean4doc"] = SexpHead {
  head = "find-fplean4doc",
  help = rstdoc_help,
  base = rstdoc_base_fplean4,
  htm  = ".html",
  f    = rstdoc_f,
}

_SH["find-leanmathsdoc"] = SexpHead {
  head = "find-leanmathsdoc",
  help = rstdoc_help,
  base = rstdoc_base_leanmaths,
  htm  = ".html",
  f    = rstdoc_f,
}

_SH["find-mechprfdoc"] = SexpHead {
  head = "find-mechprfdoc",
  help = rstdoc_help,
  base = rstdoc_base_mechprf,
  htm  = ".html",
  f    = rstdoc_f,
}

_SH["find-tclean4doc"] = SexpHead {
  head = "find-tclean4doc",
  help = rstdoc_help,
  base = rstdoc_base_tclean4,
  htm  = ".html",
  f    = rstdoc_f,
}

_SH["find-tpil4doc"] = SexpHead {
  head = "find-tpil4doc",
  help = rstdoc_help,
  base = rstdoc_base_tpil4,
  htm  = ".html",
  f    = rstdoc_f,
}

_SH["find-sqlite3doc"] = SexpHead {
  head = "find-sqlite3doc",
  help = rstdoc_help,
  base = rstdoc_base_sqlite3,
  htm  = ".html",
  f    = rstdoc_f,
}




-- «find-pydoc-tests»  (to ".find-pydoc-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-pydoc "foo#bar") ]]
= sexp_to_target_st  [[ (find-pydoc "foo#bar") ]]
= sexp_to_target_si  [[ (find-sympydoc "foo#bar") ]]
= sexp_to_target_st  [[ (find-sympydoc "foo#bar") ]]
= sexp_to_target_si  [[ (find-sympydoc "foo") ]]
= sexp_to_target_st  [[ (find-sympydoc "foo") ]]
= sexp_to_target_si  [[ (find-ghcugdoc "foo") ]]
= sexp_to_target_st  [[ (find-ghcugdoc "foo") ]]
= sexp_to_target_si  [[ (find-h98doc "foo") ]]
= sexp_to_target_st  [[ (find-h98doc "foo") ]]
= sexp_to_target_si  [[ (find-h98tdoc "foo") ]]
= sexp_to_target_st  [[ (find-h98tdoc "foo") ]]
= sexp_to_target_st  [[ (find-clhsdoc "Front/Contents") ]]
= sexp_to_target_st  [[ (find-gd3doc "foo") ]]
= sexp_to_target_st  [[ (find-gd3doc "getting_started/first_2d_game/01.project_setup") ]]
= sexp_to_target_st  [[ (find-Jdoc "index") ]]
= sexp_to_target_st  [[ (find-penlightdoc "index") ]]
= sexp_to_target_st  [[ (find-leanrefdoc "index") ]]
= sexp_to_target_st  [[ (find-leanmetadoc "index") ]]
= sexp_to_target_st  [[ (find-leanmathsdoc "index") ]]

--]==]




-- «use_sand_htmlizeline»  (to ".use_sand_htmlizeline")
-- Redefine htmlizeline to use the sandwich functions.
--
use_sand_htmlizeline = function (fname)
    --
    -- (find-blogme3 "escripts.lua")
    -- (find-blogme3 "escripts.lua" "htmlizeline")
    --
    require "escripts"
    --
    SpecialT       = UrlT + AnchorT + SexpLinkT * Eol
    -- SpecialT    = UrlT + AnchorT + PipeAmpT + PipeSnarfDirT + HereDocT + SexpLinkT * Eol
    SpecialT       = UrlT + AnchorT + PipeAmpT + PipeSnarfDirT + HereDocT
    EtcChar        = 1 - lpeg.S "\n"
    EtcSpecial     = Pos * lpeg.P {
               [1] = Pos * SpecialT
                   + EtcChar * lpeg.V(1)
      }
    EtcSpecials    = EtcSpecial^0
    EtcSpecialsEtc = EtcSpecials * Pos * EtcChar^0 * Pos
    --
    htmlizelineleft = function (str)
        return lpeg.match(lpeg.Ct(EtcSpecialsEtc) / sbeconcat(str, Q), str)
      end
    --
    hl_deluxe = HtmlizeLine {
        left  = function (hl, str) return htmlizelineleft(str) end,
        plain = function (hl, str) return Q(str) end,
      }
    --
    htmlizeline = function (linestr) return (hl_deluxe:line(linestr)) end
    --
    if fname then
      local ddots = getpathtoroot(fname)
      SexpTarget.__index.ru = function (st, relativeurl)
          return ddots..relativeurl
        end
    end
    --
    require "brackets"
    require "definers"
    def [[ STOH  1 line   htmlizeline(line:gsub("%s+", " "):bitrim()) ]]
    def [[ STOT  1 line   sexp_to_target(line:gsub("%s+", " "))       ]]
    def [[ STOSN 1 line '"'..R(STOT(line), (line:match'"(.*)"'))..'"' ]]
    --
    youtube_time = youtube_time_hhmmss
    --
    -- (find-angg ".emacs.templates" "find-eevvideopage-linkss")
    -- htmlizelines [[
    --  (find-eevvideo-links "eev2019" "emacsconf2019" "86yiRG8YJD0")
    --  (find-eevvideo-links "eev2020" "emacsconf2020" "hOAqBc42Gg8")
    --  (find-eevvideo-links "2020sometbf" "2020_some_template-based_functions" "91-9YfRPsuk")
    --  (find-eevvideo-links "eevnav" "M-x-list-packages-eev-nav" "kxBjiUo88_U")
    --  (find-eevvideo-links "2020findherelinks" "2020-find-here-links" "8jtiBlaDor4")
    --  (find-eevvideo-links "2020ssr" "2020-short-find-ssr-links-2" "_0_NLXTVhBk")
    --  ]]
end

-- «use_sand_htmlizeline-tests»  (to ".use_sand_htmlizeline-tests")
--
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
use_sand_htmlizeline()

= htmlizeline (" |& ")
= htmlizeline [[ (code-eevvideo  "eev2019" "emacsconf2019" "86yiRG8YJD0") ]]
= htmlizeline [[ (find-eev2019video "1:23") ]]
= htmlizeline [[ (find-eev2020video "1:23") ]]

--]==]



-- «Short_»  (to ".Short_")
--
Short_ = Class {
  type = "Short_",
  from = function (bigstr)
      return Short_({_={}}):add(bigstr)
    end,
  parseline = function (linestr)
      local pat_url  = "^%s*([!-~]+)%s+%->%s+([!-~]+)"
      local pat_sexp = "^%s*([!-~]+)%s+=>%s+(.*)"
      local shorthand, url  = linestr:match(pat_url)
      if shorthand then return shorthand, url end
      local shorthand, sexp = linestr:match(pat_sexp)
      if shorthand then
        -- print(sexp)
        local url = sexp_to_target(sexp)
        return shorthand, url
      end
    end,
  __tostring = function (s_) return mytostringv(s_._) end,
  __index = {
    add = function (s_, bigstr)
        for _,linestr in ipairs(splitlines(bigstr)) do
          local shorthand, url = Short_.parseline(untabify(linestr))
          if shorthand then s_._[shorthand] = url end
        end
        return s_
      end,
    expand = function (s_, shorthand, noerror)
        local url = s_._[shorthand]
        if url then return url end
        if noerror then return nil end
        error("No expansion for '"..shorthand.."'")
      end,
  },
}

if def then
  def [[ _ 2 shorthand,text R(short_:expand(shorthand), text) ]]
end


-- «Short_-tests»  (to ".Short_-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"

short_ = Short_.from [[
  test => (find-eepitch-intro "3. Test blocks")
]]
= short_
= short_:expand("test")
= short_:expand("foo")   --> error

= sexp_to_target [[ (find-lua51manual "#pdf-dofile") ]]
= _SH
= _SH["find-lua51manual"]

-- def [[ _ 2 shorthand,text R(short_:expand(shorthand), text) ]]

--]==]


-- «code_helponly2»  (to ".code_helponly2")
-- (find-angg "blogme3/sandwiches.lua" "code_helponly")
--
code_helponly2 = function (head, url)
    _SH[head] = SexpHead {
      head = head,
      help = url,
      f = function (sh, si) si:add_filling(1, 0, "help", sh.help) end,
    }
  end

code_helponly2_lines = function (bigstr)
    for _,linestr in ipairs(splitlines(bigstr)) do
      local head,url = Short_.parseline(linestr)
      if head and url then
        code_helponly2(head, url)
      end
    end
  end

-- «code_helponly2-tests»  (to ".code_helponly2-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
code_helponly2_lines [[
  hv => (find-es "tikz" "horiz-and-vert")
]]
= _SH["hv"]
= sexp_to_target_si  [[ (hv "foo") ]]
= sexp_to_target_st  [[ (hv "foo") ]]

--]==]




-- «agda»  (to ".agda")
-- (find-angg "AGDA/ha.agda")
--
_SH["find-agdastdlibsrcfile"] = SexpHead {
  head = "find-agdastdlibsrcfile",
  -- help = sexp_to_target_st [[ (find-video-links-intro "9. First-class videos") ]],
  f = function (sh, si)
      -- si:add_filling(1, nil, "help", sh.help)
      local ag = si:sexp_strarg(2)
      if ag then
	local ag2 = ag:gsub("%.agda$", "%.html"):gsub("/", ".")
        local ag3 = "https://agda.github.io/agda-stdlib/" .. ag2
        si:add_filling(2, 1, "agdahtml", ag3)
      end
    end,
}

_SH["find-agdaprimfile"] = SexpHead {
  head = "find-agdaprimfile",
  -- help = sexp_to_target_st [[ (find-video-links-intro "9. First-class videos") ]],
  f = function (sh, si)
      -- si:add_filling(1, nil, "help", sh.help)
      local ag = si:sexp_strarg(2)
      if ag then
	local ag2 = ag:gsub("%.agda$", "%.html"):gsub("/", ".")
        local ag3 = "https://agda.github.io/agda-stdlib/" .. ag2
        si:add_filling(2, 1, "agdahtml", ag3)
      end
    end,
}

_SH["find-agdacatsfile"] = SexpHead {
  head = "find-agdacatsfile",
  -- help = sexp_to_target_st [[ (find-video-links-intro "9. First-class videos") ]],
  f = function (sh, si)
      -- si:add_filling(1, nil, "help", sh.help)
      local ag = si:sexp_strarg(2)
      if ag then
	local ag1 = ag:gsub("^src/", "")
	local ag2 = ag1:gsub("%.agda$", "%.html"):gsub("/", ".")
        local ag3 = "https://agda.github.io/agda-categories/" .. ag2
        si:add_filling(2, 1, "agdahtml", ag3)
      end
    end,
}

code_helponly2_lines [=[
  find-agdatype  =>  (find-angg "AGDA/find-agdatype.el")
]=]

-- «agda-tests»  (to ".agda-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-agdastdlibsrcfile "Data/Product.agda") ]]
= sexp_to_target_st  [[ (find-agdastdlibsrcfile "Data/Product.agda") ]]
= sexp_to_target_si  [[ (find-agdaprimfile "Agda/Builtin/Sigma.agda") ]]
= sexp_to_target_st  [[ (find-agdaprimfile "Agda/Builtin/Sigma.agda") ]]
= sexp_to_target_si  [[ (find-agdatype "foo") ]]
= sexp_to_target_st  [[ (find-agdatype "foo") ]]

--  (find-agdaprimfile                "Agda/Builtin/Sigma.agda")
--> https://agda.github.io/agda-stdlib/Agda.Builtin.Sigma.html
--  (find-agdastdlibsrcfile           "Relation/Binary/Indexed/Heterogeneous/Definitions.agda")
--> https://agda.github.io/agda-stdlib/Relation.Binary.Indexed.Heterogeneous.Definitions.html

--]==]


-- «find-hoogle»  (to ".find-hoogle")
_SH["find-hoogle"] = SexpHead {
  head = "find-hoogle",
  help = "http://anggtwu.net/eev-haskell.html",
  f = function (sh, si)
      si:add_filling(1, 0, "help", sh.help)  -- not sh.help:url()
      local str = si:sexp_strarg(2)
      if str then
	local str1 = "https://hoogle.haskell.org/?hoogle=" .. str
        si:add_filling(2, 1, "tgt", str1)
      end
    end,
}

-- «find-hoogle-tests»  (to ".find-hoogle-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-hoogle "guard") ]]
= sexp_to_target_st  [[ (find-hoogle "guard") ]]

--]==]

-- «find-cabal-links»  (to ".find-cabal-links")
_SH["find-cabal-links"] = SexpHead {
  head = "find-cabal-links",
  help = "http://anggtwu.net/eev-haskell.html",
  f = function (sh, si)
      si:add_filling(1, 0, "help", sh.help)  -- not sh.help:url()
      local str = si:sexp_strarg(2)
      if str then
	local str1 = "https://hackage.haskell.org/package/" .. str
        si:add_filling(2, 1, "tgt", str1)
      end
    end,
}

-- «find-cabal-unpack»  (to ".find-cabal-unpack")
_SH["find-cabal-unpack"] = SexpHead {
  head = "find-cabal-unpack",
  help = "http://anggtwu.net/eev-haskell.html",
  f = function (sh, si)
      si:add_filling(1, 0, "help", sh.help)  -- not sh.help:url()
      local str = si:sexp_strarg(2)
      if str then
	local str1 = "https://hackage.haskell.org/package/" .. str
        si:add_filling(2, 1, "tgt", str1)
      end
    end,
}

-- «find-cabal-links-tests»  (to ".find-cabal-links-tests")
-- «find-cabal-unpack-tests»  (to ".find-cabal-unpack-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-cabal-links "kan-extensions") ]]
= sexp_to_target_st  [[ (find-cabal-links "kan-extensions") ]]
= sexp_to_target_si  [[ (find-cabal-unpack "kan-extensions") ]]
= sexp_to_target_st  [[ (find-cabal-unpack "kan-extensions") ]]

--]==]


--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-2022eevwconfigvideo "1:02:15" "many years") ]]
= sexp_to_target_st  [[ (find-2022eevwconfigvideo "1:02:15" "many years") ]]

--]==]



-- «code_helponly2_lines»  (to ".code_helponly2_lines")
code_helponly2_lines [=[
  find-find-links-links-new => (find-eev "eev-tlinks.el" "find-find-links-links-new")
  find-pdftools-page        => (find-eev "eev-pdflike.el" "find-pdftools-page")
  find-pdftoolsr-page       => (find-eev "eev-pdflike.el" "find-pdftoolsr-page")
]=]

code_helponly2_lines [[
  find-tikz1-links      => (find-angg "LUA/tikz1.el" "find-tikz1-links")
  find-tikzsearch-links => (find-angg "LUA/tikz1.el" "find-tikzsearch-links")
  tiks                  => (find-angg "LUA/tikz1.el" "tiks")
  tikz-show             => (find-angg "LUA/tikz1.el" "tikz-show")
  tikz-showtex          => (find-angg "LUA/tikz1.el" "tikz-showtex")
  ee-copy-rest          => (find-eev "eev-tlinks.el" "ee-copy-rest")
  ee-copy-rest-3        => (find-eev "eev-tlinks.el" "ee-copy-rest-3-intro")
  eepitch-sly           => (find-try-sly-intro "6. Sly: basic keys")
]]

code_c_d_remote("tikzgitfile",    "https://github.com/pgf-tikz/pgf/tree/master/")
code_c_d_remote("tikzmanfile",    "https://github.com/pgf-tikz/pgf/tree/master/doc/generic/pgf/")
code_c_d_remote("tikztgpgitfile", "https://github.com/pgf-tikz/pgf/tree/master/tex/generic/pgf/")
code_c_d_remote("fennelfile",     "https://git.sr.ht/~technomancy/fennel/tree/main/item/")
code_c_d_remote("sbclfile",       "https://sourceforge.net/p/sbcl/sbcl/ci/master/tree/")
code_c_d_remote("maximagitfile",  "https://sourceforge.net/p/maxima/code/ci/master/tree/")

code_c_d_remote("slyfile",        "https://github.com/joaotavora/sly/tree/master/")
code_c_d_remote("slynkfile",      "https://github.com/joaotavora/sly/tree/master/slynk/")
code_c_d_remote("qlslyfile",      "https://github.com/joaotavora/sly/tree/master/")
code_c_d_remote("qlslynkfile",    "https://github.com/joaotavora/sly/tree/master/slynk/")

code_c_d_remote("lpegrexfile",    "https://github.com/edubart/lpegrex/blob/main/")
code_c_d_remote("efile",          "https://github.com/emacs-mirror/emacs/blob/master/lisp/")
code_c_d_remote("emacslibpqfile", "https://github.com/anse1/emacs-libpq/blob/master/")
code_c_d_remote("grailfile",      "https://github.com/bitcathedrals/grail/blob/develop/")
code_c_d_remote("nodejssrcfile",  "https://github.com/nodejs/node/tree/main/")
code_c_d_remote("lean4prefile",   "https://github.com/leanprover/lean4/blob/master/src/")
code_c_d_remote("leanmetadocrfile", "https://github.com/leanprover-community/lean4-metaprogramming-book/tree/master/lean/")
code_c_d_remote("lspmodegitfile", "https://github.com/emacs-lsp/lsp-mode/blob/master/")

-- (find-squeakbyexpage 43)
-- = _SH["find-squeakbyexpage"]
code_pdf("squeakbyex", "http://anggtwu.net/SQUEAK/squeak-by-example-5.3.pdf")
code_pdf("fplean4",    "http://anggtwu.net/LEAN/fplean4.pdf")
code_pdf("touretzky",  "https://www.cs.cmu.edu/~dst/LispBook/book.pdf")
code_pdf("lisp15",      "https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf")

-- (find-es "maxima" "maxima-by-example-ccds")
code_pdf("mbe01", "https://home.csulb.edu/~woollett/mbe1intro.pdf")
code_pdf("mbe02", "https://home.csulb.edu/~woollett/mbe2plotfit.pdf")
code_pdf("mbe03", "https://home.csulb.edu/~woollett/mbe3ode1.pdf")
code_pdf("mbe04", "https://home.csulb.edu/~woollett/mbe4solve.pdf")
code_pdf("mbe05", "https://home.csulb.edu/~woollett/mbe5matrix.pdf")
code_pdf("mbe06", "https://home.csulb.edu/~woollett/mbe6calc1.pdf")
code_pdf("mbe07", "https://home.csulb.edu/~woollett/mbe7sint.pdf")
code_pdf("mbe08", "https://home.csulb.edu/~woollett/mbe8nint.pdf")
code_pdf("mbe09", "https://home.csulb.edu/~woollett/mbe9bfloat.pdf")
code_pdf("mbe10", "https://home.csulb.edu/~woollett/mbe10fltrans.pdf")
code_pdf("mbe11", "https://home.csulb.edu/~woollett/mbe11fft.pdf")
code_pdf("mbe12", "https://home.csulb.edu/~woollett/mbe12dirac3.pdf")
code_pdf("mbe13", "https://home.csulb.edu/~woollett/mbe13qdraw.pdf")
code_pdf("mbe14", "https://home.csulb.edu/~woollett/mbe14fit.pdf")

-- (find-es "maxima" "maxima-workbook")
code_pdf("maximawb", "https://roland-salz.de/Maxima_Workbook.pdf")

-- (find-books "__logic/__logic.el" "martin-lof")
code_pdf("martinlofitt", "https://archive-pml.github.io/martin-lof/pdfs/Bibliopolis-Book-retypeset-1984.pdf")

-- (find-eev "eev-lean4.el" "ee-leandoc-:fplean4")
code_pdf("lean4",    "http://anggtwu.net/snarf/https/lean-lang.org/lean4/doc/print.pdf")
code_pdf("tpil4",    "http://anggtwu.net/snarf/https/lean-lang.org/theorem_proving_in_lean4/print.pdf")
code_pdf("leanmeta", "http://anggtwu.net/snarf/https/leanprover-community.github.io/lean4-metaprogramming-book/print.pdf")
code_pdf("fplean4",  "http://anggtwu.net/snarf/https/lean-lang.org/functional_programming_in_lean/print.pdf")
code_pdf("tclean4",  "http://anggtwu.net/snarf/https/ammkrn.github.io/type_checking_in_lean4/print.pdf")




-- «find-maximanode»  (to ".find-maximanode")
-- Skel: (find-sandwiches-def-links "find-maximanode")
--
_SH["find-maximanode"] = SexpHead {
  head = "find-maximanode",
  help = sexp_to_target_st [[ (find-TH "find-maximanode") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local node = si:sexp_strarg(2)
      if node then
        local oldR = R
        require "maxima-index-html"  -- (find-blogme3 "maxima-index-html.lua")
        R = oldR
        local html0 = maxima_index_table[node]
        local html = html0 and "https://maxima.sourceforge.io/docs/manual/"..html0
        if html then si:add_filling(2, 1, "node", html) end
      end
    end,
}

-- «find-maximanode-tests»  (to ".find-maximanode-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-maximanode "fundef") ]]
= sexp_to_target_st  [[ (find-maximanode "fundef") ]]
= sexp_to_target_si  [[ (find-maximanode "fundef0") ]]
= sexp_to_target_st  [[ (find-maximanode "fundef0") ]]

--]==]


-- «find-yttranscript-links»  (to ".find-yttranscript-links")
-- Skel: (find-sandwiches-def-links "find-yttranscript-links")
--
_SH["find-yttranscript-links"] = SexpHead {
  head = "find-yttranscript-links",
  help = sexp_to_target_st [[ (find-TH "2022-yttranscript") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local hash = si:sexp_strarg(3)
      if hash then
        si:add_filling(3, 1, "yt", youtube_make_url(hash))
      end
    end,
}

-- «find-yttranscript-links-tests»  (to ".find-yttranscript-links-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-yttranscript-links "eev2023replsb" "s3enXsuXyNg") ]]
= sexp_to_target_st  [[ (find-yttranscript-links "eev2023replsb" "s3enXsuXyNg") ]]

--]==]



-- «find-gitk»  (to ".find-gitk")
-- Skel: (find-sandwiches-def-links "find-gitk")
--
_SH["find-gitk"] = SexpHead {
  head = "find-gitk",
  help = sexp_to_target_st [[ (find-eev "eev-plinks.el" "find-gitk") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
    end,
}

-- «find-gitk-tests»  (to ".find-gitk-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-gitk "/tmp/eevgit-test1/") ]]
= sexp_to_target_st  [[ (find-gitk "/tmp/eevgit-test1/") ]]

--]==]


-- «code_lsubs»  (to ".code_lsubs")
-- See: (find-blogme3 "sandwiches.lua" "code_intro")
--
code_lsubs = function (c, mp4stem)
    local find_clsubs = "find-"..c.."lsubs"
    local baseurl = format("http://anggtwu.net/SUBTITLES/%s.lua.html", mp4stem)
    _SH[find_clsubs] = SexpHead {
      head = find_clsubs,
      -- help = SexpTarget {f="find_intro", stem=stem, anchor=nil},
      f = function (sh, si)
          -- si:add_filling(1, nil, "help", sh.help)
          local time = si:sexp_strarg(2)
          local target = baseurl .. (time and "#"..time or "")
          if time then
            si:add_filling(2, 1, "target", target)
          else
            si:add_filling("e", nil, "target", target)
          end
        end,
    }
  end

-- «code_lsubs-tests»  (to ".code_lsubs-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
code_lsubs("2024luaso", "2024-find-luaso-links")
= _SH["find-2024luasolsubs"]

= sexp_to_target_si  [[ (find-2024luasolsubs "00:00") ]]
= sexp_to_target_st  [[ (find-2024luasolsubs "00:00") ]]
= sexp_to_target_si  [[ (find-2024luasolsubs) ]]
= sexp_to_target_st  [[ (find-2024luasolsubs) ]]

--]==]



-- «code-lsubs»  (to ".code-lsubs")
-- Skel: (find-sandwiches-def-links "code-lsubs")
--
_SH["code-lsubs"] = SexpHead {
  head = "code-lsubs",
  -- help = sexp_to_target_st [[ (find-eev "eev-tlinks.el" "code-lsubs") ]],
  f = function (sh, si)
      -- si:add_filling(1, nil, "help", sh.help)
      local c       = si:sexp_strarg(2)
      local mp4stem = si:sexp_strarg(3)
      if c and mp4stem then
        code_lsubs(c, mp4stem)
        -- local lsubs = format("http://anggtwu.net/SUBTITLES/%s.lua.html", mp4stem)
        -- PP(c, mp4stem, lsubs)
        -- si:add_filling(2, 1, "yt", lsubs)
        -- si:add_filling(3, 1, "yt", lsubs)
      end
    end,
}

-- «code-lsubs-tests»  (to ".code-lsubs-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (code-lsubs "2024luaso" "2024-find-luaso-links") ]]
= sexp_to_target_st  [[ (code-lsubs "2024luaso" "2024-find-luaso-links") ]]
= sexp_to_target_si  [[ (find-2024luasolsubs "00:00") ]]
= sexp_to_target_st  [[ (find-2024luasolsubs "00:00") ]]
= sexp_to_target_si  [[ (find-2024luasolsubs) ]]
= sexp_to_target_st  [[ (find-2024luasolsubs) ]]

--]==]


-- «find-clhsdoci»  (to ".find-clhsdoci")
-- Skel: (find-sandwiches-def-links "find-clhsdoci")
--
_SH["find-clhsdoci"] = SexpHead {
  head = "find-clhsdoci",
  help = sexp_to_target_st [[ (find-try-sly-intro "2. Install some elisp packages") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local symbol = si:sexp_strarg(2)
      if symbol then
	local tbl = require "clhs-symbols"
        local tgt0 = tbl[symbol:upper()]
        local tgt1 = tgt0 and "http://clhs.lisp.se/"..tgt0
	if tgt1 then si:add_filling(2, 1, "tgt", tgt1) end
      end
    end,
}

-- «find-clhsdoci-tests»  (to ".find-clhsdoci-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= sexp_to_target_si  [[ (find-clhsdoci "require") ]]
= sexp_to_target_st  [[ (find-clhsdoci "require") ]]

--]==]


-- «find-anchor»  (to ".find-anchor")
-- Skel: (find-sandwiches-def-links "find-anchor")
--
_SH["find-anchor"] = SexpHead {
  head = "find-anchor",
  help = sexp_to_target_st [[ (find-eev-quick-intro "8.5. Hyperlinks to anchors in other files") ]],
  f = function (sh, si)
      si:add_filling(1, nil, "help", sh.help)
      local fname = si:sexp_strarg(2)
      local tag   = si:sexp_strarg(3)
      if fname and fname:sub(1,2) == "~/" then
        local target0 = "http://anggtwu.net/"..fname:sub(3)..".html"
        local target  = target0..(tag and "#"..tag or "")
        si:add_filling(2, 1, "tgt", target)
        if tag then
          si:add_filling(3, 1, "tgt", target)
        end
      end
    end,
}

-- «find-anchor-tests»  (to ".find-anchor-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
= ("abcde"):sub(1,2)
= sexp_to_target_si  [[ (find-anchor "~/lisptree/lisptree.mac") ]]
= sexp_to_target_st  [[ (find-anchor "~/lisptree/lisptree.mac") ]]

--]==]



-- «code-etex-tla»  (to ".code-etex-tla")
-- Skel: (find-sandwiches-def-links "code-etex-tla")
--  See: (find-blogme3 "code-etex-tlas.lua")
--
code_etex_tla_p = function (sh, si)
    local stem = sh.stem
    local url0 = format("http://anggtwu.net/LATEX/%s.pdf", stem)
    local p    = si:sexp_numericarg(2)
    if p then
      local url = format("%s#page=%d", url0, p)
      si:add_filling(2, 0, "p", url)
      if si:sexp_strarg(3) then
        si:add_filling(3, 1, "p", url)
      end
    else
      si:add_filling(1, 0, "p", url0)
    end
  end

code_etex_tla_a = function (sh, si)
    local stem = sh.stem
    local url0 = format("http://anggtwu.net/LATEX/%s.tex.html", stem)
    local tag  = si:sexp_strarg(2)
    if tag then
      local url = format("%s#%s", url0, tag)
      si:add_filling(2, 1, "a", url)
    else
      si:add_filling(1, 0, "a", url0)
    end
  end

code_etex_tla = function (tla, stem)
    _SH[tla.."p"] = SexpHead {
      head = tla.."p",
      tla  = tla,
      stem = stem,
      f    = code_etex_tla_p,
    }
    _SH[tla.."a"] = SexpHead {
      head = tla.."a",
      tla  = tla,
      stem = stem,
      f    = code_etex_tla_a,
    }
  end

-- «code-etex-tla-tests»  (to ".code-etex-tla-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches-defs.lua"
code_etex_tla("pat", "2024panic-teresopolis")
= sexp_to_target_si  [[ (patp 2 "toc") ]]
= sexp_to_target_st  [[ (patp 2 "toc") ]]
= sexp_to_target_si  [[ (patp)         ]]
= sexp_to_target_st  [[ (patp)         ]]
= sexp_to_target_si  [[ (pata   "toc") ]]
= sexp_to_target_st  [[ (pata   "toc") ]]
= sexp_to_target_si  [[ (pata)         ]]
= sexp_to_target_st  [[ (pata)         ]]

--]==]


-- «code-etex-tlas-load»  (to ".code-etex-tlas-load")
-- (find-blogme3 "code-etex-tlas.lua")
require "code-etex-tlas"


-- (find-blogme3 "sandwiches-defs.lua" "code-pdf-page")