|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file:
-- http://anggtwu.net/blogme3/sandwiches.lua.html
-- http://anggtwu.net/blogme3/sandwiches.lua
-- (find-angg "blogme3/sandwiches.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
-- Version: 2023oct23
-- This file is part of blogme3.
-- See: http://anggtwu.net/blogme3-sandwiches.html
-- (find-TH "blogme3-sandwiches")
-- Typical usage:
--
-- require "sandwiches-defs"
-- use_sand_htmlizeline()
--
-- See: (find-blogme3 "sandwiches-defs.lua")
-- (find-blogme3 "sandwiches-defs.lua" "use_sand_htmlizeline")
--
--
-- This file defines classes for transforming sexps into "sandwiches"
-- that alternate between parts that are plain text (slices of bread)
-- and parts that are hrefs with both a target URL and text
-- (fillings). For example, this sexp
--
-- (find-eev-intro "1." (+ -2 -3) +4 "foo" "bar")
--
-- can have these three intervals marked as "fillings":
--
-- (find-eev-intro "1." (+ -2 -3) +4 "foo" "bar")
-- -------------- :1: head
-- -- :2m: sec
-- --:e: end
--
-- its intervals are:
--
-- (find-eev-intro "1." (+ -2 -3) +4 "foo" "bar")
-- - :bread
-- -------------- :filling:1: head
-- -- :bread
-- -- :filling:2m: sec
-- ------------------------- :bread
-- --:filling:e: end
-- :bread
--
-- Each interval is represented by a "be" structure, that in the case
-- of bread is just a pair {b=<pos>, e=<pos>}, and in the case of
-- filling is a table {b=<pos>, e=<pos>, text=<string>, st=<st>},
-- where <st> is either a SexpTarget structure or nil. The
-- representation above displays for each filling the "name" of its
-- interval:
--
-- "1" means "first item of the sexp",
-- "2m" means "middle of the second item of the sexp",
-- "e" means "end of the sexp" (the '")"').
--
-- An object si of the class SexpIntervals has these fields:
--
-- si.line: the line that we are trying to htmlize,
--
-- si.left,si.sexp,si.head,si.skel,si.right: the results of running
-- getsexpr(si.line),
--
-- si.item_be_s: an array of "be"s with just the fields b and e,
-- one for each item,
--
-- si.filling_be_s: a table of "be"s with the fields b, e, and
-- text, and maybe st, indexed by `b's,
--
-- si.b_to_name: a table that lets us converts the `b's of
-- intervals that are fillings to their names, and back; the `b's
-- are numbers, and the names are strings.
--
-- The documentation at this moment consists mostly of test blocks.
-- See: (find-eepitch-intro "3. Test blocks")
-- «.getsexpr» (to "getsexpr")
-- «.SexpIntervals» (to "SexpIntervals")
-- «.SexpIntervals-tests» (to "SexpIntervals-tests")
-- «.find_node_encode» (to "find_node_encode")
-- «.find_node_encode-tests» (to "find_node_encode-tests")
-- «.SexpTarget» (to "SexpTarget")
-- «.SexpTarget-tests» (to "SexpTarget-tests")
-- «.SexpHead» (to "SexpHead")
-- «.SexpHead-tests» (to "SexpHead-tests")
-- «.code_helponly» (to "code_helponly")
-- «.code_helponly-tests» (to "code_helponly-tests")
-- «.HtmlizeLine» (to "HtmlizeLine")
-- «.HtmlizeLine-tests» (to "HtmlizeLine-tests")
-- «.code_c_d_angg» (to "code_c_d_angg")
-- «.code_c_d_angg-tests» (to "code_c_d_angg-tests")
-- «.code_c_d_remote» (to "code_c_d_remote")
-- «.code_c_d_remote-tests» (to "code_c_d_remote-tests")
-- «.code_intro» (to "code_intro")
-- «.code_intro-tests» (to "code_intro-tests")
-- «.code_c_m_b» (to "code_c_m_b")
-- «.code_c_m_b-tests» (to "code_c_m_b-tests")
-- «.code_youtube» (to "code_youtube")
-- «.code_youtube-tests» (to "code_youtube-tests")
-- «getsexpr» (to ".getsexpr")
-- Based on: (find-angg "LUA/lua50init.lua" "getsexp")
-- New version: (find-angg "LUA/SexpAtEol1.lua" "SexpAtEol-tests")
--
getsexpr = function (linestr)
local right = linestr:reverse():match("%s*"):reverse()
local linestr0 = linestr:sub(1, -#right-1)
local sexp, head, skel, left = getsexp(linestr0)
return sexp, head, skel, left, right
end
-- ____ ___ _ _
-- / ___| _____ ___ __|_ _|_ __ | |_ ___ _ ____ ____ _| |___
-- \___ \ / _ \ \/ / '_ \| || '_ \| __/ _ \ '__\ \ / / _` | / __|
-- ___) | __/> <| |_) | || | | | || __/ | \ V / (_| | \__ \
-- |____/ \___/_/\_\ .__/___|_| |_|\__\___|_| \_/ \__,_|_|___/
-- |_|
--
-- «SexpIntervals» (to ".SexpIntervals")
--
SexpIntervals = Class {
type = "SexpIntervals",
from = function (linestr)
local sexp, head, skel, left, right = getsexpr(linestr)
if not sexp then return end
local si = SexpIntervals {
line=str, -- Like '# (find-eev-intro "1.")'
sexp=sexp, -- like '(find-eev-intro "1.")'
head=head, -- like 'find-eev-intro'
skel=skel, -- like '(find-eev-intro "__")'
left=left, -- like '# '
right=right, -- like ''
}
local skelbody = " "..si.skel:sub(2,-2).." "
local item_be_s = {}
for b,e in skelbody:gmatch("()[^ \t]+()") do
table.insert(item_be_s, {b=b, e=e})
end
si.item_be_s = item_be_s
si.filling_be_s = VTable {} -- filling intervals, indexed by `b's
si.b_to_name = HTable {} -- `b's <-> `name's; for example 2 <-> "1"
return si
end,
__tostring = function (si) return si:tostring() end,
__index = {
--
-- When si.sexp = '(find-foopdf (+ -2 42) "Text")'
-- we have si:sexp_rawarg(1) = 'find-foopdf',
-- si:sexp_numericarg(2) = 40,
-- si:sexp_strarg(3) = 'Text'.
sexp_sub = function (si, b, e)
return si.sexp:sub(b, e-1)
end,
sexp_rawarg = function (si, n)
local be = si.item_be_s[n]
if not be then return end
return si:sexp_sub(be.b, be.e)
end,
sexp_strarg = function (si, n)
local rawarg = si:sexp_rawarg(n)
if not rawarg then return end
if not rawarg:match('^".*"$') then return end
return rawarg:sub(2, -2)
end,
sexp_numericarg = function (si, n)
local rawarg = si:sexp_rawarg(n)
if not rawarg then return end
if rawarg:match('^[-+]?%d+$') then return tonumber(rawarg) end
local body = rawarg:match('^%(%+ (.*)%)')
if body then
local total = 0
for _,k in ipairs(map(tonumber, split(body))) do
total = total + k
end
return total
end
end,
--
n_shrink_to_b_e_name = function (si, n, shrink)
if n == "e" then
local e = #si.sexp+1
local b = (si.sexp:sub(-2, -2) == '"') and e-2 or e-1
return b,e,"e"
end
local be = si.item_be_s[n]
if shrink == nil or shrink == 0 then return be.b, be.e, n.."" end
if shrink == 1 then return be.b+1, be.e-1, n.."m" end
error()
end,
add_filling0 = function (si, be)
local b,name = be.b, be.name
si.filling_be_s[b] = be
si.b_to_name[name] = b
si.b_to_name[b] = name
end,
add_filling = function (si, n, shrink, text, st)
local b,e,name = si:n_shrink_to_b_e_name(n, shrink)
local be = VTable {b=b, e=e, name=name, text=text}
be.st = (st and SexpTarget.from(st)) or SexpTarget.from(text)
-- if not be.st then be.st = SexpTarget {text=text} end
si:add_filling0(be)
return si
end,
--
dash = function (si, b, e)
return (" "):rep(b-1) .. ("-"):rep(e-b) .. (" "):rep(#si.sexp-e+1)
end,
be_name = function (si, be) return si.b_to_name[be.b] end,
filling_to_string = function (si, be)
return format("%s:filling:%s: %s",
si:dash(be.b, be.e),
si:be_name(be),
be.text)
end,
fillings_sorted = function (si)
local bes = {}
for _,b in ipairs(sorted(keys(si.filling_be_s))) do
table.insert(bes, si.filling_be_s[b])
end
return bes
end,
tostring = function (si)
local bigstr = si.sexp
for _,be in ipairs(si:fillings_sorted()) do
bigstr = bigstr.."\n"..si:filling_to_string(be)
end
return bigstr
end,
--
tosandwich = function (si)
local fills = si:fillings_sorted()
local bes, lastpos = VerticalTable {}, 1
local add = function (b, e, st)
table.insert(bes, {b=b, e=e, origtext=si:sexp_sub(b, e), st=st})
end
for _,be in ipairs(fills) do
add(lastpos, be.b)
add(be.b, be.e, be.st)
lastpos = be.e
end
add(lastpos, #si.sexp+1)
return bes
end,
--
name_to_st = function (si, name)
return si.filling_be_s[si.b_to_name[name]].st
end,
target_st = function (si)
local o = si.b_to_name["e"]
or si.b_to_name["2m"]
or si.b_to_name["2"]
or si.b_to_name["1"]
return si.filling_be_s[o].st
end,
--
-- :head_apply() uses the table of SexpHeads defined below.
head_apply = function (si)
local sh = _SH[si.head]
if sh then sh:f(si); return true end
end,
},
}
-- «SexpIntervals-tests» (to ".SexpIntervals-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches.lua"
si = SexpIntervals.from [[ (find-foopdf (+ -2 42) "Text") ]]
PPV(si)
= si:sexp_rawarg(1) --> "find-foopdf"
= si:sexp_numericarg(2) --> 40
= si:sexp_strarg(3) --> "Text"
= si
= si:add_filling(1, nil, "head")
= si:add_filling("e", nil, "end")
= si:add_filling(3, 1, "str")
= si:name_to_st("3m")
= si:target_st("e")
PPV(si:fillings_sorted())
= si:tosandwich()
--]==]
-- «find_node_encode» (to ".find_node_encode")
find_node_encode_1 = function (c)
local T = {[" "]="-", ["&"]="-"}
return T[c] or format("_%04x", string.byte(c))
end
find_node_encode = function (nodename)
return (nodename:gsub("([^A-Za-z0-9])", find_node_encode_1))
end
-- «find_node_encode-tests» (to ".find_node_encode-tests")
-- https://www.gnu.org/software/guile/manual/html_node/lambda_002a-and-define_002a
-- (find-guilenode "lambda* and define*")
-- (find-elnode "Char-Table Type")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches.lua"
= find_node_encode("lambda* and define*")
--]]
-- ____ _____ _
-- / ___| _____ ___ _|_ _|_ _ _ __ __ _ ___| |_
-- \___ \ / _ \ \/ / '_ \| |/ _` | '__/ _` |/ _ \ __|
-- ___) | __/> <| |_) | | (_| | | | (_| | __/ |_
-- |____/ \___/_/\_\ .__/|_|\__,_|_| \__, |\___|\__|
-- |_| |___/
--
-- «SexpTarget» (to ".SexpTarget")
--
infomanual_basedir = infomanual_basedir or VerticalTable {}
SexpTarget = Class {
type = "SexpTarget",
from = function (o)
if type(o) == "string" then return SexpTarget {text=o} end
if otype(o) == "SexpTarget" then return o end
error()
end,
__tostring = mytabletostring,
__index = {
url = function (st)
if st.f then return st[st.f](st) end
return st.text
end,
ru = function (st, relativeurl)
return "http://anggtwu.net/"..relativeurl -- change this
end,
--
find_angg = function (st)
local fname,anchor = st.fname, st.anchor
return st:ru(fname..(st.ext or ".html")..
(anchor and ("#"..anchor) or ""))
end,
find_intro = function (st)
local stem,anchor = st.stem, st.anchor
local anggurl = "eev-intros/find-"..stem.."-intro.html"
if anchor then anggurl = anggurl.."#"..anchor end
return st:ru(anggurl)
end,
find_node = function (st)
local manual,node = st.manual, st.node
local baseurl = infomanual_basedir[manual]
if not baseurl then return nil end
local shre = "([-'/ &])"
local shtable = {["-"] = "_002d", ["'"] = "_0027", ["/"] = "_002f",
[" "] = "-", ["&"] = "-"}
--local shnode = node and node:gsub("%s+", " "):gsub(shre, shtable)
local shnode = node and find_node_encode(node)
return baseurl..(shnode or "")
end,
find_youtube = function (st)
local hash,time = st.hash, st.time
return youtube_make_url(hash, time)
end,
find_pdf = function (st)
local pdfurl,page = st.pdfurl, st.page
return pdfurl..(page and "#page="..page or "")
end,
find_remote = function (st)
local baseurl,rest = st.baseurl, st.rest
return baseurl..rest
end,
},
}
-- «SexpTarget-tests» (to ".SexpTarget-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches.lua"
st = SexpTarget.from("foo")
= st
= st:url()
SexpTarget.__index.foo = function (st) return "FOO" end
= SexpTarget { f="foo" } :url()
SexpTarget.__index.foo = function (st) return "FOO"..st.a end
= SexpTarget { f="foo", a="AAA" } :url()
= SexpTarget { f="find_angg", fname="abc/def" } :url()
= SexpTarget { f="find_angg", fname="abc/def", anchor="ghi" } :url()
= SexpTarget { f="find_intro", stem="eev" } :url()
= SexpTarget { f="find_intro", stem="eev", anchor="1" } :url()
= SexpTarget { f="find_youtube", hash="0123456789abc" } :url()
= SexpTarget { f="find_youtube", hash="0123456789abc", time="1:23" } :url()
infomanual_basedir["emacs"] = "http://gnu/manual/emacs/"
= SexpTarget { f="find_node", manual="emacs" } :url()
= SexpTarget { f="find_node", manual="emacs", node="Sec 1-2/3" } :url()
= SexpTarget { f="find_node", manual="emAcs", node="Sec 1-2/3" } :url()
--]==]
-- ____ _ _ _
-- / ___| _____ ___ __ | | | | ___ __ _ __| |
-- \___ \ / _ \ \/ / '_ \| |_| |/ _ \/ _` |/ _` |
-- ___) | __/> <| |_) | _ | __/ (_| | (_| |
-- |____/ \___/_/\_\ .__/|_| |_|\___|\__,_|\__,_|
-- |_|
--
-- «SexpHead» (to ".SexpHead")
--
SexpHead = Class {
type = "SexpHead",
__tostring = mytabletostring,
__index = {
},
}
_SH = VerticalTable {}
-- «SexpHead-tests» (to ".SexpHead-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches.lua"
dofile "cruft-jan2024.lua"
_SH["foo"] = SexpHead {
e = "abc",
f = function (sh, si)
si:add_filling(1, nil, "FOO")
si:add_filling(2, 1, si:sexp_strarg(3))
si:add_filling("e", nil, sh.e)
end,
}
si = SexpIntervals.from [[ (foo "def" "ghi") ]]
si:head_apply()
= si
= _SH["foo"]
= _SH
--]==]
-- _ _ _ _
-- ___ ___ __| | ___ | |__ ___| |_ __ ___ _ __ | |_ _
-- / __/ _ \ / _` |/ _ \ | '_ \ / _ \ | '_ \ / _ \| '_ \| | | | |
-- | (_| (_) | (_| | __/ | | | | __/ | |_) | (_) | | | | | |_| |
-- \___\___/ \__,_|\___|___|_| |_|\___|_| .__/ \___/|_| |_|_|\__, |
-- |_____| |_| |___/
--
-- «code_helponly» (to ".code_helponly")
-- (find-blogme3 "sandwiches-defs.lua" "code_helponly2")
--
code_helponly = function (head, stem, anchor)
_SH[head] = SexpHead {
head = head,
help = SexpTarget {f="find_intro", stem=stem, anchor=anchor},
f = function (sh, si)
si:add_filling(1, nil, "help", sh.help)
end,
}
end
code_helponly_line = function (linestr)
local si = SexpIntervals.from(linestr)
if not si then return end
local head = bitrim(si.left)
local stem = si.head:match "find%-(.*)%-intro(.*)"
local posspec = si:sexp_strarg(2)
local anchor = posspec and posspec:match "^(%d[.%d]*)%."
code_helponly(head, stem, anchor)
end
code_helponly_lines = function (bigstr)
for _,linestr in ipairs(splitlines(bigstr)) do
code_helponly_line(linestr)
end
end
-- «code_helponly-tests» (to ".code_helponly-tests")
--
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches.lua"
code_helponly_lines [[
eelatex-bounded (find-bounded-intro)
eev-bounded (find-bounded-intro)
eek (find-eev-quick-intro "3. Elisp hyperlinks")
find-efunction (find-eev-quick-intro "3. Elisp hyperlinks")
]]
= _SH
si = SexpIntervals.from [[ (eek "H e l l o") ]]
si:head_apply()
= si
= si:tosandwich()
--]==]
-- _ _ _ _ _ _ _
-- | | | | |_ _ __ ___ | (_)_______| | (_)_ __ ___
-- | |_| | __| '_ ` _ \| | |_ / _ \ | | | '_ \ / _ \
-- | _ | |_| | | | | | | |/ / __/ |___| | | | | __/
-- |_| |_|\__|_| |_| |_|_|_/___\___|_____|_|_| |_|\___|
--
-- «HtmlizeLine» (to ".HtmlizeLine")
--
HtmlizeLine = Class {
type = "HtmlizeLine",
__index = {
left = function (hl, str) return str end,
plain = function (hl, str) return str end,
href = function (hl, url, text)
return format('<a href="%s">%s</a>', url, text)
end,
be = function (hl, be)
local texthtml = hl:plain(be.origtext)
local url = be.st and be.st:url()
if url then return hl:href(url, texthtml) end
return texthtml
end,
sandwich = function (hl, sand)
local bigstr = ""
for _,be in ipairs(sand) do bigstr = bigstr..hl:be(be) end
return bigstr
end,
line = function (hl, linestr)
local si = SexpIntervals.from(linestr)
if not si then return hl:left(linestr) end
if not si:head_apply() then return hl:left(linestr) end
DBG("s530")
local left,right = si.left, si.right
local sandwich = si:tosandwich()
DBG("s533")
local html = hl:left(left) .. hl:sandwich(sandwich) .. right
DBG("s535")
return html,si
end,
},
}
-- «HtmlizeLine-tests» (to ".HtmlizeLine-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches.lua"
code_helponly_lines [[
eev-bounded (find-bounded-intro)
eek (find-eev-quick-intro "3. Elisp hyperlinks")
]]
hl = HtmlizeLine {}
linestr = [[ (eek "H e l l o") ]]
html,si = hl:line(linestr)
= html
= si
= si:tosandwich()
linestr = [[ (foo) ]]
= hl:line(linestr)
--]==]
-- _ _
-- ___ ___ __| | ___ ___ __| | __ _ _ __ __ _ __ _
-- / __/ _ \ / _` |/ _ \ / __| / _` | / _` | '_ \ / _` |/ _` |
-- | (_| (_) | (_| | __/ | (__ | (_| | | (_| | | | | (_| | (_| |
-- \___\___/ \__,_|\___|___\___|___\__,_|___\__,_|_| |_|\__, |\__, |
-- |_____| |_____| |_____| |___/ |___/
--
-- «code_c_d_angg» (to ".code_c_d_angg")
--
code_c_d_angg = function (c, d, ext)
local find_c = "find-"..c
_SH[find_c] = SexpHead {
head = find_c,
-- (find-eev-quick-intro "9. Shorter hyperlinks")
help = SexpTarget {f="find_intro", stem="eev-quick", anchor="9"},
f = function (sh, si)
si:add_filling(1, nil, "help", sh.help)
local a, b = si:sexp_strarg(2), si:sexp_strarg(3)
if a then
local target = SexpTarget {f="find_angg", fname=d..a, anchor=b, ext=ext}
si:add_filling("e", nil, "target", target)
end
end,
}
end
-- «code_c_d_angg-tests» (to ".code_c_d_angg-tests")
--
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches.lua"
code_c_d_angg("LATEX", "LATEX/")
linestr = [[ (find-LATEX "2021haskell.tex" "title") ]]
si = SexpIntervals.from(linestr)
si:head_apply()
= si
= si:tosandwich()
--]==]
-- _ _ _
-- ___ ___ __| | ___ ___ __| | _ __ ___ _ __ ___ ___ | |_ ___
-- / __/ _ \ / _` |/ _ \ / __| / _` | | '__/ _ \ '_ ` _ \ / _ \| __/ _ \
-- | (_| (_) | (_| | __/ | (__ | (_| | | | | __/ | | | | | (_) | || __/
-- \___\___/ \__,_|\___|___\___|___\__,_|___|_| \___|_| |_| |_|\___/ \__\___|
-- |_____| |_____| |_____|
--
-- «code_c_d_remote» (to ".code_c_d_remote")
--
code_c_d_remote = function (c, baseurl)
local find_c = "find-"..c
_SH[find_c] = SexpHead {
head = find_c,
-- (find-eev-quick-intro "9. Shorter hyperlinks")
help = SexpTarget {f="find_intro", stem="eev-quick", anchor="3"},
f = function (sh, si)
si:add_filling(1, nil, "help", sh.help)
local a = si:sexp_strarg(2)
if a then
local target = SexpTarget {f="find_remote", baseurl=baseurl, rest=a}
local shrink = (a == "") and 0 or 1
si:add_filling(2, shrink, "target", target)
end
end,
}
end
-- «code_c_d_remote-tests» (to ".code_c_d_remote-tests")
--
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches.lua"
code_c_d_remote("lua51manual", "http://www.lua.org/manual/5.1/manual.html")
linestr = [[ (find-lua51manual "" "title") ]]
linestr = [[ (find-lua51manual "#2.1" "title") ]]
si = SexpIntervals.from(linestr)
si:head_apply()
= si
= si:tosandwich()
--]==]
-- _ _ _
-- ___ ___ __| | ___ (_)_ __ | |_ _ __ ___
-- / __/ _ \ / _` |/ _ \ | | '_ \| __| '__/ _ \
-- | (_| (_) | (_| | __/ | | | | | |_| | | (_) |
-- \___\___/ \__,_|\___|___|_|_| |_|\__|_| \___/
-- |_____|
--
-- «code_intro» (to ".code_intro")
--
code_intro = function (stem)
local find_stem_intro = "find-"..stem.."-intro"
_SH[find_stem_intro] = SexpHead {
head = find_stem_intro,
help = SexpTarget {f="find_intro", stem=stem, anchor=nil},
f = function (sh, si)
si:add_filling(1, nil, "help", sh.help)
local a = si:sexp_strarg(2)
local anchor = a and a:match("^(%d[.%d]*)%.")
local target = anchor and SexpTarget {f="find_intro", stem=stem, anchor=anchor}
si:add_filling("e", nil, "target", target or sh.help)
end,
}
end
-- «code_intro-tests» (to ".code_intro-tests")
--
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches.lua"
code_intro("foobar")
linestr = [[ (find-foobar-intro "42.3. plic") ]]
si = SexpIntervals.from(linestr)
si:head_apply()
= si
= si:tosandwich()
--]==]
-- _ _
-- ___ ___ __| | ___ ___ _ __ ___ | |__
-- / __/ _ \ / _` |/ _ \ / __| | '_ ` _ \ | '_ \
-- | (_| (_) | (_| | __/ | (__ | | | | | | | |_) |
-- \___\___/ \__,_|\___|___\___|___|_| |_| |_|___|_.__/
-- |_____| |_____| |_____|
--
-- «code_c_m_b» (to ".code_c_m_b")
-- Skel: (find-sandwiches-def-links "find-enode")
--
code_c_m_b_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 {f="find_node", manual=manual, node=a}
if target then si:add_filling("e", nil, "target", target) end
end
code_c_m_b = function (c, manual, basedir)
infomanual_basedir[manual] = basedir
local find_cnode = "find-"..c.."node"
_SH[find_cnode] = SexpHead {
head = find_cnode,
-- (find-eev-quick-intro "9.2. Extra arguments to `code-c-d'")
help = SexpTarget {f="find_intro", stem="eev-quick", anchor="9.2"},
f = code_c_m_b_f,
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 {f="find_node", manual=manual, node=a}
if target then si:add_filling("e", nil, "target", target) end
end,
}
end
-- «code_c_m_b-tests» (to ".code_c_m_b-tests")
--
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches.lua"
dofile "cruft-jan2024.lua" -- (find-blogme3file "cruft-jan2024.lua")
code_c_m_b("e", "emacs", "http://www.gnu.org/software/emacs/manual/html_node/emacs/")
linestr = [[ (find-enode "Keys") ]]
si = SexpIntervals.from(linestr)
si:head_apply()
= si
= si:tosandwich()
-- Not working yet:
= sexp_to_target_si [[ (find-enode "37675653 202207 1" "structural") ]]
= sexp_to_target_st [[ (find-enode "37675653 202207 1" "structural") ]]
--]==]
-- _ _ _
-- ___ ___ __| | ___ _ _ ___ _ _| |_ _ _| |__ ___
-- / __/ _ \ / _` |/ _ \ | | | |/ _ \| | | | __| | | | '_ \ / _ \
-- | (_| (_) | (_| | __/ | |_| | (_) | |_| | |_| |_| | |_) | __/
-- \___\___/ \__,_|\___|____\__, |\___/ \__,_|\__|\__,_|_.__/ \___|
-- |_____|___/
--
-- «code_youtube» (to ".code_youtube")
--
code_youtube = function (c, hash)
local find_c = "find-"..c
_SH[find_c] = SexpHead {
head = find_c,
-- (find-audiovideo-intro "4. Short hyperlinks to audio and video files")
help = SexpTarget {f="find_intro", stem="audiovideo", anchor="4"},
f = function (sh, si)
si:add_filling(1, nil, "help", sh.help)
local time = si:sexp_strarg(2)
if time then
local target = SexpTarget {f="find_youtube", hash=hash, time=time}
si:add_filling(2, 1, "target", target)
end
end,
}
end
-- «code_youtube-tests» (to ".code_youtube-tests")
--
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "sandwiches.lua"
code_youtube("eev2019video", "86yiRG8YJD0")
linestr = [[ (find-eev2019video "15:56") ]]
si = SexpIntervals.from(linestr)
si:head_apply()
= si
= si:tosandwich()
--]==]