上一篇:伪竖排
对每个人最偏心的莫过于工夫。绝大多数人的工夫,被极少数的人以花样繁多的管理学伎俩轻轻偷去了一部分。窃钱者蹲监狱,窃工夫者为老板。若每个人都能管好本人的工夫,天下必将大同。
工夫戳增强版
回顾一下之前在 card-env.tex 文件里定义的工夫戳:
\startluacodemy = {}function my.is_cjk_char(c) if c >= 0x3400 and c <= 0x4db5 or c >= 0x4e00 and c <= 0x9fa5 or c >= 0x9fa6 and c <= 0x9fbb or c >= 0xf900 and c <= 0xfa2d or c >= 0xfa30 and c <= 0xfa6a or c >= 0xfa70 and c <= 0xfad9 or c >= 0x20000 and c <= 0x2a6d6 or c >= 0x2f800 and c <= 0x2fa1d or c >= 0xff00 and c <= 0xffef or c >= 0x2e80 and c <= 0x2eff or c >= 0x3000 and c <= 0x303f or c >= 0x31c0 and c <= 0x31ef then return true; else return false; endendfunction my.rotate(x, a) pad = "\\kern.125em" for _, c in utf8.codes(x) do if my.is_cjk_char(c) then context("%s{\\rotate[rotation=%d]{%s}}%s", pad, a, utf8.char(c), pad) else context("{\\raise.5\\maxdepth\\hbox{%s}}", utf8.char(c)) end endend\stopluacode\def\timestamp#1{\rotate[rotation=270]{\ctxlua{my.rotate("#1", 90)}}}\setuptexttexts [margin] [][\hfill{\timestamp{2023 年 01 月 26 日 凌晨 04 时 44 分}}\hfill]
当初,将 \timestamp
定义为
\def\timestamp#1{% \page \setuptexttexts [margin][][\hfill{\rotate[rotation=270]{\ctxlua{my.rotate("#1", 90)}}}\hfill]}
重定义的 \timestamp
宏承受一个参数,应用 \page
另起新页,将参数内容安放于页面右侧留白区域。上面是 \timestamp
的用法示例:
\environment card-env\starttext\timestamp{2023 年 01 月 30 日}测试页 1\timestamp{2023 年 01 月 31 日}测试页 2\stoptext
\page
宏用于分页,仅在前后皆有内容时无效,例如
\starttext\pagefoo\pagebar\page\stoptext
其中,第一个和第三个 \page
是无用的,会被 TeX 编译器疏忽,只有第二个 \page
无效,使得 foo
和 bar
各占一页。
待办事项
用 ConTeXt 的 xtable 能够模仿风行一时的 To do List。
首先,结构一个三列的表格:
\environment card-env\starttext\timestamp{2023 年 01 月 31 日}\definextable[todolist]\startxtable[todolist] \startxrow \startxcell $\circ$ \stopxcell \startxcell 晒太阳 \stopxcell \startxcell $\checkmark$ \stopxcell \stopxrow \startxrow \startxcell $\circ$ \stopxcell \startxcell 包饺子 \stopxcell \startxcell $\checkmark$ \stopxcell \stopxrow \startxrow \startxcell $\circ$ \stopxcell \startxcell 拖地板 \stopxcell \startxcell $\checkmark$ \stopxcell \stopxrow\stopxtable\stoptext
假使排版后果未呈现 $\cdot$ 和 $\checkmark$ 符号,可在 card-env.tex 里设定数学字体:
\definefontfamily[myfont][serif][sourcehanserifcn]\definefontfamily[myfont][math][xitsmath] % <--- 增加这一行!\setscript[hanzi]\setupbodyfont[myfont,7pt]
当初暗藏表格的边框,将第一列宽度调整为 1.5em
,第二列宽度设置为 .9\textwidth
,即版心宽度的 0.9 倍,第三列宽度设置为 .1\textwidth
:
\setupxtable[todolist][frame=off]\startxtable[todolist] \startxrow \startxcell[width=1.5em] $\circ$ \stopxcell \startxcell[width=.9\textwidth] 晒太阳 \stopxcell \startxcell[width=.1\textwidth] $\checkmark$ \stopxcell \stopxrow \startxrow \startxcell $\circ$ \stopxcell \startxcell 包饺子 \stopxcell \startxcell $\checkmark$ \stopxcell \stopxrow \startxrow \startxcell $\circ$ \stopxcell \startxcell 拖地板 \stopxcell \startxcell \stopxcell \stopxrow\stopxtable
Lua 表 -> ConTeXt 表格
为了减少一条待办事项,须要写一堆命令,不胜其繁。因为这些宏的呈现具备重复性,因而能够思考用 Lua 编程的形式予以简化,因为在 Lua 语言里,表格的语法非常简单。例如
\startxtable \startxrow \startxcell 1\stopxcell \startxcell 2\stopxcell \startxcell 3\stopxcell \stopxrow\stopxtable
所表白的表格模式,用 Lua 的表构造可表述为
{1, 2, 3}
上面的示例可将 Lua 表构造转化为 ConTeXt 表格:
\environment card-env\startluacodemy = my or {}local ctx = contextfunction my.add(row) ctx.startxrow() for _, v in ipairs(row) do ctx.startxcell(); context(v); ctx.stopxcell() end ctx.stopxrow()end\stopluacode\def\foo#1{\ctxlua{my.add({#1})}}\starttext% 将表格单元长宽均设为 2em,且令内容居中\setupxtable[width=2em, height=2em, align={middle,lohi}]\startxtable\foo{4, 9, 2}\foo{3, 5, 7}\foo{8, 1, 6}\stopxtable\stoptext
以上述 Lua 代码为根底,略加修改,便可简化待办事项的增加:
\environment card-env\definextable[todolist]\setupxtable[todolist][frame=off]\startluacodemy = my or {}local ctx = contextlocal dim = number.todimenlocal textwidth = tex.dimen.textwidthfunction my.task(task, status) ctx.startxrow() -- 第一列 ctx.startxcell{width=dim(tex.sp("1.5em"))}; context("$\\circ$"); ctx.stopxcell() -- 第二列 ctx.startxcell{width=dim(0.9 * textwidth)}; context("%s", task); ctx.stopxcell() -- 第三列 ctx.startxcell{width=dim(0.1 * textwidth),align="{middle,lohi}"}; context(status); ctx.stopxcell() ctx.stopxrow()end\stopluacode\def\task#1#2{\ctxlua{my.task("#1", "#2")}}\starttext\timestamp{2023 年 01 月 31 日}\startxtable[todolist]\task{晒太阳}{$\\checkmark$}\task{包饺子}{$\\checkmark$}\task{拖地板}{}\stopxtable\stoptext
留神,在上述代码里,\circ
和 \checkmark
里的反斜线符号 \
呈现在 Lua 语境里时,须要增加反斜线 \
予以本义。若要躲避该问题,能够应用 Lua 的长字串语法。
Lua 长字串
以下 Lua i代码定义了 4 个字符串变量:
local a = "\\starttext ... \\stoptext"local b = [[\starttext ... \stoptext]]local c = [=[\starttext ... \stoptext]=]local d = [==[\starttext ... \stoptext]==]
其中,a
的值用的是 Lua 短字符串语法,而 b
,c
和 d
的值用的是 Lua 长字符串语法。在长字符串语法中,\
符号无需本义,且字符串能够间接换行,无需应用换行符 \n
。例如,短字符串
local a = "\\starttext\n ... \n\\stoptext"
与之等价的长字符串为
local a = [[\starttext ... \stoptext]]
基于 Lua 长字串语法,待办事项的宏定义与用法示例可批改为
\environment card-env\definextable[todolist]\setupxtable[todolist][frame=off]\startluacodemy = my or {}local ctx = contextlocal dim = number.todimenlocal textwidth = tex.dimen.textwidthfunction my.task(task, status) ctx.startxrow() -- 第一列 ctx.startxcell{width=dim(tex.sp("1.5em"))}; context([[$\circ$]]); ctx.stopxcell() -- 第二列 ctx.startxcell{width=dim(0.9 * textwidth)}; context([[%s]], task); ctx.stopxcell() -- 第三列 ctx.startxcell{width=dim(0.1 * textwidth),align="{middle,lohi}"}; context(status); ctx.stopxcell() ctx.stopxrow()end\stopluacode\def\task#1#2{\ctxlua{my.task([[#1]], [[#2]])}}\starttext\timestamp{2023 年 01 月 31 日}\startxtable[todolist]\task{晒太阳}{$\checkmark$}\task{包饺子}{$\checkmark$}\task{拖地板}{}\stopxtable\stoptext
将上述代码中的 \environment
和 \starttext
语句之间的代码挪移到 card-env.tex 文件。
结语
card.tex:
\environment card-env\starttext\timestamp{2023 年 01 月 31 日}\startxtable[todolist]\task{晒太阳}{$\checkmark$}\task{包饺子}{$\checkmark$}\task{拖地板}{}\stopxtable\stoptext
card-env.tex:
% 页面布局\definepapersize[card][width=85.6mm,height=53.98mm]\setuppapersize[card]\setuplayout [backspace=.1\paperwidth, width=.8\paperwidth, topspace=.015\paperheight, height=.97\paperheight, leftmargin=.666\backspace, rightmargin=.666\cutspace, headerdistance=.025\makeupheight, footerdistance=.025\makeupheight, textheight=.95\makeupheight]% 字体\definefontfamily[myfont][serif][sourcehanserifcn]\definefontfamily[myfont][math][xitsmath]\setscript[hanzi]\setupbodyfont[myfont,7pt]% 页码\setuppagenumbering[location=]\setupfootertexts[margin][][\hfill\pagenumber\hfill]% 题目\setuphead[title][align=middle]% 工夫戳\startluacodemy = {}function my.is_cjk_char(c) if c >= 0x3400 and c <= 0x4db5 or c >= 0x4e00 and c <= 0x9fa5 or c >= 0x9fa6 and c <= 0x9fbb or c >= 0xf900 and c <= 0xfa2d or c >= 0xfa30 and c <= 0xfa6a or c >= 0xfa70 and c <= 0xfad9 or c >= 0x20000 and c <= 0x2a6d6 or c >= 0x2f800 and c <= 0x2fa1d or c >= 0xff00 and c <= 0xffef or c >= 0x2e80 and c <= 0x2eff or c >= 0x3000 and c <= 0x303f or c >= 0x31c0 and c <= 0x31ef then return true; else return false; endendfunction my.rotate(x, a) pad = "\\kern.125em" for _, c in utf8.codes(x) do if my.is_cjk_char(c) then context("%s{\\rotate[rotation=%d]{%s}}%s", pad, a, utf8.char(c), pad) else context("{\\raise.5\\maxdepth\\hbox{%s}}", utf8.char(c)) end endend\stopluacode\def\timestamp#1{% \page \setuptexttexts [margin] [][\hfill{\rotate[rotation=270]{\ctxlua{my.rotate("#1", 90)}}}\hfill]}% 待办事项\definextable[todolist]\setupxtable[todolist][frame=off]\startluacodemy = my or {}local ctx = contextlocal dim = number.todimenlocal textwidth = tex.dimen.textwidthfunction my.task(task, status) ctx.startxrow() -- 第一列 ctx.startxcell{width=dim(tex.sp("1.5em"))}; context([[$\circ$]]); ctx.stopxcell() -- 第二列 ctx.startxcell{width=dim(0.9 * textwidth)}; context([[%s]], task); ctx.stopxcell() -- 第三列 ctx.startxcell{width=dim(0.1 * textwidth),align="{middle,lohi}"}; context(status); ctx.stopxcell() ctx.stopxrow()end\stopluacode\def\task#1#2{\ctxlua{my.task([[#1]], [[#2]])}}