diff --git a/CCNUthesis-main.bib b/CCNUthesis-main.bib index 29513d1..2ffa673 100644 --- a/CCNUthesis-main.bib +++ b/CCNUthesis-main.bib @@ -1,182 +1,426 @@ -%%%% 文献类型 %%%% -%% 注:下面以 -%% xxx -%% Required Fields: xxx, xxx, xxx(必须要填写的信息) -%% Optional Fields: xxx, xxx, xxx(选填的信息) -%% 的格式介绍各种文献类型 -% article|book|unpublished|mastersthesis|phdthesis| -% inproceedings|proceedings|techreport|misc| -% article An article from a journal or magazine. -% Required Fields: author, title, journal, year. -% Optional Fields: volume, number, pages, month, note. -% book A book with an explicit publisher. -% Required Fields: author or editor, title, publisher, year. -% Optional Fields: volume or number, series, address, edition, month, note. -% unpublished A document having an author and title, but not formally published. -% Required Fields: author, title, note. -% Optional Fields: month, year. -% mastersthesis A Master's thesis. -% Required Fields: author, title, school, year. -% Optional Fields: type, address, month, note. -% phdthesis A PhD thesis. -% Required Fields: author, title, school, year. -% Optional Fields: type, address, month, note. -% inproceedings 会议论文【集】的一篇文章 -% An article in a conference proceedings. -% Required Fields: author, title, booktitle, year. -% Optional Fields: editor, volume or number, series, pages, -% address, month, organization, publisher, note. -% proceedings The proceedings of a conference. -% Required Fields: title, year. -% Optional Fields: editor, volume or number, series, address, month, -% organization, publisher, note. -% techreport A report published by a school or other institution, -% usually numbered within a series. -% Required Fields: author, title, institution, year. -% Optional Fields: type, number, address, month, note. -% misc Use this type when nothing else fits. -% Required Fields: none. -% Optional Fields: author, title, howpublished, month, year, note. -%%%% 数据类型 %%%% -%% 注:下面的数据不是所有文献都有,根据需要自行填写,但尽可能完整全面 -% title 标题 -% author 作者 -% 多个作者之间用“and”连接,如(注意空格 -% “夏康玮 and 夏康玮 and 夏康玮” -% “Feynman, Richard P and Leighton, Robert B and Sands, Matthew” -% year 年份 -% publisher 出版社 -% address 出版地 -% edition 版本 -% 第一版不标注 -% 中文用“第二版” -% 英文用数字“2” -% volume 卷 -% journal 期刊 -% number 期刊号 -% pages 页码,若不是一页,用小横杠“-”连接,如“1-10 -% school 哪所学校的学位论文 -% url 网址(比如网络上的文章) -% 注意如果有“%”要用“\%”来转译%,否则会被当作注释符号 -% note Any additional information that can help the reader. -% The First word should be capitalized. -% howpublished How something strange has been published. -% The First word should be capitalized. -%%%% 格式 %%%% -% @文献类型{引用词, -% ={}, -% ={}, -% ={} -% } -% 注意上面的逗号都是【英文逗号】,且注意中的内容中的空格 -% 引用词是在正文里引用时用到的: \cite{<引用词>} -% 通常由【作者名】、【年份】和【文章名的部分】组成 -% 方便区分以及看到就知道引用的是哪篇文献 -%%%% 示例 %%%% -% 下面的数据内容仅为示例用,可能有误 -% @book{曾谨言2013量子力学, -% title={量子力学: 卷 I}, -% author={曾谨言 and 曾谨言 and 曾谨言 and 曾谨言}, -% year={2013}, -% publisher={科学出版社}, -% address={北京}, -% pages={1-10}, -% } -% @book{feynman2011feynman, -% title={The Feynman lectures on physics, Vol. I: The new millennium edition: mainly mechanics, radiation, and heat}, -% author={Feynman, Richard P and Leighton, Robert B and Sands, Matthew}, -% year={2011}, -% publisher={Basic books}, -% volume={1}, -% pages={2-8} -% } - -% @article{zurek2014quantum, -% title={Quantum Darwinism, classical reality, and the randomness of quantum jumps}, -% author={Zurek, Wojciech H}, -% journal={arXiv preprint arXiv:1412.5206}, -% year={2014}, -% volume={1}, -% number={7}, -% pages={2-8} -% } - -% @misc{wikimedia:stern-gerlach-experiment, -% author={Wikimedia Commons}, -% title={File:Stern-Gerlach experiment zh.png --- Wikimedia Commons{,} the free media repository}, -% year={2016}, -% url={https://commons.wikimedia.org/w/index.php?title=File:Stern-Gerlach_experiment_zh.png&oldid=221590546}, -% note={[Online; accessed 25-July-2019]}, -% } -%%%% 示例结束 %%%% - - - -%%%% 用户的bib数据库 %%%% -@book{曾谨言2013量子力学, - title={量子力学: 卷 I}, - author={曾谨言 and 曾谨言 and 曾谨言 and 曾谨言}, - year={2013}, - publisher={科学出版社}, - address={北京}, - pages={1-10}, - edition={第二版} -} -@book{feynman2011feynman, - title={The Feynman lectures on physics, Vol. I: The new millennium edition: mainly mechanics, radiation, and heat}, - author={Feynman, Richard P and Leighton, Robert B and Sands, Matthew}, - volume={1}, - year={2011}, - publisher={Basic books}, - pages={2-8}, - edition={7}, -} - -@article{zurek2014quantum, - title={Quantum Darwinism, classical reality, and the randomness of quantum jumps}, - author={Zurek, Wojciech H}, - journal={arXiv preprint arXiv:1412.5206}, - year={2014}, - volume={1}, - number={7}, - pages={2-8}, -} - -@book{cohen2013claude, - title={Claude Cohen-Tannoudji; Bernard Diu; Franck Lalo{\"e}: Quantenmechanik}, - author={Cohen-Tannoudji, Claude and Diu, Bernard and Lalo{\"e}, Franck}, - volume={1}, - year={2013}, - publisher={Walter de Gruyter}, - edition={Second}, -} - -@misc{zettili2003quantum, - title={Quantum mechanics: concepts and applications}, - author={Zettili, Nouredine}, - year={2003}, - publisher={AAPT} -} - -@misc{wikimedia:stern-gerlach-experiment, - author={Wikimedia Commons}, - title={File:Stern-Gerlach experiment zh.png --- Wikimedia Commons{,} the free media repository}, - year={2016}, - url={https://commons.wikimedia.org/w/index.php?title=File:Stern-Gerlach_experiment_zh.png&oldid=221590546}, - note={[Online; accessed 25-July-2019]}, -} - -@inproceedings{邱泽奇建构与分化, - author = {邱泽奇}, - title = {建构与分化:当代中国社会结构的过程}, - booktitle = {社区研究与社会发展}, - year = {2012}, - editor = {潘乃谷,马戎}, - editortype = {editor}, - booksubtitle = {中国社会学纪念费孝通教授学术活动60周年学术讨论会}, - date = {2012}, - location = {北京}, - address = {天津}, - publisher = {海洋出版社}, - organization = {组织} +%%%% 文献类型 %%%% +%% 注:下面以 +%% xxx +%% Required Fields: xxx, xxx, xxx(必须要填写的信息) +%% Optional Fields: xxx, xxx, xxx(选填的信息) +%% 的格式介绍各种文献类型 +% article|book|unpublished|mastersthesis|phdthesis| +% inproceedings|proceedings|techreport|misc| +% article An article from a journal or magazine. +% Required Fields: author, title, journal, year. +% Optional Fields: volume, number, pages, month, note. +% book A book with an explicit publisher. +% Required Fields: author or editor, title, publisher, year. +% Optional Fields: volume or number, series, address, edition, month, note. +% unpublished A document having an author and title, but not formally published. +% Required Fields: author, title, note. +% Optional Fields: month, year. +% mastersthesis A Master's thesis. +% Required Fields: author, title, school, year. +% Optional Fields: type, address, month, note. +% phdthesis A PhD thesis. +% Required Fields: author, title, school, year. +% Optional Fields: type, address, month, note. +% inproceedings 会议论文【集】的一篇文章 +% An article in a conference proceedings. +% Required Fields: author, title, booktitle, year. +% Optional Fields: editor, volume or number, series, pages, +% address, month, organization, publisher, note. +% proceedings The proceedings of a conference. +% Required Fields: title, year. +% Optional Fields: editor, volume or number, series, address, month, +% organization, publisher, note. +% techreport A report published by a school or other institution, +% usually numbered within a series. +% Required Fields: author, title, institution, year. +% Optional Fields: type, number, address, month, note. +% misc Use this type when nothing else fits. +% Required Fields: none. +% Optional Fields: author, title, howpublished, month, year, note. +%%%% 数据类型 %%%% +%% 注:下面的数据不是所有文献都有,根据需要自行填写,但尽可能完整全面 +% title 标题 +% author 作者 +% 多个作者之间用“and”连接,如(注意空格 +% “夏康玮 and 夏康玮 and 夏康玮” +% “Feynman, Richard P and Leighton, Robert B and Sands, Matthew” +% year 年份 +% publisher 出版社 +% address 出版地 +% edition 版本 +% 第一版不标注 +% 中文用“第二版” +% 英文用数字“2” +% volume 卷 +% journal 期刊 +% number 期刊号 +% pages 页码,若不是一页,用小横杠“-”连接,如“1-10 +% school 哪所学校的学位论文 +% url 网址(比如网络上的文章) +% 注意如果有“%”要用“\%”来转译%,否则会被当作注释符号 +% note Any additional information that can help the reader. +% The First word should be capitalized. +% howpublished How something strange has been published. +% The First word should be capitalized. +%%%% 格式 %%%% +% @文献类型{引用词, +% ={}, +% ={}, +% ={} +% } +% 注意上面的逗号都是【英文逗号】,且注意中的内容中的空格 +% 引用词是在正文里引用时用到的: \cite{<引用词>} \parencite +% 通常由【作者名】、【年份】和【文章名的部分】组成 +% 方便区分以及看到就知道引用的是哪篇文献 +%%%% 示例 %%%% +% 下面的数据内容仅为示例用,可能有误 +% @book{曾谨言2013量子力学, +% title={量子力学: 卷 I}, +% author={曾谨言 and 曾谨言 and 曾谨言 and 曾谨言}, +% year={2013}, +% publisher={科学出版社}, +% address={北京}, +% pages={1-10}, +% } +% @book{feynman2011feynman, +% title={The Feynman lectures on physics, Vol. I: The new millennium edition: mainly mechanics, radiation, and heat}, +% author={Feynman, Richard P and Leighton, Robert B and Sands, Matthew}, +% year={2011}, +% publisher={Basic books}, +% volume={1}, +% pages={2-8} +% } + +% @article{zurek2014quantum, +% title={Quantum Darwinism, classical reality, and the randomness of quantum jumps}, +% author={Zurek, Wojciech H}, +% journal={arXiv preprint arXiv:1412.5206}, +% year={2014}, +% volume={1}, +% number={7}, +% pages={2-8} +% } + +% @misc{wikimedia:stern-gerlach-experiment, +% author={Wikimedia Commons}, +% title={File:Stern-Gerlach experiment zh.png --- Wikimedia Commons{,} the free media repository}, +% year={2016}, +% url={https://commons.wikimedia.org/w/index.php?title=File:Stern-Gerlach_experiment_zh.png&oldid=221590546}, +% note={[Online; accessed 25-July-2019]}, +% } +%%%% 示例结束 %%%% + + + +%%%% 用户的bib数据库 %%%% +@book{曾谨言2013量子力学, + title={量子力学: 卷 I}, + author={曾谨言 and 曾谨言 and 曾谨言 and 曾谨言}, + year={2013}, + publisher={科学出版社}, + address={北京}, + pages={1-10}, + edition={第二版} +} +@book{feynman2011feynman, + title={The Feynman lectures on physics, Vol. I: The new millennium edition: mainly mechanics, radiation, and heat}, + author={Feynman, Richard P and Leighton, Robert B and Sands, Matthew}, + volume={1}, + year={2011}, + publisher={Basic books}, + pages={2-8}, + edition={7}, +} + +@article{zurek2014quantum, + title={Quantum Darwinism, classical reality, and the randomness of quantum jumps}, + author={Zurek, Wojciech H}, + journal={arXiv preprint arXiv:1412.5206}, + year={2014}, + volume={1}, + number={7}, + pages={2-8}, +} + +@book{cohen2013claude, + title={Claude Cohen-Tannoudji; Bernard Diu; Franck Lalo{\"e}: Quantenmechanik}, + author={Cohen-Tannoudji, Claude and Diu, Bernard and Lalo{\"e}, Franck}, + volume={1}, + year={2013}, + publisher={Walter de Gruyter}, + edition={Second}, +} + +@misc{zettili2003quantum, + title={Quantum mechanics: concepts and applications}, + author={Zettili, Nouredine}, + year={2003}, + publisher={AAPT} +} + +@misc{wikimedia:stern-gerlach-experiment, + author={Wikimedia Commons}, + title={File:Stern-Gerlach experiment zh.png --- Wikimedia Commons{,} the free media repository}, + year={2016}, + url={https://commons.wikimedia.org/w/index.php?title=File:Stern-Gerlach_experiment_zh.png&oldid=221590546}, + note={[Online; accessed 25-July-2019]}, +} + +@inproceedings{邱泽奇建构与分化, + author = {邱泽奇}, + title = {建构与分化:当代中国社会结构的过程}, + booktitle = {社区研究与社会发展}, + year = {2012}, + editor = {潘乃谷,马戎}, + editortype = {editor}, + booksubtitle = {中国社会学纪念费孝通教授学术活动60周年学术讨论会}, + date = {2012}, + location = {北京}, + address = {天津}, + publisher = {海洋出版社}, + organization = {组织} +} + +%% 3,4,6的部分条目由于水平所限做了手动调整(输出结果含有见:的)(欺骗电脑,都有注释),使用时建议照着例子修改,防止出错 +%%1.期刊文献 +@article{李晓东, + author = {李晓东 and 张庆红 and 叶瑾琳}, + title = {气候学研究的若干理论问题}, + journaltitle = {北京大学学报:自然科学版}, + year = {1999}, + volume = {35}, + number = {1}, + pages = {101-106} +} + +% 这里的author采用了原样抄录法,这个时候输入什么输出什么 +@article{Ahn, + author = {{Ahn S} and {Tanksley SD}}, + title = {Comparative linkage maps of the rice and maize genomes}, + journaltitle = {Proceedings of the National Academy of Sciences of the United States of America}, + year = {1993}, + volume = {90}, + pages = {7980-7984} +} +%%2.杂志(报纸)文献 +@newspaper{丁文祥, + author = {丁文祥}, + title = {数字革命与竞争国际化}, + journaltitle = {中国青年报}, + date = {2000-11-20}, + number = {15} +} + +%%3.会议论文集 +%%为了与学校标准的标点符号一模一样,条目editor把编者和文集名写在一起这种操作是不得已而为之 +@inproceedings{张启发, + author = {张启发 and 李建雄}, + title = {水稻杂种优势的遗传和分子生物学基础的研究进展}, + editor = {王连铮 and 戴景瑞主编 and 全国作物育种学术讨论会论文集}, + booktitle = {中国作物学会第六届理事会暨全国作物育种学术讨论会,北京,1998}, + location = {北京}, + publisher = {中国农业科技术出版社}, + year = {1998}, + pages = {1-10}, +} +% 下面的例子没有使用骗系统的方法 +@proceedings{雷光春, + author = {雷光春}, + title = {综合湿地管理:综合湿地管理国际研讨会论文集}, + location = {北京}, + publisher = {海洋出版社}, + year = {2012}, +} +%% 4.会议论文(两个例子都借用了article类) +% 不得不使用article进行伪装,利用usera域手动改为字母C +% 两个volume都填了地点(本来这个是填入卷数),同样也是为了与标准一致 +@article{邱泽奇, + usera = {C}, + author = {邱泽奇}, + title = {建构与分化:当代中国社会结构的过程}, + journaltitle = {中国社会学纪念费孝通教授学术活动 60 周年学术讨论会 }, + year = {1996}, + volume = {北京}, +} +%% 拼音姓名,姓首字母大写并写全称,名写缩写,取每个字的拼音首字母大写 +@article{zhang, + usera = {C}, + author = {{Zhang Q} and {Gao YJ} and {Yang SH} and {Ragab R}}, + title = {Molecular marker-based analysis of heterosis in hybrid rice}, + journaltitle = {Abstract, 7th Annual Meeting of the Rockefeller Foundation's International Program on Rice Biotechnology}, + year = {1994}, + volume = {Bali, Indonesia}, +} + +% 5.普通图书 +@book{唐绪军, + author = {唐绪军}, + title = {报业经济与报业经营}, + location = {北京}, + publisher = {新华出版社}, + year = {1999}, + pages = {117-121}, +} + +@book{昂温, + author = {{昂温, G} and {昂温, P S}}, + title = {外国出版史}, + translator = {陈生铮}, + location = {北京}, + publisher = {中国书籍出版社}, + year = {1988}, +} +% 这里的author采用了系统自动,英文姓名会自动调整顺序并且全部大写(GB/T 7714-2015), +% 你在书的封面看到的是Henry D. Foth ,但录入为参考文献时变为FOTH H D, +% 也可采用1中第二个实例的直接抄录,但是要自己调整顺序,顺序规范详见GB/T 7714-2015. +@book{Foth, + author = {Henry D. Foth}, + title = {Fundamentals of soil science}, + edition = {7}, + location = {New York}, + publisher = {John Wiley & Sons}, + year = {1984}, + pages = {151-159}, +} + +% 6.专著章节或文集 +杨国枢.中国人对现代化的反应:心理学的观点[M].见:乔健主编, 中国人的观念与行为.天津:天津人民出版社,1995:209-239. + +%仍然是条件所限,为了与学校的要求一致的标点符号,把编者和书名同时写在booktitle +@inbook{杨国枢, + author = {杨国枢}, + title = {中国人对现代化的反应:心理学的观点}, + booktitle = {乔健主编, 中国人的观念与行为}, + location = {天津}, + publisher = {天津人民出版社}, + year = {1995}, + pages = {209-239}, +} +% 仍然是条件所限,为了与学校的要求一致的标点符号,把编者和书名同时写在booktitle +% 英文姓名录入采用原样抄录 +% 遇到文献名称有公式符号时,与正文一致,在$$中见写入相应的TeX代码,如$\mathrm{CO}_2$% +@inbook{Morison, + author = {{Morison JIL}}, + title = {Intercellular $\mathrm{CO}_2$ concentration and stomatal responses to $\mathrm{CO}_2$}, + booktitle = {Zeiger E, Farquhar GD, Cowan IR eds., Stomatal Function}, + location = {Stanford}, + publisher = {Stanford University Press}, + year = {1987}, + pages = {229-251} +} +为了达到一模一样的效果,对底层文件gb7714-2015.bbx进行了修改, +将第919行in={in\intitlepunct}改为in={In\intitlepunct}使得in中的i大写 + +%% 7.学位论文 +%% 由于要打出[硕士/博士学位论文]不得不借用book类型,用edition输入[博士学位论文] +%% 原来的机构institution变为publisher填写学校 +@book{张志祥, + usera = {D}, + author = {张志祥}, + title = {间断动力系统的随机扰动及其在守恒律方程中的应用}, + edition = {[博士学位论文]}, + location = {北京}, + publisher = {北京大学}, + year = {1998} +} + +@book{Aldemita, + usera = {D}, + author = {{Aldemita RR}}, + title = {Genetic Engineering of rice: Agrobacterium tumefaciens-mediatedtransformation of rice and evaluation of a corn pollen-specific promoter using the gusA gene in transgenic rice}, + edition = {(Ph D dissertation)}, + location = {West Lafyatte}, + publisher = {Purdue University}, + year = {1998} +} + +%% 8.专利 +@patent{张凯军, + author = {张凯军}, + title = {轨道火车及高速轨道火车紧急安全制动辅助装置}, + number = {201220158825.2}, + date = {2012-04-05} +} +%% 国别和专利号同时写在number中 +@patent{Kosek, + author = {{Kosek A} and {Momose H} and {Kawahito M} and {Alan Turling}}, + title = {Compiler}, + number = {US, 828402}, + date = {2002-05-25} +} + +%% 9.技术标准 +@standard{文献编写, + author = {全国文献工作标准化技术委员会第六分委员会}, + title = {GB 6447-86. 文献编写规则}, + location = {北京}, + publisher = {中国标准出版社}, + year = {1986} +} + + +%% 10.报告 +%% biblatex对这个地方信息缺省时处理,只好把两个时间都写在一起并借用条目location +两个时间第一个是出版时间,第二个是引用时间 +%% 有关OL:当有录入信息url时,就会有OL表示online,这里没有提供网址,但是 +%% 是online的,因此手动输入 +@report{国防白皮, + usera = {R/OL}, + author = {中华人民共和国国务院新闻办公室}, + title = {国防白皮书:中国武装力量的多样化运用}, + location = {2013-04-16[2014-06-11]} +} +%当author是个组织的时候一定要使用直接抄录 +@report{federal, + author = {{U.S. Department of Transportation Federal Highway Administration}}, + title = {Guidelines for bandling excavated acid-producing materials, PB 91-194001}, + location = {Springfield}, + institution = {U.S. Department of Commerce National Information Service}, + year = {1990}, + pages = {22-23} +} + +@report{health, + author = {{World Health Organization}}, + title = {Factors regulating the immune response: report of WHO Scientific Group}, + location = {Geneva}, + institution = {WHO}, + year = {1970}, + pages = {10-11} +} + +%%11.电子资源 +关于[文献类型标识/文献载体标识]的确定 +文献载体标识包括OL:联机网络 CD:光盘 DK:磁盘 MT:磁带 +只要有url项,文献载体标识就会是OL,如果无法录入url但是是从网上下载的资源, +需要手动添加usera={x/OL}, x由文献类别决定 +如果这个文献是纯电子资源或电子公告,文献类型标识为EB +这个EB不包括电子专著,电子连续出版物,电子学位论文,电子专利 +@article{江向东, + author = {江向东}, + title = {互联网环境下的信息处理与图书管理系统解决方案}, + journal = {情报学报}, + number = {2}, + volume = {18}, + year = {1998}, + pages = {4}, + urldate = {2000-01-18}, + url = {http://www.chinainfo.gov.cn/periodical/gbxb/gbxb99/gbxb990203} +} + +%%bib包不够完善当同时出现(更新或修改日期)[引用日期]且没有出版年的时候, +需要同时写在organization中 +@online{萧钮, + author = {萧钮}, + title = {出版业信息化迈入快车道}, + organization = {2001-12-19[2002-04-15]}, + url = {http://www.creader.com/news/20011219/200112190019.html} +} +%%录入英文文献时,需要区分各个信息的种类! +@online{PACS-L, + title = {PACS-L; the publi-access computer systems forum}, + organization = {Houston, Tex:University of Houston Libraries}, + year = {1989}, + urldate = {1995-05-17}, + url = {http://info.lib.uh.edu/pacsl.html} } \ No newline at end of file diff --git a/CCNUthesis-manual.pdf b/CCNUthesis-manual.pdf deleted file mode 100644 index 166d552..0000000 Binary files a/CCNUthesis-manual.pdf and /dev/null differ diff --git a/CCNUthesis-manual.tex b/CCNUthesis-manual.tex index f6e3f7f..8d5d48b 100644 --- a/CCNUthesis-manual.tex +++ b/CCNUthesis-manual.tex @@ -5,8 +5,8 @@ author = {夏康玮 \quad 林康益}, title = {CCNUthesis用户手册}, email = {kangweixia_xdyy@163.com}, - date = {2022-01-31}, - version = {0.0.1}, + date = {2022-02-19}, + version = {1.0.3}, github-repository = {https://github.com/xkwxdyy/CCNUthesis}, gitee-repository = {https://gitee.com/xkwxdyy/CCNUthesis}, } diff --git a/CCNUthesis.cls b/CCNUthesis.cls index ad20882..134d86b 100644 --- a/CCNUthesis.cls +++ b/CCNUthesis.cls @@ -1,7 +1,7 @@ \NeedsTeXFormat{LaTeX2e} \RequirePackage{expl3} \ProvidesExplClass{CCNUthesis} - {2022-02-01}{v1.0.2} + {2022-02-19}{v1.0.3} {Thesis template for Central China Normal University} \RequirePackage { xtemplate, l3keys2e } @@ -17,6 +17,12 @@ \@ifpackagelater {#1} { 2020/07/17 } { } { \msg_error:nnn { ccnuthesis } { l3-too-old } {#1} } } +\msg_new:nnn { ccnuthesis } { unsupported-engine } + { + The~ ccnuthesis~ class~ requires~ either~ XeTeX~ or~ LuaTeX. \\\\ + "#1"~ is~ not~ supported~ at~ present.~ You~ must~ change \\ + your~ typesetting~ engine~ to~ "xelatex"~ or~ "lualatex". + } \sys_if_engine_xetex:F { \sys_if_engine_luatex:F @@ -25,12 +31,6 @@ { \c_sys_engine_str } } } -\msg_new:nnn { ccnuthesis } { unsupported-engine } - { - The~ ccnuthesis~ class~ requires~ either~ XeTeX~ or~ LuaTeX. \\\\ - "#1"~ is~ not~ supported~ at~ present.~ You~ must~ change \\ - your~ typesetting~ engine~ to~ "xelatex"~ or~ "lualatex". - } \box_new:N \l__ccnu_tmpa_box \clist_new:N \l__ccnu_tmpa_clist \clist_new:N \l__ccnu_tmpb_clist @@ -194,7 +194,7 @@ { { no-math } { fontspec }, { perpage } { footmisc }, - { amsmath, thmmarks } { ntheorem } + % { amsmath, thmmarks } { ntheorem } } { \PassOptionsToPackage #1 } \LoadClass { ctexbook } @@ -207,7 +207,7 @@ geometry, fancyhdr, footmisc, - ntheorem, + % ntheorem, graphicx, longtable, caption, @@ -220,6 +220,8 @@ adjustbox, calc, etoolbox, + amsthm, + thmtools } \RequirePackage[titles]{tocloft} \graphicspath{{figures/}{logo/}} @@ -909,96 +911,96 @@ \hbox_to_wd:nn { 1.5 em } { \@thefnmark \hfil } #1 } -\clist_const:Nn \c__ccnu_thm_style_plain_clist - { plain, margin, change } -\clist_const:Nn \c__ccnu_thm_style_break_clist - { break, marginbreak, changebreak } -\tl_new:N \l__ccnu_thm_style_tl -\tl_new:N \l__ccnu_thm_header_font_tl -\tl_new:N \l__ccnu_thm_body_font_tl -\tl_new:N \l__ccnu_thm_qed_tl -\tl_new:N \l__ccnu_thm_counter_tl -\keys_define:nn { ccnu / theorem } - { - style .tl_set:N = \l__ccnu_thm_style_tl, - header-font .tl_set:N = \l__ccnu_thm_header_font_tl, - body-font .tl_set:N = \l__ccnu_thm_body_font_tl, - qed .tl_set:N = \l__ccnu_thm_qed_tl, - counter .tl_set:N = \l__ccnu_thm_counter_tl - } -\cs_new_eq:NN \__ccnu_thm_ntheorem_style:n \theoremstyle -\cs_new_eq:NN \__ccnu_thm_ntheorem_new:w \newtheorem -\RenewDocumentCommand \newtheorem { s o m m } - { - \IfBooleanTF {#1} - { \tl_set:Nn \l__ccnu_thm_qed_tl { \ensuremath { \square } } } - { \tl_set:Nn \l__ccnu_thm_qed_tl { } } - \tl_set:Nn \l__ccnu_thm_style_tl { plain } - \IfValueT {#2} { \keys_set:nn { ccnu / theorem } {#2} } - \ccnu_thm_set_header_font:V \l__ccnu_thm_header_font_tl - \ccnu_thm_set_body_font:V \l__ccnu_thm_body_font_tl - \ccnu_thm_set_qed:V \l__ccnu_thm_qed_tl - \IfBooleanTF {#1} - { - \clist_if_in:nVF { plain, break } \l__ccnu_thm_style_tl - { - \clist_if_in:NVTF - \c__ccnu_thm_style_plain_clist \l__ccnu_thm_style_tl - { \__ccnu_thm_redefine_style:n { plain } } - { - \clist_if_in:NVTF - \c__ccnu_thm_style_break_clist \l__ccnu_thm_style_tl - { \__ccnu_thm_redefine_style:n { break } } - { - \__ccnu_error:nx { unknown-theorem-style } - { \l__ccnu_thm_style_tl } - } - } - } - \tl_put_left:Nn \l__ccnu_thm_style_tl { nonumber } - \ccnu_thm_new_no_number:Vxx \l__ccnu_thm_style_tl {#3} {#4} - } - { - \clist_clear:N \l__ccnu_tmpa_clist - \clist_concat:NNN \l__ccnu_tmpa_clist - \c__ccnu_thm_style_plain_clist \c__ccnu_thm_style_break_clist - \clist_if_in:NVF \l__ccnu_tmpa_clist \l__ccnu_thm_style_tl - { - \__ccnu_error:nx { unknown-theorem-style } - { \l__ccnu_thm_style_tl } - } - \ccnu_thm_new:VVxx \l__ccnu_thm_style_tl \l__ccnu_thm_counter_tl - {#3} {#4} - } - } -\cs_new:Npn \__ccnu_thm_redefine_style:n #1 - { - \__ccnu_warning:nxx { redefine-theorem-style } - {#1} { \l__ccnu_thm_style_tl } - \tl_set:Nn \l__ccnu_thm_style_tl {#1} - } -\__ccnu_msg_new:nn { redefine-theorem-style } - { Theorem~ style~ "#2"~ will~ be~ redefined~ as~ "#1". } -\__ccnu_msg_new:nn { unknown-theorem-style } - { Theorem~ style~ "#1"~ is~ unknown. } -\cs_new:Npn \ccnu_thm_new:nnnn #1#2#3#4 - { - \__ccnu_thm_ntheorem_style:n {#1} - \__ccnu_thm_ntheorem_new:w {#3} {#4} [#2] - } -\cs_generate_variant:Nn \ccnu_thm_new:nnnn { VVxx } -\cs_new:Npn \ccnu_thm_new_no_number:nnn #1#2#3 - { - \__ccnu_thm_ntheorem_style:n {#1} - \__ccnu_thm_ntheorem_new:w {#2} {#3} - } -\cs_generate_variant:Nn \ccnu_thm_new_no_number:nnn { Vxx } -\cs_new:Npn \ccnu_thm_set_qed:n #1 { \theoremsymbol {#1} } -\cs_new:Npn \ccnu_thm_set_header_font:n #1 { \theoremheaderfont {#1} } -\cs_new:Npn \ccnu_thm_set_body_font:n #1 { \theorembodyfont {#1} } -\cs_generate_variant:Nn \ccnu_thm_set_qed:n { V } -\cs_generate_variant:Nn \ccnu_thm_set_header_font:n { V } -\cs_generate_variant:Nn \ccnu_thm_set_body_font:n { V } +% \clist_const:Nn \c__ccnu_thm_style_plain_clist +% { plain, margin, change } +% \clist_const:Nn \c__ccnu_thm_style_break_clist +% { break, marginbreak, changebreak } +% \tl_new:N \l__ccnu_thm_style_tl +% \tl_new:N \l__ccnu_thm_header_font_tl +% \tl_new:N \l__ccnu_thm_body_font_tl +% \tl_new:N \l__ccnu_thm_qed_tl +% \tl_new:N \l__ccnu_thm_counter_tl +% \keys_define:nn { ccnu / theorem } +% { +% style .tl_set:N = \l__ccnu_thm_style_tl, +% header-font .tl_set:N = \l__ccnu_thm_header_font_tl, +% body-font .tl_set:N = \l__ccnu_thm_body_font_tl, +% qed .tl_set:N = \l__ccnu_thm_qed_tl, +% counter .tl_set:N = \l__ccnu_thm_counter_tl +% } +% \cs_new_eq:NN \__ccnu_thm_ntheorem_style:n \theoremstyle +% \cs_new_eq:NN \__ccnu_thm_ntheorem_new:w \newtheorem +% \RenewDocumentCommand \newtheorem { s o m m } +% { +% \IfBooleanTF {#1} +% { \tl_set:Nn \l__ccnu_thm_qed_tl { \ensuremath { \square } } } +% { \tl_set:Nn \l__ccnu_thm_qed_tl { } } +% \tl_set:Nn \l__ccnu_thm_style_tl { plain } +% \IfValueT {#2} { \keys_set:nn { ccnu / theorem } {#2} } +% \ccnu_thm_set_header_font:V \l__ccnu_thm_header_font_tl +% \ccnu_thm_set_body_font:V \l__ccnu_thm_body_font_tl +% \ccnu_thm_set_qed:V \l__ccnu_thm_qed_tl +% \IfBooleanTF {#1} +% { +% \clist_if_in:nVF { plain, break } \l__ccnu_thm_style_tl +% { +% \clist_if_in:NVTF +% \c__ccnu_thm_style_plain_clist \l__ccnu_thm_style_tl +% { \__ccnu_thm_redefine_style:n { plain } } +% { +% \clist_if_in:NVTF +% \c__ccnu_thm_style_break_clist \l__ccnu_thm_style_tl +% { \__ccnu_thm_redefine_style:n { break } } +% { +% \__ccnu_error:nx { unknown-theorem-style } +% { \l__ccnu_thm_style_tl } +% } +% } +% } +% \tl_put_left:Nn \l__ccnu_thm_style_tl { nonumber } +% \ccnu_thm_new_no_number:Vxx \l__ccnu_thm_style_tl {#3} {#4} +% } +% { +% \clist_clear:N \l__ccnu_tmpa_clist +% \clist_concat:NNN \l__ccnu_tmpa_clist +% \c__ccnu_thm_style_plain_clist \c__ccnu_thm_style_break_clist +% \clist_if_in:NVF \l__ccnu_tmpa_clist \l__ccnu_thm_style_tl +% { +% \__ccnu_error:nx { unknown-theorem-style } +% { \l__ccnu_thm_style_tl } +% } +% \ccnu_thm_new:VVxx \l__ccnu_thm_style_tl \l__ccnu_thm_counter_tl +% {#3} {#4} +% } +% } +% \cs_new:Npn \__ccnu_thm_redefine_style:n #1 +% { +% \__ccnu_warning:nxx { redefine-theorem-style } +% {#1} { \l__ccnu_thm_style_tl } +% \tl_set:Nn \l__ccnu_thm_style_tl {#1} +% } +% \__ccnu_msg_new:nn { redefine-theorem-style } +% { Theorem~ style~ "#2"~ will~ be~ redefined~ as~ "#1". } +% \__ccnu_msg_new:nn { unknown-theorem-style } +% { Theorem~ style~ "#1"~ is~ unknown. } +% \cs_new:Npn \ccnu_thm_new:nnnn #1#2#3#4 +% { +% \__ccnu_thm_ntheorem_style:n {#1} +% \__ccnu_thm_ntheorem_new:w {#3} {#4} [#2] +% } +% \cs_generate_variant:Nn \ccnu_thm_new:nnnn { VVxx } +% \cs_new:Npn \ccnu_thm_new_no_number:nnn #1#2#3 +% { +% \__ccnu_thm_ntheorem_style:n {#1} +% \__ccnu_thm_ntheorem_new:w {#2} {#3} +% } +% \cs_generate_variant:Nn \ccnu_thm_new_no_number:nnn { Vxx } +% \cs_new:Npn \ccnu_thm_set_qed:n #1 { \theoremsymbol {#1} } +% \cs_new:Npn \ccnu_thm_set_header_font:n #1 { \theoremheaderfont {#1} } +% \cs_new:Npn \ccnu_thm_set_body_font:n #1 { \theorembodyfont {#1} } +% \cs_generate_variant:Nn \ccnu_thm_set_qed:n { V } +% \cs_generate_variant:Nn \ccnu_thm_set_header_font:n { V } +% \cs_generate_variant:Nn \ccnu_thm_set_body_font:n { V } \captionsetup [ figure ] { font = small, @@ -2098,20 +2100,70 @@ info / secret-level = none, info / school-id = { 10246 }, info / date = { \zhtoday }, - theorem / header-font = { \sffamily }, - theorem / body-font = { \ccnu@kai }, - theorem / counter = { chapter } + % theorem / header-font = { \sffamily }, + % theorem / body-font = { \ccnu@kai }, + % theorem / counter = { chapter } } \NewDocumentCommand \ccnusetup { m } { \keys_set:nn { ccnu } {#1} } -\newtheorem* { proof } { \c__ccnu_name_proof_tl } -\newtheorem { axiom } { \c__ccnu_name_axiom_tl } -\newtheorem { corollary } { \c__ccnu_name_corollary_tl } -\newtheorem { definition } { \c__ccnu_name_definition_tl } -\newtheorem { example } { \c__ccnu_name_example_tl } -\newtheorem { lemma } { \c__ccnu_name_lemma_tl } -\newtheorem { theorem } { \c__ccnu_name_theorem_tl } +% \newtheorem* { proof } { \c__ccnu_name_proof_tl } +% \newtheorem { axiom } { \c__ccnu_name_axiom_tl } +% \newtheorem { corollary } { \c__ccnu_name_corollary_tl } +% \newtheorem { definition } { \c__ccnu_name_definition_tl } +% \newtheorem { example } { \c__ccnu_name_example_tl } +% \newtheorem { lemma } { \c__ccnu_name_lemma_tl } +% \newtheorem { theorem } { \c__ccnu_name_theorem_tl } +\cs_new:Npn \__xdyymath_declare_theorem_with_counter_within:n #1 + { + \declaretheorem + [ + name = \clist_item:nn {#1} {1} , + refname = \clist_item:nn {#1} {2} , + within = \clist_item:nn {#1} {3} , + ] + { \clist_item:nn {#1} {4} } + } +\cs_new:Npn \__xdyymath_declare_theorem_with_counter_sibling:n #1 + { + \declaretheorem + [ + name = \clist_item:nn {#1} {1} , + refname = \clist_item:nn {#1} {2} , + sibling = \clist_item:nn {#1} {3} , + ] + { \clist_item:nn {#1} {4} } + } +\cs_new:Npn \__xdyymath_declare_theorem_without_counter:n #1 + { + \declaretheorem + [ + name = \clist_item:nn {#1} {1} , + refname = \clist_item:nn {#1} {2}, + numbered = no, + % headpunct = {}, + style = withoutcounterstyle + ] + { \clist_item:nn {#1} {3} } + } +\clist_map_function:nN + { + { 定理, 定理, chapter, theorem }, + { 例, 例, chapter, example }, + { 问题, 问题, chapter, question }, + }\__xdyymath_declare_theorem_with_counter_within:n + +\clist_map_function:nN + { + { 定义, 定义, theorem, definition }, + { 性质, 性质, theorem, property }, + { 命题, 命题, theorem, proposition }, + { 推论, 推论, theorem, corollary }, + { 引理, 引理, theorem, lemma }, + { 公理, 公理, theorem, axiom }, + { 反例, 反例, theorem, antiexample }, + { 猜想, 猜想, theorem, conjecture }, + }\__xdyymath_declare_theorem_with_counter_sibling:n % 去掉目录的页码 % https://tex.stackexchange.com/questions/38847/clear-tableofcontents-page-in-book-or-report @@ -2222,4 +2274,5 @@ % 可以是单个文件,也可以是用英文逗号 “,” 隔开的一组文件 % 如果使用 biblatex,则必须明确给出 .bib 后缀名 } - } \ No newline at end of file + } + \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7594b16..5ca401c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # 更新日志 +## [v1.0.3] - 2022-02-19 +### Fixed +- 修复`msg`报错 + +### Changed +- 重新修改定理类环境 + ## [v1.0.2] - 2022-02-01 ### Changed - 修改`choices`宏包为`xchoices`宏包 diff --git a/back/Appendix.tex b/back/Appendix.tex index 7859ba8..094b15e 100644 --- a/back/Appendix.tex +++ b/back/Appendix.tex @@ -3,7 +3,7 @@ \chapter*{附录} 此处可以写调查问卷,访谈记录等 -用\verb|xchoices{}|环境可以排版任意个选项,用\verb|\item|分隔即可(现将代码注释掉,如有需要取消注释即可,如果不需要,可自行删除或不管(因为不影响编译效果) +用\verb|xchoices|环境可以排版任意个选项,用\verb|\item|分隔即可(现将代码注释掉,如有需要取消注释即可,如果不需要,可自行删除或不管(因为不影响编译效果) % \begin{xchoices} % \item 选项1 diff --git a/body/chapter1.tex b/body/chapter1.tex index 46a008c..0b5b22a 100644 --- a/body/chapter1.tex +++ b/body/chapter1.tex @@ -20,5 +20,5 @@ \section{研究背景} \subsection{前人工作} -测试 \parencite{邱泽奇建构与分化} +测试 \parencite{邱泽奇建构与分化} %带方括号的引用 \cite 为无格式的引用 \section{研究背景} diff --git a/body/chapter3.tex b/body/chapter3.tex index 7976b24..0c5b173 100644 --- a/body/chapter3.tex +++ b/body/chapter3.tex @@ -5,33 +5,51 @@ \section{已定义好的一些定理环境} \begin{definition} - 我是定义 + 这是一段文字 $E = m c^2$ \end{definition} \begin{theorem} - 我是定理 + 这是一段文字 $E = m c^2$ \end{theorem} -\begin{proof} - 我是证明 -\end{proof} +\begin{example} + 这是一段文字 $E = m c^2$ +\end{example} + +\begin{property} + 这是一段文字 $E = m c^2$ +\end{property} + +\begin{proposition} + 这是一段文字 $E = m c^2$ +\end{proposition} \begin{corollary} - 我是推论 + 这是一段文字 $E = m c^2$ \end{corollary} +\begin{lemma} + 这是一段文字 $E = m c^2$ +\end{lemma} + \begin{axiom} - 我是公理 + 这是一段文字 $E = m c^2$ \end{axiom} +\begin{antiexample} + 这是一段文字 $E = m c^2$ +\end{antiexample} -\begin{example} - 我是例 -\end{example} - -\begin{lemma} - 我是引理 -\end{lemma} +\begin{conjecture} + 这是一段文字 $E = m c^2$ +\end{conjecture} +\begin{question} + 这是一段文字 $E = m c^2$ +\end{question} +析出文献,即从著作或公开发表的书籍文章中分析出来所获得的文献资料。 +连续出版物指印刷或非印刷形式的出版物,具有统一的题名,定期或不定期以连续分册形式出版,有卷期或年月标识,并且计划无限期地连续出版。连续出版物包括:期刊、报纸、年度出版物(年鉴、指南等)以及成系列的报告、学会会刊、会议录和专著丛书等。 +%%下面的文献引用用来测试前五个文献类别 +\parencite{李晓东,Ahn,丁文祥,张启发,雷光春,邱泽奇,zhang,唐绪军,昂温,Foth,杨国枢,Morison,张志祥,Aldemita,张凯军,Kosek,文献编写,国防白皮,federal,health,江向东,萧钮,PACS-L} diff --git a/gb7714-2015.bbx b/gb7714-2015.bbx new file mode 100644 index 0000000..052a75b --- /dev/null +++ b/gb7714-2015.bbx @@ -0,0 +1,4121 @@ +%% +%% --------------------------------------------------------------- +%% biblatex-gb7714-2015 --- A biblatex implementation of the +%% GBT7714-2015 bibliography style,numerical sequence +%% Maintained by huzhenzhen +%% E-mail: hzzmail@163.com +%% Released under the LaTeX Project Public License v1.3c or later +%% --------------------------------------------------------------- +%% + +% +% 版本和时间信息 +% +\def\versionofgbtstyle{2021/12/11 v1.1b} +\def\versionofbiblatex{\abx@version} +\ProvidesFile{gb7714-2015.bbx}[\versionofgbtstyle biblatex bibliography style] +%\RequireBiber[3]%显式指定用biber后端,当用bibtex时会报错,但其实不会影响编译,只是采用bibtex后无法达成格式需求 + +%===================================================================== +% 加载标准样式 +%===================================================================== +\RequireBibliographyStyle{numeric-comp} +\RequirePackage{xstring}%解决texlive2015的biblatex3.0不加载xstring包的问题 + + +%===================================================================== +% 功能函数 +%===================================================================== + % + % biblatex版本判断 + % 20180405,v1.0k,为兼容biblatexv3.11增加toggle:iftlnine,HU zhenzhen + % 20181020,v1.0n,为不再使用xstring宏包做的修改,hzz + % + % 原理方法:当版本继续更新时,增加一个新的toggle用以处理新的旧版,最新版和未判断出来的版本永远用iftlatest + \providetoggle{iftlfive}\togglefalse{iftlfive} %处理biblatex3.2之前版本,时间2016-03-01前 + \providetoggle{iftlsix}\togglefalse{iftlsix} %处理biblatex3.3开始改变姓名机制后版本,时间2016-03-01及以后 + \providetoggle{iftlseven}\togglefalse{iftlseven}%处理biblatex3.7的兼容性,时间2016-12-01后 + \providetoggle{iftleight}\togglefalse{iftleight}%处理biblatex3.8到3.9的兼容性,时间2017-11-01后到2017-12-01前 + \providetoggle{iftlnine}\togglefalse{iftlnine} %处理biblatex10的兼容性,时间2017-12-01后 + \providetoggle{iftlatest}\toggletrue{iftlatest} %假设是最新版biblatex + + \@ifpackagelater{biblatex}{2014/04/01}{ + \@ifpackagelater{biblatex}{2016/03/01}{ + \@ifpackagelater{biblatex}{2016/12/01}{ + \@ifpackagelater{biblatex}{2017/11/01}{ + \@ifpackagelater{biblatex}{2017/12/01}{ + \@ifpackagelater{biblatex}{2018/02/19}{} + {\toggletrue{iftlnine}\togglefalse{iftlatest}}} + {\toggletrue{iftleight}\togglefalse{iftlatest}}} + {\toggletrue{iftlseven}\togglefalse{iftlatest}}} + {\toggletrue{iftlsix}\togglefalse{iftlatest}}} + {\toggletrue{iftlfive}\togglefalse{iftlatest}}} + {\PackageError{biblatex}{Outdated 'biblatex' package} + {Please update biblatex, This is a fatal error.}} + + \newcommand\defversion[2]{\csdef{codeversion#1#2}}%定义不同版本的命令 + \newcommand\switchversion[2]{\csuse{codeversion#1#2}}%使用不同版本的命令 + + % + % 判断CJK字符的函数,用于判断作者等信息是否由中文字符构成 + % v1.0k,20180509,hzz + % + % 原理方法:用biber中的perl方法代替。因为利用tex函数对字符判断时,当字符在宏 + % 中时,基于`的方法无法解决GBK编码的问题,基于CJKsymbol的方法无法解决utf-8 + % 编码用xelatex编译的问题。 + % + % 原理是:利用perl正则将中文标识记录到域中, + % 然后利用\iffieldundef和\iffieldequalstr进行判断 + \providetoggle{ifCJKforgbt} + \def\testCJKfirst#1{% + \iffieldundef{#1}{\togglefalse{ifCJKforgbt}}{% + \iffieldequalstr{#1}{chinese}{\toggletrue{ifCJKforgbt}}{\togglefalse{ifCJKforgbt}}}} + + % + % 2个卷的解析函数,用于连续出版物 + % + % 原理方法: 范围起止间隔符号还是用-,而不是与date相同的/,因为有合期期刊的问题,需要用到/符号 + \newcommand{\multivolparser}[1]{% + \IfSubStr{#1}{-}% + {\StrBefore{#1}{-}[\multivolfirst]\StrBehind{#1}{-}[\multivolsecond]}% + {\def\multivolfirst{#1}\def\multivolsecond{}}% + } + + + % + % 2个期的解析函数,用于连续出版物 + % + \newcommand{\multinumberparser}[1]{% + \IfSubStr{#1}{-}% + {\StrBefore{#1}{-}[\multinumberfirst]\StrBehind{#1}{-}[\multinumbersecond]}% + {\def\multinumberfirst{#1}\def\multinumbersecond{}}% + } + + % 对没有分隔符环境命令的低版本biblatex做增补,避免报错 + % + \iftoggle{iftlfive}{ + + \def\blx@inf@delimdeclare#1#2{% + \blx@info{Delimiter '#1' in context '#2' already defined, overwriting}} + + \def\blx@warn@delimuse#1#2{% + \blx@warning{Delimiter '#1' in context '#2' undefined}} + % Delimiter interface + + % []{}{} + \newrobustcmd*{\DeclareDelimFormat}{% + \@ifstar + {\blx@declaredelimclear} + {\blx@declaredelim}} + + \newrobustcmd*{\blx@declaredelimclear}[3][]{% + \ifcsvoid{blx@declaredelimcontexts@#2} + {} + {\def\do##1{\csundef{blx@printdelim@##1@#2}}% + \dolistcsloop{blx@declaredelimcontexts@#2}}% + \cslet{blx@declaredelimcontexts@#2}\@empty + \ifblank{#1} + {\blx@declaredelim{#2}{#3}} + {\blx@declaredelim[#1]{#2}{#3}}} + + \newrobustcmd*{\blx@declaredelim}[3][]{% + \ifblank{#1} + {\blx@declaredelim@i{}{}{#2}{#3}} + {\def\do##1{% + \listcsadd{blx@declaredelimcontexts@#2}{##1}% + \blx@declaredelim@i{blx@printdelim@##1@}{##1}{#2}{#3}}% + \docsvlist{#1}}}% + + \def\blx@declaredelim@i#1#2#3#4{% + \def\do@i##1{% + \ifcsdef{#1##1} + {\blx@inf@delimdeclare{##1}{#2}} + {}% + \csdef{#1##1}{#4}}% + \forcsvlist{\do@i}{#3}} + + % *[]{}{} + \newrobustcmd*{\DeclareDelimAlias}{% + \@ifstar + {\blx@declaredelimalias} + {\blx@declaredelimaliasauto}} + + \newrobustcmd*{\blx@declaredelimalias}[3][]{% + \ifblank{#1} + {\blx@declaredelimalias@i{}{#2}{#3}} + {\def\do##1{% + \blx@declaredelimalias@i{blx@printdelim@##1@}{#2}{#3}}% + \docsvlist{#1}}} + + \newrobustcmd*{\blx@declaredelimaliasauto}[2]{% + \blx@declaredelimalias@i{}{#1}{#2}% + \ifcsvoid{blx@declaredelimcontexts@#2} + {} + {\def\do##1{% + \blx@declaredelimalias@i{blx@printdelim@##1@}{#1}{#2}}% + \dolistcsloop{blx@declaredelimcontexts@#2}}} + + \def\blx@declaredelimalias@i#1#2#3{% + \ifcsdef{#1#2} + {\blx@inf@delimdeclare{#2}{#1}} + {}% + \csdef{#1#2}{\csuse{#1#3}}} + + \def\blx@delimcontext{none} + \newcommand*{\printdelim}[2][]{% + \ifblank{#1} + {\ifcsdef{blx@printdelim@\blx@delimcontext @#2} + {\csuse{blx@printdelim@\blx@delimcontext @#2}} + {\ifcsdef{#2}% fall back on legacy macros + {\csuse{#2}} + {\blx@warn@delimuse{#2}{*}}}} + {\ifcsdef{blx@printdelim@#1@#2} + {\csuse{blx@printdelim@#1@#2}} + {\blx@warn@delimuse{#2}{#1}}}} + + \newcommand*{\delimcontext}[1]{% + \edef\blx@delimcontext{\blx@delimcontextalias{#1}}} + + \def\blx@delimcontextalias#1{% + \ifcsdef{blx@delimcontextalias@#1} + {\csuse{blx@delimcontextalias@#1}} + {#1}} + + \newcommand*{\DeclareDelimcontextAlias}[2]{% + \csgdef{blx@delimcontextalias@#1}{#2}} + }{} + + +%===================================================================== +% 数据模型定义 +%===================================================================== + %定义类型和载体标识,从gb内容看载体基本属于介质。 + %为与lee zeping的bst的样式统一,使用mark和medium这两域名 + %为单个条目的姓名格式控制增加nameformat和namefmtid两个域 + %为缩略信息文献表增加了shortbooktitle域 + %为多语言排序增加了lansortorder域 + %因为language域会被clearlang选项清除,增加languageid域,类型设为field而不是list + \DeclareDatamodelFields[type=field,datatype=literal]{mark,medium,nameformat} + \DeclareDatamodelFields[type=field,datatype=integer]{namefmtid} + \DeclareDatamodelFields[type=field,datatype=literal]{shortbooktitle} + \DeclareDatamodelFields[type=field,datatype=literal]{lansortorder} + \DeclareDatamodelFields[type=field,datatype=literal]{languageid} + + %因为biblatex更新3.14版本以后,biber对于为声明数据模型的条目类型 + %不再默认读取,而是以空字符串作为条目类型名,自然在条目定义alias时 + %就会出现问题,因此显式的声明一下newspaper,然后保留后面采用alias的方式 + %而standard类型则是采用另一种方式直接在sourcemap中转换为其它类型。 + \@ifpackagelater{biblatex}{2019/11/30}{%2019/12/01 v3.14 + \DeclareDatamodelEntrytypes{newspaper}% + }{} + + + +%===================================================================== +% 设置宏包选项 +%===================================================================== + % + % 增加一个控制是否调整日期输出位置的选项mergedate + % 为兼容性考虑,但实际不产生作用了,因为如果要使用ay样式可以直接从bibstyle进入 + % 因为使用string所以只适用于biblatex3.3以上版本 + % 20210415,v1.0y,hzz + \DeclareBibliographyOption[string]{mergedate}[none]{% + \ifcsdef{bbx@opt@mergedate@#1} + {\csuse{bbx@opt@mergedate@#1}} + {}} + \ExecuteBibliographyOptions{mergedate} + + \def\bbx@opt@mergedate@none{}%none就是正常的顺序编码样式 + \def\bbx@opt@mergedate@true{}%none就是正常的顺序编码样式 + \def\bbx@opt@mergedate@false{}%none就是正常的顺序编码样式 + + + % + % 增加一个控制是否输出恢复传统crossref作用的选项 + % 20210216,v1.0w,hzz + \newtoggle{bbx:citexref} + \DeclareBibliographyOption{citexref}[true]{% + \settoggle{bbx:citexref}{#1}} + \ExecuteBibliographyOptions{citexref} + + \newbibmacro*{citexref}{% + \printtext[bibhyperref]{% + \printfield{labelprefix}% + \printfield{labelnumber}% + \ifbool{bbx:subentry} + {\printfield{entrysetcount}} + {}}} + + \DeclareCiteCommand{\bbx@xrefcite}[\mkbibbrackets]% + {\boolfalse{citetracker}% + \boolfalse{pagetracker}% + \boolfalse{backtracker}} + {\usebibmacro{citexref}} + {} + {} + + \newbibmacro*{crosscite}[1]{% + \iftoggle{bbx:citexref} + {\iffieldundef{crossref} + {\iffieldundef{xref} + {\usebibmacro{#1}} + {\printtext{\bbx@xrefcite{\thefield{xref}}}}} + {\printtext{\bbx@xrefcite{\thefield{crossref}}}}} + {\usebibmacro{#1}}} + + % + % 增加一个控制是否输出文献载体的选项 + % 20191125,v1,0s,hzz + \newtoggle{bbx:gbmedium} + \DeclareBibliographyOption{gbmedium}[true]{%biblatex低版本 + \settoggle{bbx:gbmedium}{#1}} + \ExecuteBibliographyOptions{gbmedium} + + % + % 增加一个控制是否输出annotation域的选项,该域可以用于在文献条目后面输出一些注释信息 + % 20190509,v1,0s,hzz + \newtoggle{bbx:gbannote} + \DeclareBibliographyOption{gbannote}[false]{%biblatex低版本 + \settoggle{bbx:gbannote}{#1}} + \ExecuteBibliographyOptions{gbannote} + % + %用于在文献条目后面输出注释信息的宏 + %FieldFormat{annotation}用于设置注释信息的格式 + \DeclareFieldFormat{annotation}{% + \printtext{\addspace(#1)}% + } + \renewbibmacro*{annotation}{% + \iftoggle{bbx:gbannote}% + {\iffieldundef{annotation}% + {\printfile[annotation]{\bibannotationprefix\thefield{entrykey}.tex}}% + {\printfield{annotation}}}% + {}% + } + + % + % 增加一个控制是否输出type域的选项 + % 20190212,v1,0q,hzz + \newtoggle{bbx:gbfieldtype} + \DeclareBibliographyOption{gbfieldtype}[false]{%biblatex低版本 + \settoggle{bbx:gbfieldtype}{#1}} + \ExecuteBibliographyOptions{gbfieldtype} + + % + % 增加一个控制是否根据页码重设脚注数字标号的选项 + % 20190422,v1,0r,hzz + \newtoggle{bbx:gbfnperpage} + \DeclareBibliographyOption{gbfnperpage}[false]{% + \settoggle{bbx:gbfnperpage}{#1}} + \ExecuteBibliographyOptions{gbfnperpage} + + + % + % 增加一个选项,用于控制是否实现GB/T 7714-2015标准的脚注文献表 + % 20190203,v1.0p,hzz + % 原理方法:默认做patch,文献引用带圈上标数字表示,脚注中的文献用带圈非上标数字做标签 + % 当前面的脚注中已经存在当前文献,那么当前文献内容不再输出而用同(4)这样的方式 + % 需要注意的是由于小页环境和表格中的脚注本身的问题,可能会有一些问题 + \DeclareBibliographyOption{gbfootbib}[false]{% + \ifstrequal{#1}{false}{}{\execgbfootbib}} + \ExecuteBibliographyOptions{gbfootbib} + + %% + \newlength{\footbibmargin} + \newlength{\footbiblabelsep} + \setlength{\footbibmargin}{1em}%脚注的段落左侧缩进距离 + \setlength{\footbiblabelsep}{0.5em}%脚注中标记号与脚注段落的间距 + \def\execgbfootbib% + {% + %开启引用跟踪计数器,为使用\ifciteseen等测试命令 + \ExecuteBibliographyOptions{citetracker=true} + % + %利用footmisc宏包来实现脚注文献的悬挂对齐 + \AtEndPreamble{ + \@ifclassloaded{beamer}{}{ + %beamer类因为其特殊性,为避免冲突不调footmisc。 + %同时footmisc与hyperref宏包也不兼容,所以使用footmisc时会破坏脚注的超链接 + %如果要实现超链接可以将下句注释掉,这里留着主要是实现悬挂对齐。 + %\PassOptionsToPackage{perpage,hang}{footmisc}% + %\RequirePackage{footmisc}% + + %重新实现脚注的根据单页重设脚注号码 + %重新实现脚注的悬挂对齐问题,不再使用footmisc,直接从latex核心代码和hyperref代码进行修改 + %v1.0q 20190317 hzz + %v1.0r 20190422 hzz 根据gbfnperpage选项设置 + \iftoggle{bbx:gbfnperpage}% + {\@addtoreset{footnote}{page}}{}%重设计数器 + +\@ifpackageloaded{hyperref}{%加载hyperref则对\H@@footnotetext做重定义 + \long\def\H@@footnotetext##1{\insert\footins{% + \reset@font\footnotesize + \interlinepenalty\interfootnotelinepenalty + \splittopskip\footnotesep + \splitmaxdepth \dp\strutbox \floatingpenalty \@MM + \hsize\columnwidth \@parboxrestore + \protected@edef\@currentlabel{% + \csname p@footnote\endcsname\@thefnmark + }% + \color@begingroup + \leftskip \footbibmargin%增加的左侧缩进 + \@makefntext{% + \rule\z@\footnotesep\ignorespaces##1\@finalstrut\strutbox% + }% + \color@endgroup}}% + + \long\def\H@@mpfootnotetext##1{% + \global\setbox\@mpfootins\vbox{% + \unvbox\@mpfootins + \reset@font\footnotesize + \hsize\columnwidth + \@parboxrestore + \protected@edef\@currentlabel + {\csname p@mpfootnote\endcsname\@thefnmark}% + \leftskip \footbibmargin%增加的左侧缩进 + \color@begingroup + \@makefntext{% + \rule\z@\footnotesep\ignorespaces##1\@finalstrut\strutbox}% + \color@endgroup}} + }{%否则对latex核心代码中的\@footnotetext做重定义 + \long\def\@footnotetext##1{\insert\footins{% + \reset@font\footnotesize + \interlinepenalty\interfootnotelinepenalty + \splittopskip\footnotesep + \splitmaxdepth \dp\strutbox \floatingpenalty \@MM + \hsize\columnwidth \@parboxrestore + \protected@edef\@currentlabel{% + \csname p@footnote\endcsname\@thefnmark + }% + \color@begingroup + \leftskip \footbibmargin%增加的左侧缩进 + \@makefntext{% + \rule\z@\footnotesep\ignorespaces##1\@finalstrut\strutbox% + }% + \color@endgroup}}% + + \long\def\@mpfootnotetext##1{% + \global\setbox\@mpfootins\vbox{% + \unvbox\@mpfootins + \reset@font\footnotesize + \hsize\columnwidth + \@parboxrestore + \protected@edef\@currentlabel + {\csname p@mpfootnote\endcsname\@thefnmark}% + \leftskip \footbibmargin%增加的左侧缩进 + \color@begingroup + \@makefntext{% + \rule\z@\footnotesep\ignorespaces##1\@finalstrut\strutbox}% + \color@endgroup}} + } + + \long\def\@makefntext##1{%增加了脚注标记与正文的间隔 + \parindent 1em\noindent \hb@xt@ 0em{\hss \@makefnmark\makebox[\footbiblabelsep]{}}##1} + + } + + % + %使脚注标记加圈并设置数字的字体为tiny,不使用修改thefootnote的方式 + \def\@makefnmark{\hbox{\@textsuperscript{\textcircled{\tiny\@thefnmark}}}} + %做patch使得脚注内容中的脚注数字标签不上标 + \pretocmd{\@makefntext}{% + \def\@makefnmark{% + \hbox{\textcircled{\tiny\@thefnmark}}% + }% + }{}{} + } + + % + %判断当前文献是否已经引用过且是做的footfullcite(即已经作为脚注输出文献内容) + %记录首次输出时的脚注号码,用于后面再次引用该文献时的输出,比如同(4)。 + %v1.0q 20190309 区分使脚注标注适应minipage中的情况 + \newbibmacro*{citesavefn}{% + \ifciteseen%当被引用过为true + {\ifcsdef{sec\arabic{refsection}\arabic{page}et\thefield{entrykey}}%当已经定义过脚注序号信息 + {\csgdef{labelsec\arabic{refsection}\arabic{page}et\thefield{entrykey}}{% + \str@sameentry\gdef\@thefnmark{\csuse{sec\arabic{refsection}\arabic{page}et\thefield{entrykey}}}% + \@makefnmark% + }}% + {\csxdef{sec\arabic{refsection}\arabic{page}et\thefield{entrykey}}{% + \ifcsstring{@mpfn}{mpfootnote}{\@alph\c@mpfootnote}{\thefootnote}% + }}% + }% + {\csxdef{sec\arabic{refsection}\arabic{page}et\thefield{entrykey}}{% + \ifcsstring{@mpfn}{mpfootnote}{\@alph\c@mpfootnote}{\thefootnote}% + %判断在minipage中比较麻烦,这里使用\@mpfn的定义进行判断 + }}% + } + + % + %重定义\footfullcite使完成gb7714-2015的脚注文献要求 + \DeclareCiteCommand{\footfullcite}[\mkbibfootnote]% + {\defcounter{maxnames}{\blx@maxbibnames}%局部定义maxnames和minnames计数器 + \defcounter{minnames}{\blx@minbibnames}%使footfullcite内的作者输出与正文文献表中的一致。 + \usebibmacro{prenote}% + \renewbibmacro*{postnote}{% + \iffieldundef{postnote}% + {}{\setunit{\addcolon\addspace}\printfield{postnote}}}%与ay样式不同,由于已修改postnote域格式,直接用printfield + }% + {\usebibmacro{citesavefn}% + \ifcsdef{labelsec\arabic{refsection}\arabic{page}et\thefield{entrykey}}% + {\csuse{labelsec\arabic{refsection}\arabic{page}et\thefield{entrykey}}}%\nopunct + {\usedriver{\DeclareNameAlias{sortname}{default}}{\thefield{entrytype}}}% + }% + {\multicitedelim}% + {\usebibmacro{postnote}} + + } + + % + % 增加一个选项,用于控制gb7714的使用范围,即英文文献和中文文献使用不同的样式 + % 20180814,v1.0m,hzz + % 原理方法: + % 只为兼容性考虑不做任何处理 + \DeclareBibliographyOption{gbstyle}[true]{%biblatex低版本 + } + + % + % 增加一个控制是否输出文献类型和载体标识的选项 + % + % 原理方法: + % 对于biblatex3.4以上版本DeclareBibliographyOption命令中的[datatype]如果是boolean,那么是可以省略的 + % 所以用老版本的不用[datatype]的命令可以兼容所有biblatex版本 + \newtoggle{bbx:gbtype} + %\DeclareBibliographyOption[boolean]{gbtype}[true]{%biblatex高版本 + \DeclareBibliographyOption{gbtype}[true]{%biblatex低版本 + \settoggle{bbx:gbtype}{#1}} + \ExecuteBibliographyOptions{gbtype} + + % + % 增加一个源文件编码选择选项,当true时可以使用GBK编码。 + % v1.0k, 2018.05.08, by hzz + % + % 原理方法:将需要输出的中文字符串用命令形式表示存储,采用utf8编码时采用bbx文档 + % 内的定义即是utf8编码的中文字符串,但tex源文件是gbk编码时,利用gb7714-2015-gbk.def + % 文档内的gbk编码的字符串覆盖。这种覆盖只能在宏包末尾加载时成功实现,所以使用 + % AtEndOfPackage。该解决思路源自biblatex-caspervector宏包。 + % 另外注意: + % gbk编码的tex文档,利用pdflatex/latex能正确编译,利用xelatex能编译,但中文显示乱码 + % 在源文档前面增加 XeTeX 原语:\XeTeXinputencoding "GBK" 后,显示正常 + % utf-8编码的tex文档,利用xelatex能正确编译,而pdflatex/latex不能编译。 + \newtoggle{bbx:codegbk} + \DeclareBibliographyOption{gbcodegbk}[false]{% + \settoggle{bbx:codegbk}{#1}} + \ExecuteBibliographyOptions{gbcodegbk} + + \def\str@bibliography{参考文献} + \def\str@references{参考文献} + \def\str@bytranslator{译} + \def\str@andotherscn{等} + \def\str@andcn{和} + \def\str@backrefpage{引用页} + \def\str@backrefpages{引用页} + \def\str@noaddress{出版地不详} + \def\str@nopublisher{出版者不详} + \def\str@edition{版} + \def\str@volumecn{卷} + \def\str@numbercn{册} + \def\str@serialcn{第} + \def\str@sameentry{同} + \def\str@incn{见} + \def\str@mathesiscn{硕士学位论文} + \def\str@phdthesiscn{博士学位论文} + \def\str@editorcn{主编} + + \AtEndOfPackage{% + \iftoggle{bbx:codegbk}{% + \ExecuteBibliographyOptions{texencoding = GBK} + \input{gb7714-2015-gbk.def} + }{}} + + % + % 增加一个严格按GB/T 7714-2015给出著录格式控制域的输出的选项 + % v1.0k, 2018.05.08, by hzz + % + % 原理方法: + % 默认设置该选项为真,进而不输出GB/T 7714-2015中没有的域的信息 + % 这样可以避免因为bib文件带有多余的域的信息的输出,比如因为bibtex样式 + % 可能需要用于中英文判断的language域的信息。 + \newtoggle{bbx:gbstrict} + \DeclareBibliographyOption{gbstrict}[true]{% + \settoggle{bbx:gbstrict}{#1}} + \ExecuteBibliographyOptions{gbstrict} + + % + % 增加一个控制标题域超链接设置的选项 + % v1.0k, 2018.05.24, by hzz + % + % 原理方法: + % 利用标题域格式来实现,默认设置该选项为false,不做超链接。 + % 设置为true,则标题设置超链接 + \newtoggle{bbx:titlelink} + \DeclareBibliographyOption{gbtitlelink}[false]{% + \settoggle{bbx:titlelink}{#1}} + \ExecuteBibliographyOptions{gbtitlelink} + + % + % 增加一个控制参考文献标题是否能够被ctex宏包设置的选项 + % v1.0l, 2018.07.02, by hzz + % + % 原理方法: + % 重定义biblatex的宏,去除使用本地化字符串的方式,是的可以利用ctexset进行设置 + \newtoggle{bbx:ctexset} + \DeclareBibliographyOption{gbctexset}[true]{% + \settoggle{bbx:ctexset}{#1}} + \ExecuteBibliographyOptions{gbctexset} + + \AtEndOfPackage{% + \iftoggle{bbx:ctexset}{% + \def\blx@defbibstrings#1#2{% + \def\do##1{\csundef{abx@lstr@##1}\csundef{abx@sstr@##1}}% + \abx@dostrings + \csuse{abx@strings@#1}% + \setkeys{blx@lbx}{#2}% + \let\do\blx@defbibstrings@i + \csxdef{abx@strings@#1}{\abx@dostrings}% + } + }{}} + + % + % 增加一个处理佚名或noauthor的控制选项 + % + % 原理方法:在顺序编码制中不需要使用,为与作者年制的兼容性考虑,这里也增加避免报错 + \DeclareBibliographyOption{gbnoauthor}[true]{}% + + + % + % 增加一个恢复域格式为标准样式的控制选项 + % v1.0k, 2018.05.15, by hzz + % + % 原理方法: + % 默认设置该选项为false,采用国标要求的域格式输出相关域 + % 当设置该选项为true时,则重新利用标准样式的域格式输出相关的域 + \newtoggle{bbx:gbfieldstd} + \DeclareBibliographyOption{gbfieldstd}[false]{% + \settoggle{bbx:gbfieldstd}{#1}% + \ifstrequal{#1}{false}{}{\execgbfdfmtstd}% + } + \ExecuteBibliographyOptions{gbfieldstd} + + % + % 增加一个出版项自动处理控制选项,当true时使用出版者不详等信息补充缺失的出版信息。 + % + \newtoggle{bbx:gbpub} + \DeclareBibliographyOption{gbpub}[true]{% + %\settoggle{bbx:gbpub}{#1} %或采用下面这一句 + \ifstrequal{#1}{false}{\togglefalse{bbx:gbpub}}{\toggletrue{bbx:gbpub}}} + \ExecuteBibliographyOptions{gbpub} + + % + % 增加控制析出文献来源前的标点符号//输出的选项 + % v1.0k, 2018.04.20,added in by hzz + \newtoggle{bbx:gbpunctin} + \DeclareBibliographyOption{gbpunctin}[true]{% + \settoggle{bbx:gbpunctin}{#1}} + \ExecuteBibliographyOptions{gbpunctin} + + + + + + % + % 选项设置 + % + \ExecuteBibliographyOptions{ + sorting=none, + useprefix=true, %名字的信息包括前缀 + date = year, %日期仅写到年 + maxbibnames = 3,%设置名字最大数量 + minbibnames = 3, %设置缩减后的名字最小数量 + maxitems = 1,%设置列表最大数量 + minitems = 1, %设置缩减后的列表最小数量 + isbn=false, + } + + % + %为日期相关选项增加选项值gb7714-2015 + % + \csdef{mkdaterangegb7714-2015}#1{% + \begingroup + \blx@metadateinfo{#1}% + \iffieldundef{#1year} + {} + {\printtext[#1date]{% + \blx@gbdate{#1}{}}}% + \endgroup} + + \newrobustcmd*{\blx@gbdate}[3][]{% + \dateeraprintpre{#2#3year}% + \blx@imc@forcezerosy{\thefield{#2#3year}}\ifblank{#1}{}{\printfield{#1}}% + \iffieldundef{#2#3month}{}{\hyphen\blx@imc@forcezerosmdt{\thefield{#2#3month}}}% + \iffieldundef{#2#3day}{}{\hyphen\blx@imc@forcezerosmdt{\thefield{#2#3day}}}} + + + %为姓名格式选择增加的计数器 + \newcounter{gbnamefmtcase} + \def\thegbnamefmtcase{\the\c@gbnamefmtcase} + %为数字标签格式选择增加的计数器/命令 + \newcommand{\mkgbnumlabel}[1]{\mkbibbrackets{#1}} + \def\gbbiblabelopt@bracket{\renewcommand{\mkgbnumlabel}[1]{\mkbibbrackets{##1}}} + \def\gbbiblabelopt@parens{\renewcommand{\mkgbnumlabel}[1]{\mkbibparens{##1}}} + \def\gbbiblabelopt@dot{\renewcommand{\mkgbnumlabel}[1]{##1\adddot}} + \def\gbbiblabelopt@plain{\renewcommand{\mkgbnumlabel}[1]{##1}} + \def\gbbiblabelopt@box{\renewcommand{\mkgbnumlabel}[1]{\framebox{##1}}} + \def\gbbiblabelopt@circle{\renewcommand{\mkgbnumlabel}[1]{\textcircled{##1}}} + %为文献表中数字标签对齐方式选择增加的计数器/命令 + \newcounter{gbalignlabel} + \def\thegbalignlabel{\the\c@gbalignlabel} + %为引用标签标注/文献表中本地化字符串中英文选择增加的计数器/命令 + \newcounter{gbcitelocalcase} + \newcounter{gbbiblocalcase} + \def\thegbcitelocalcase{\the\c@gbcitelocalcase} + \def\thegbbiblocalcase{\the\c@gbbiblocalcase} + +\@ifpackagelater{biblatex}{2016/03/27} + { % 针对biblatex>=3.3版本的选项设置 + % 增加不同语言排序的切换选项 + % numeric样式,不使用该选项,这里给出仅为兼容性考虑 + % v1.0q,20190307,hzz + % + % 增加不同语言排序的切换选项 + % gblanorder=chineseahead的顺序为cn,jp,kr,en,fr,ru + % gblanorder=englishahead的顺序为en,fr,ru,cn,jp,kr + % gblanorder=cn;en;ru;fr;jp;kr的顺序为指定的cn;en;ru;fr;jp;kr,自定义内容可以随意写以分号分隔 + % v1.0q,20190307,hzz + % + \DeclareBibliographyOption[string]{gblanorder}[chineseahead]{% + \ifstrequal{#1}{chineseahead}%%中文在前的顺序 + {\gdef\lancnorder{1}\gdef\lanjporder{2}\gdef\lankrorder{3}% + \gdef\lanenorder{4}\gdef\lanfrorder{5}\gdef\lanruorder{6}}% + {% + \ifstrequal{#1}{englishahead}% + {\execlanodeah\dealsortlan}% + {\execlanodudf{#1}\dealsortlan}% + }% + } + \ExecuteBibliographyOptions{gblanorder} + + \def\execlanodeah{%中文在后的顺序 + \gdef\lancnorder{4} + \gdef\lanjporder{5} + \gdef\lankrorder{6} + \gdef\lanenorder{1} + \gdef\lanfrorder{2} + \gdef\lanruorder{3}} + + \newcounter{lanordernum} + \newcommand{\execlanodudf}[1]{%like:cn;en;ru;fr;jp;kr + \setcounter{lanordernum}{0} + \DeclareListParser{\parsinglanorder}{;} + \renewcommand*{\do}[1]{\stepcounter{lanordernum}\csxdef{lan##1order}{\thelanordernum}} + \parsinglanorder{#1} + } + + % + % 增加本地化字符串的中英文切换选项 + % gbcitelocal指标注中的本地化字符串 + % gbbiblocal 指文献表中的本地化字符串 + % gblocal 指设置文献表和标注中的本地化字符串 + % v1.0o,20190103,hzz + % + \DeclareBibliographyOption[string]{gbcitelocal}[gb7714-2015]{% + \ifstrequal{#1}{gb7714-2015}{\setcounter{gbcitelocalcase}{0}}{}% + \ifstrequal{#1}{chinese}{\setcounter{gbcitelocalcase}{1}}{}% + \ifstrequal{#1}{english}{\setcounter{gbcitelocalcase}{2}}{}% + } + \ExecuteBibliographyOptions{gbcitelocal} + + \DeclareBibliographyOption[string]{gbbiblocal}[gb7714-2015]{% + \ifstrequal{#1}{gb7714-2015}{\setcounter{gbbiblocalcase}{0}}{}% + \ifstrequal{#1}{chinese}{\setcounter{gbbiblocalcase}{1}}{}% + \ifstrequal{#1}{english}{\setcounter{gbbiblocalcase}{2}}{}% + } + \ExecuteBibliographyOptions{gbbiblocal} + + \DeclareBibliographyOption[string]{gblocal}[gb7714-2015]{% + \ExecuteBibliographyOptions{gbbiblocal=#1}% + \ExecuteBibliographyOptions{gbcitelocal=#1}% + } + %\ExecuteBibliographyOptions{gblocal} %默认值已经通过两个相关选项设置 + + % + % 增加序号标签格式处理选项 + % v1.0l,20180623,hzz + % + \DeclareBibliographyOption[string]{gbbiblabel}[bracket]{% + \csuse{gbbiblabelopt@#1} + } + \ExecuteBibliographyOptions{gbbiblabel} + + % + % 增加姓名大小写格式处理选项 + % + \DeclareBibliographyOption[string]{gbnamefmt}[uppercase]{% + \ifstrequal{#1}{uppercase}{\setcounter{gbnamefmtcase}{0}}{}% + \ifstrequal{#1}{lowercase}{\setcounter{gbnamefmtcase}{1}}{}% + \ifstrequal{#1}{givenahead}{\setcounter{gbnamefmtcase}{2}}{}%given-family + \ifstrequal{#1}{familyahead}{\setcounter{gbnamefmtcase}{3}}{} + \ifstrequal{#1}{pinyin}{\setcounter{gbnamefmtcase}{4}}{}%family-given + \ifstrequal{#1}{reverseorder}{\setcounter{gbnamefmtcase}{5}}{}%family-given/given-family + \ifstrequal{#1}{quanpin}{\setcounter{gbnamefmtcase}{6}}{}%全拼 + } + \ExecuteBibliographyOptions{gbnamefmt} + + % + % 增加标签对齐选项 + % + % right是默认的右对齐,left是左对齐,gb7714-2015是项对齐方式 + \DeclareBibliographyOption[string]{gbalign}[right]{% + \ifstrequal{#1}{right}{\setcounter{gbalignlabel}{0}}{} + \ifstrequal{#1}{left}{\setcounter{gbalignlabel}{1}}{} + \ifstrequal{#1}{center}{\setcounter{gbalignlabel}{2}}{} + \ifstrequal{#1}{gb7714-2015}{\setaligngbstyle}{} + \ifstrequal{#1}{gb7714-2015ay}{\setaligngbstyleay}{} + } + } + {% 针对biblatex<3.3版本的选项设置 + % 增加不同语言排序的切换选项 + % numeric样式, biblatex 3.4及以下版本不能使用多个stylesourcemap,所以不使用该选项 + % v1.0q,20190307,hzz + % + \DeclareBibliographyOption{gblanorder}[chineseahead]{} + + % + % 增加序号标签格式处理选项 + % v1.0l,20180623,hzz + % + \DeclareBibliographyOption{gbbiblabel}[bracket]{% + \csuse{gbbiblabelopt@#1} + } + \ExecuteBibliographyOptions{gbbiblabel} + + % + % 增加姓名大小写格式处理选项 + % + \DeclareBibliographyOption{gbnamefmt}[uppercase]{% + \ifstrequal{#1}{uppercase}{\setcounter{gbnamefmtcase}{0}}{}% + \ifstrequal{#1}{lowercase}{\setcounter{gbnamefmtcase}{1}}{}% + \ifstrequal{#1}{givenahead}{\setcounter{gbnamefmtcase}{2}}{}%given-family + \ifstrequal{#1}{familyahead}{\setcounter{gbnamefmtcase}{3}}{} + \ifstrequal{#1}{pinyin}{\setcounter{gbnamefmtcase}{4}}{}%family-given + \ifstrequal{#1}{reverseorder}{\setcounter{gbnamefmtcase}{5}}{}%family-given/given-family + \ifstrequal{#1}{quanpin}{\setcounter{gbnamefmtcase}{6}}{}%family-given + } + \ExecuteBibliographyOptions{gbnamefmt} + + % + % 增加标签对齐选项 + % + % 原理方法:right是默认的右对齐,left是左对齐,gb7714-2015无效,仍然为右对齐模式, + % 因为在这种biblatex低版本中,舍弃了list类环境后,会出错。 + % 注意:texlive2015中的3.0版中的DeclareBibliographyOption选项没有类型说明 + \DeclareBibliographyOption{gbalign}[right]{% + \ifstrequal{#1}{right}{\setcounter{gbalignlabel}{0}}{} + \ifstrequal{#1}{left}{\setcounter{gbalignlabel}{1}}{} + \ifstrequal{#1}{center}{\setcounter{gbalignlabel}{2}}{} + \ifstrequal{#1}{gb7714-2015}{}{} + \ifstrequal{#1}{gb7714-2015ay}{\setaligngbstyleay}{} + } + } + + +% +% 针对biblatex<3.3版本的选项设置,比如texlive2015中的3.0版 +% +\defversion{3.0}{opt}{ + \ExecuteBibliographyOptions{ + firstinits=true, %名字有缩写,参考3.1.2.3 Internal + } +} +% +% 针对3.3<=biblatex<3.5版本的选项设置,比如texlive2016中的3.4版 +% +\defversion{3.4}{opt}{ + \ExecuteBibliographyOptions{ + giveninits=true, %名字有缩写,参考3.1.2.3 Internal + } +} +% +% 针对3.7<=biblatex<=3.9版本的选项设置,比如texlive2017中的3.7版 +% +\defversion{3.7}{opt}{ + \ExecuteBibliographyOptions{ + giveninits=true, + urldate =edtf, %iso8601 + eventdate =edtf, + } +} +% +% 针对3.10<=biblatex版本的选项设置,比如texlive2018中的3.11版 +% +\defversion{3.10}{opt}{ + \ExecuteBibliographyOptions{ + giveninits=true, + urldate =gb7714-2015, %iso,iso8601,edtf + eventdate =gb7714-2015, + } +} + +% +% 根据biblatex版本信息,选择选项设置 +% +% 原理方法:如下这种选择机制能自动兼容更新的版本,但对于老版本 +% 必须要把情况列全。 +\iftoggle{iftlfive}{\switchversion{3.0}{opt}}{}%biblatex<=3.2 +\iftoggle{iftlsix}{\switchversion{3.4}{opt}}{}%3.3<=biblatex<=3.6 +\iftoggle{iftlseven}{\switchversion{3.7}{opt}}{}%biblatex=3.7 +\iftoggle{iftleight}{\switchversion{3.7}{opt}}{}%3.8<=biblatex<=3.9 +\iftoggle{iftlnine}{\switchversion{3.10}{opt}}{}%biblatex=3.10 +\iftoggle{iftlatest}{\switchversion{3.10}{opt}}{}%biblatex最新3.11 + + +%===================================================================== +% 设置本地化字符串 +%===================================================================== + % + % 新建当地化字符串,用来记录“等”字符、“和”字符 + % + \NewBibliographyString{andotherscn} + \NewBibliographyString{andothersincitecn} + \NewBibliographyString{andothersincite} + \NewBibliographyString{andcn} + \NewBibliographyString{andothersjp} + \NewBibliographyString{andotherskr} + \NewBibliographyString{andjp} + \NewBibliographyString{andkr} + \NewBibliographyString{andincitecn} + \NewBibliographyString{andincite} + \NewBibliographyString{volumecn} + \NewBibliographyString{numbercn} + \NewBibliographyString{serialcn} + \NewBibliographyString{incn} + \NewBibliographyString{mathesiscn} + \NewBibliographyString{phdthesiscn} + \NewBibliographyString{editorcn} + \NewBibliographyString{editorscn} + \NewBibliographyString{bytranslatorcn} + + + + % + % 修改一些当地化字符串 + % + % 原理方法:直接利用当地化格式english修改出一些中文的格式,具体修改内容参考english.lbx文件 + % 当然也可以增加比如上面定义的andotherscn + % 注意:在lbx文件和bbx文件中定义本地字符串的不同语法,两个参数和一个参数的区别 + + \DefineBibliographyStrings{english}{ + bibliography = {\str@bibliography}, + references = {\str@references}, + bytranslatorcn = {\str@bytranslator},%\addperiod,%将trans. by 改成 译\addcomma\ + and = {\addcomma},%将第2和3人名间的and符号改成逗号,用\finalnamedelim命令也可以定义,参见3.9.1节 + andcn = {\addcomma},%and本地化字符串的中文对应词 + andincitecn = {\str@andcn},%将标注中的分开,便于与文献表中的区分 + andincite = {\addcomma\space},%注意add开头的命令会其把前面的空格去掉 + %andothers = {et al.},%将超过3个人名的省略,et al.改成为 等 + andotherscn = {\str@andotherscn},%将超过3个人名的省略,et al.改成为 等 + andothersincitecn={\str@andotherscn},%将标注中的分开,便于与文献表中的区分 + andothersincite={et al\adddot}, + backrefpage = {\str@backrefpage:}, + backrefpages = {\str@backrefpages:}, + in={In\intitlepunct}, + volumecn={\str@volumecn}, + numbercn={\str@numbercn}, + serialcn={\str@serialcn}, + andothersjp={他}, + andotherskr={외}, + andjp={和}, + andkr={和}, + incn={\str@incn\addcolon\addspace}, + mathesiscn={\str@mathesiscn}, + phdthesiscn={\str@phdthesiscn}, + editorscn={\str@editorcn}, + editorcn={\str@editorcn}, +} + + % + % 增加两个命令用于临时的局部的修改本地化字符串 + % 其中\setlocalbibstring修改缩写字符串,setlocalbiblstring修改长字符串 + % 注意使用时因为是局部修改,因此要将其与需要修改的引用命令放在一个编组符号内 + % v1.0t,hzz,20190525 + \newcommand{\setlocalbibstring}[2]{% + \csdef{abx@sstr@#1}{#2}} + \newcommand{\setlocalbiblstring}[2]{% + \csdef{abx@lstr@#1}{#2}} + +%===================================================================== +% 动态数据修改 +%===================================================================== +% +% 各层次的数据映射和动态修改 +% +% 原理方法: +% 1. 进行语言包括中英文判断,并设置和记录,比如记录到userf,usere中 +% 2. 增加文献标识符如[M],[J]等,对一些容易混淆的域进行设置以增强兼容性 +% 3. \DeclareSourcemap命令对于biblatex3.11以下版本只能出现一次,3.11版开始支持多个 +% 4. \DeclarestyleSourcemap在biblatex v3.7版开始可以支持出现多次 +% 5. 把作者和译者信息准确的记录到userf,usere中,用于后面判断是否是cjk字符。 +% 注意:这里用userf,usere而不是namee,namef,是因为只有把name列表转成域,才能有效读取姓名中的字符, +% 如果用namee,namef,name信息会自动解析,所以就不能为cjk判断提供需要的信息 +% +% 不同的文献类型使用相同的驱动输出可以有5种方法: +% 1. 是数据源层的映射,将其它类型转换为某一要使用驱动的类型 +% 2. 是样式层映射,也是将其它类型转换为某一要使用驱动的类型 +% 3. 是驱动层映射,也是将其它类型转换为某一要使用驱动的类型 +% 4. 定义驱动类型别名DeclareBibliographyAlias,将其它类型定义为某一要使用驱动的类型的别名 +% 驱动别名定义本质上是做了驱动层映射 +% 5. 直接定义不同的类型的驱动,但驱动内容相同。 +% +% 关于数据映射和驱动使用的考虑如下: +% 1. 为避免利用biber输出bib文件时的数据变动,尽量不在数据源层映射做类型转换 +% 2. 为减少代码量,尽量少做内容相同的不同类型驱动 +% 3. 因此类型相关的处理主要在样式层映射、驱动层映射、驱动别名 +% 4. 由于biblatex默认做的驱动别名处理可能增加一些信息比如masterthesis转thesis时增加的type +% 可以在样式层映射做某些需要避免这种默认处置的转换 +% 5. 当没有避免默认行为的需求时,全部采用驱动别名的方式处理,等价于驱动层的映射 +% +% 文献类型和驱动考虑如下: +% 1. 连续出版物及析出文献有其特殊性,因此考虑两类periodical和article +% newpaper映射为article,并以note域做区分特殊处理 +% 2. 专著和专著中的析出文献是主要的类型,因此考虑book和inbook +% standard映射为book或inbook,并以note域做区分特殊处理 +% collection和proceedings基本与book类似,因此做book驱动别名处理 +% incollection和inproceedings基本与inbook类似,因此做inbook驱动别名处理 +% 3. 专利类型有其特殊性,考虑patent类型 +% 4. 电子资源类型有其特殊性,考虑online类型 +% 5. 报告类型与book有点类似,出版项处理与book一样,但有时又要有修改和更新日期 +% 因此考虑用一种类型来输出,使用report类型 +% 6. 手册/学位论文等类型与book有点类似,但对于出版项处理时,有缺省时,直接省略, +% 同时有version和edition的区别,因此考虑用一种类型来输出,使用manual类型 +% 7. 包括报告,学位论文在内的其它所有的类型,都做一个判断,当没有出版项时, +% 且存在网址信息时,将其转换为online类型输出,否则都做为manual类型输出。 +% 8. 备选类型misc当存在网址时直接转换为online,由于howpublished域可用于描述 +% 更多的信息,因此不存在网址时,独立做一个备选格式 +% 9. 出版项主要以如下方式处理: +% (a) location+institution+date 仅用于连续出版物 +% (b)publisher+location+date 用于需要完整输出出版项的类型,比如book,collection,proceedings,in*,report +% (c)institution+location+date 用于出版项缺失时不输出的类型,包括manual,thesis,archive等其他类型 +% (d)printlist{insitution} 用于电子资源,仅输出出版者或组织,为数据映射方便,本来默认的organization域转换为用insitution输出。 +% (e) 不输出,主要用于连续出版物析出的文献 +% 10. 日期以如下方式处理: +% date 由于存在biblatex选项,因此通过选项控制,数据源为date解析数据或year +% urldate 由于存在biblatex选项,因此通过选项控制,输出到日,且用[]包围,数据源为urldate +% newsdate 用于公告日期,公开日期或新闻日期,输出到日,但无包围符号,数据源为date +% modifydate 用于更新或修改日期,输出到日,且用()包围,数据源为date或enddate或eventdate + + +\DeclareSourcemap{ +\maps[datatype=bibtex]{% + \map{%如果author或者editor或者translator存在,那么设置namea便于后面判断。 + \step[fieldsource=author,final] + \step[fieldset=namea,origfieldval] + } + \map{% + \step[fieldsource=editor,final] + \step[fieldset=namea,origfieldval] + } + \map{% + \step[fieldsource=translator,final] + \step[fieldset=namea,origfieldval] + } + \map{%让address和location同步,biblatex中address是location的别名 + %因此输出的时候只有location信息,但处理过程中是可以存在address的。 + %\step[notfield=address,final] + \step[fieldsource=location,final] + \step[fieldset=address,origfieldval] + } + \map{%让address和location同步 + %\step[notfield=location,final] + \step[fieldsource=address,final] + \step[fieldset=location,origfieldval] + } + \map{%处理在bib文件用mark标记文献类型标识符的情况 + \step[fieldsource=mark,final] + \step[fieldset=usera, origfieldval] + } + \map{%处理在bib文件中直接给出文献的姓名格式为lowercase的情况 + \step[fieldsource=nameformat,match=lowercase,final] + \step[fieldset=namefmtid,fieldvalue={1}] + } + \map{%处理在bib文件中直接给出文献的姓名格式为givenahead的情况 + \step[fieldsource=nameformat,match=givenahead,final] + \step[fieldset=namefmtid,fieldvalue={2}] + } + \map{%处理在bib文件中直接给出文献的姓名格式为familyahead的情况 + \step[fieldsource=nameformat,match=familyahead,final] + \step[fieldset=namefmtid,fieldvalue={3}] + } + \map{%处理在bib文件中直接给出文献的姓名格式为pinyin的情况 + \step[fieldsource=nameformat,match=pinyin,final] + \step[fieldset=namefmtid,fieldvalue={4}] + } + \map{%处理在bib文件中直接给出文献的姓名格式为全拼的情况 + \step[fieldsource=nameformat,match=quanpin,final] + \step[fieldset=namefmtid,fieldvalue={6}] + } + \map{%根据article确定文献类型标识符 + \pertype{article} + \step[fieldset=usera, fieldvalue={J}] + } + \map{%根据periodical确定文献类型标识符 + \pertype{periodical} + \step[fieldset=usera, fieldvalue={J}] + \step[fieldsource=author] %有时会把author和editor混淆,处理后使用editor + \step[fieldset=editor, origfieldval] + \step[fieldsource=publisher] %有时会把publisher和institution混淆,处理后使用institution + \step[fieldset=institution, origfieldval] + } + \map{%根据增加一个新闻报纸的类型newspaper确定文献类型标识符 + \pertype{newspaper} + \step[fieldset=usera, fieldvalue={N}] + \step[fieldset=note, fieldvalue=news]%因为没有专门的驱动,记录note方便映射为article后判断 + } + \map{%对应增加的一个数据库类型database确定文献类型标识符 + \pertype{database} + \step[fieldset=usera, fieldvalue={DB}] + \step[fieldsource=publisher] %有时会把publisher和institution混淆,处理后使用institution + \step[fieldset=institution, origfieldval] + } + \map{%对应增加的一个数据集类型dataset确定文献类型标识符 + \pertype{dataset} + \step[fieldset=usera, fieldvalue={DS}]% + \step[fieldsource=publisher] %有时会把publisher和institution混淆,处理后使用institution + \step[fieldset=institution, origfieldval] + } + \map{%对应增加的一个软件类型software确定文献类型标识符 + \pertype{software} + \step[fieldset=usera, fieldvalue={CP}] + \step[fieldsource=publisher] %有时会把publisher和institution混淆,处理后使用institution + \step[fieldset=institution, origfieldval] + } + \map{%对应增加的一个舆图类型map确定文献类型标识符 + \pertype{map} + \step[fieldset=usera, fieldvalue={CM}]% + \step[fieldsource=publisher] %有时会把publisher和institution混淆,处理后使用institution + \step[fieldset=institution, origfieldval] + } + \map{%对应增加的一个档案类型archive确定文献类型标识符 + \pertype{archive} + \step[fieldset=usera, fieldvalue={A}] + \step[fieldsource=publisher] %有时会把publisher和institution混淆,处理后使用institution + \step[fieldset=institution, origfieldval] + } + \map{%因为misc类型本身就是没有类型,而不像其它文献有明确的类型,所以 + %当misc类型带有网址时,直接将其转换为online类型 + \pertype{misc} + \step[fieldsource=url,final] + \step[typesource=misc,typetarget=online] + } + \map{%对应增加的一个备选类型misc确定文献类型标识符 + \pertype{misc} + \step[fieldset=usera, fieldvalue={Z}]% + } + \map{ + \pertype{book} + \pertype{inbook} + \step[fieldset=usera, fieldvalue={M}] + \step[fieldsource=version] %有时会把version和edition混淆,处理后直接用edition + \step[fieldset=edition, origfieldval] + } + \map{%兼容老的standard类型,确定文献类型标识符 + \pertype{standard} + \step[fieldset=usera, fieldvalue={S}] + \step[fieldset=note, fieldvalue=standard]%因为没有专门的驱动,记录note方便映射为book和inbook后判断 + } + \map{ + \pertype{patent} + \step[fieldset=usera, fieldvalue={P}] + } + \map{ + \pertype{inproceedings} + \pertype{conference}%兼容老的conference类型 + \step[fieldset=usera, fieldvalue={C}] + \step[fieldsource=institution]%有时会把publisher和institution混淆,处理后使用publisher + \step[fieldset=publisher, origfieldval] + } + \map{ + \pertype{proceedings} + \step[fieldset=usera, fieldvalue={C}] + \step[fieldsource=institution]%有时会把publisher和institution混淆,处理后使用publisher + \step[fieldset=publisher, origfieldval] + } + \map{ + \pertype{incollection} + \step[fieldset=usera, fieldvalue={G}] + \step[fieldsource=institution]%有时会把publisher和institution混淆,处理后使用publisher + \step[fieldset=publisher, origfieldval] + } + \map{ + \pertype{collection} + \step[fieldset=usera, fieldvalue={G}] + \step[fieldsource=institution]%有时会把publisher和institution混淆,处理后使用publisher + \step[fieldset=publisher, origfieldval] + } + \map{ + \pertype{report} + \pertype{techreport}%兼容老的techreport类型 + \step[fieldset=usera, fieldvalue={R}] + \step[fieldsource=institution]%有时会把publisher和institution混淆,处理后使用publisher + \step[fieldset=publisher, origfieldval] + } + \map{ + \pertype{thesis} + \pertype{mastersthesis}%兼容老的mastersthesis和phdthesis类型 + \pertype{phdthesis} + \step[fieldset=usera, fieldvalue={D}] + \step[fieldsource=publisher]%有时会把publisher和institution混淆,处理后使用institution + \step[fieldset=institution, origfieldval] + } + \map{ + \pertype{online} + \pertype{electronic}%兼容老的electronic类型 + \pertype{www}%兼容老的www类型 + \step[fieldset=usera, fieldvalue={EB}] + \step[fieldsource=publisher]%有时会把publisher和institution混淆,处理后使用institution + \step[fieldset=institution, origfieldval]%因为online的出版项处理类似手册 + \step[fieldsource=organization]%有时会把organization和institution混淆,处理后使用institution,以增强兼容性 + \step[fieldset=institution, origfieldval] + } + \map{ + \pertype{manual} + \step[fieldset=usera, fieldvalue={A}] + \step[fieldsource=edition]%有时会把version和edition混淆,处理后使用version + \step[fieldset=version, origfieldval] + \step[fieldsource=publisher]%有时会把publisher和institution混淆,处理后使用institution + \step[fieldset=institution, origfieldval] + \step[fieldsource=organization]%有时会把organization和institution混淆,处理后使用institution,以增强兼容性 + \step[fieldset=institution, origfieldval] + } + \map{ + \pertype{unpublished} + \step[fieldset=usera, fieldvalue={Z}] + } + \map[overwrite]{%用于处理zotero从cnki导出中文文献姓名中存在逗号的情况 + \step[fieldsource={author}, match=\regexp{([\x{2FF0}-\x{9FA5}])\,\s*}, replace=\regexp{$1}] + }% + \map[overwrite]{%用于处理zotero从cnki导出中文文献姓名中存在逗号的情况 + \step[fieldsource={editor}, match=\regexp{([\x{2FF0}-\x{9FA5}])\,\s*}, replace=\regexp{$1}] + }% + \map[overwrite]{%用于处理zotero从cnki导出中文文献姓名中存在逗号的情况 + \step[fieldsource={translator}, match=\regexp{([\x{2FF0}-\x{9FA5}])\,\s*}, replace=\regexp{$1}] + }% + \map[overwrite]{%用于处理zotero从cnki导出中文文献姓名中存在逗号的情况 + \step[fieldsource={bookauthor}, match=\regexp{([\x{2FF0}-\x{9FA5}])\,\s*}, replace=\regexp{$1}] + }% + \map{%处理一些用year表示date的情况 + %这样处理将会设置date域,并使得labeldatesource变为空,因为date的前缀为空(如果是urldate,那么labeldatesource就是url)。 + %同时date域会被biblatex自动解析为year,month,day,并且覆盖原来的year信息 + \step[fieldsource=year] + \step[fieldset=date, origfieldval] + } + \map{%将entrykey放入keywords中用于后期使用 + \step[fieldsource=entrykey] + \step[fieldset=keywords, origfieldval] + } + \map{\step[fieldsource=title,match=\regexp{[\x{0100}-\x{017F}]},final]%\x80-\xFF + \step[fieldset=userd,fieldvalue={french}]%法语,0080开始到00ff的字符没法匹配有点奇怪 + } + \map{% + \step[fieldsource=title,match=\regexp{[\x{0400}-\x{052F}]},final] + \step[fieldset=userd,fieldvalue={russian}]%俄语 + } + \map{% + \step[fieldsource=title,match=\regexp{[\x{3040}-\x{30FF}\x{31F0}-\x{31FF}]},final] + \step[fieldset=userd,fieldvalue={japanese}]%日语 + } %确定形式后可增加类似andotherscn这样的本地化字符串处理 + \map{% + \step[fieldsource=title,match=\regexp{[\x{1100}-\x{11FF}\x{3130}-\x{318F}\x{AC00}-\x{D7AF}]},final] + \step[fieldset=userd,fieldvalue={korean}]%韩语 + } + \map{%文献题名的中文判断,将信息保存到userd中,避免因为标签生成原因导致title域被清除而产生问题 + \step[fieldsource=title, match=\regexp{[\x{2FF0}-\x{9FA5}]},final]% + \step[fieldset=userd, fieldvalue={chinese}] + } + \map{%将没有设置userd,且存在title域的默认设置为英文 + \step[fieldsource=title,final] + \step[fieldset=userd,fieldvalue={english}] + } + \map{\step[fieldsource=author,match=\regexp{[\x{0100}-\x{017F}]},final]%\x80-\xFF + \step[fieldset=userf,fieldvalue={french}]%法语,0080开始到00ff的字符没法匹配有点奇怪 + } + \map{% + \step[fieldsource=author,match=\regexp{[\x{0400}-\x{052F}]},final] + \step[fieldset=userf,fieldvalue={russian}]%俄语 + } + \map{% + \step[fieldsource=author,match=\regexp{[\x{3040}-\x{30FF}\x{31F0}-\x{31FF}]},final] + \step[fieldset=userf,fieldvalue={japanese}]%日语 + } %确定形式后可增加类似andotherscn这样的本地化字符串处理 + \map{% + \step[fieldsource=author,match=\regexp{[\x{1100}-\x{11FF}\x{3130}-\x{318F}\x{AC00}-\x{D7AF}]},final] + \step[fieldset=userf,fieldvalue={korean}]%韩语 + } + \map{%作者的中文判断 + \step[fieldsource=author, match=\regexp{[\x{2FF0}-\x{9FA5}]},final] + \step[fieldset=userf, fieldvalue={chinese}] + } + \map{%将没有设置userf,且存在author域的默认设置为英文 + \step[fieldsource=author,final] + \step[fieldset=userf,fieldvalue={english}] + } + \map{\step[fieldsource=translator,match=\regexp{[\x{0100}-\x{017F}]},final]%\x80-\xFF + \step[fieldset=usere,fieldvalue={french}]%法语,0080开始到00ff的字符没法匹配有点奇怪 + } + \map{% + \step[fieldsource=translator,match=\regexp{[\x{0400}-\x{052F}]},final] + \step[fieldset=usere,fieldvalue={russian}]%俄语 + } + \map{% + \step[fieldsource=translator,match=\regexp{[\x{3040}-\x{30FF}\x{31F0}-\x{31FF}]},final] + \step[fieldset=usere,fieldvalue={japanese}]%日语 + } %确定形式后可增加类似andotherscn这样的本地化字符串处理 + \map{% + \step[fieldsource=translator,match=\regexp{[\x{1100}-\x{11FF}\x{3130}-\x{318F}\x{AC00}-\x{D7AF}]},final] + \step[fieldset=usere,fieldvalue={korean}]%韩语 + } + \map{%译者的中文判断 + \step[fieldsource=translator, match=\regexp{[\x{2FF0}-\x{9FA5}]},final] + \step[fieldset=usere, fieldvalue={chinese}] + } + \map{%将没有设置usere,且存在translator域的默认设置为英文 + \step[fieldsource=translator,final] + \step[fieldset=usere,fieldvalue={english}] + } + \map{\step[fieldsource=editor,match=\regexp{[\x{0100}-\x{017F}]},final]%\x80-\xFF + \step[fieldset=userc,fieldvalue={french}]%法语,0080开始到00ff的字符没法匹配有点奇怪 + } + \map{% + \step[fieldsource=editor,match=\regexp{[\x{0400}-\x{052F}]},final] + \step[fieldset=userc,fieldvalue={russian}]%俄语 + } + \map{% + \step[fieldsource=editor,match=\regexp{[\x{3040}-\x{30FF}\x{31F0}-\x{31FF}]},final] + \step[fieldset=userc,fieldvalue={japanese}]%日语 + } %确定形式后可增加类似andotherscn这样的本地化字符串处理 + \map{% + \step[fieldsource=editor,match=\regexp{[\x{1100}-\x{11FF}\x{3130}-\x{318F}\x{AC00}-\x{D7AF}]},final] + \step[fieldset=userc,fieldvalue={korean}]%韩语 + } + \map{%编者的中文判断 + \step[fieldsource=editor, match=\regexp{[\x{2FF0}-\x{9FA5}]},final]%直接匹配cjk字符,unicode编码位置从2FF0到9FA5 + \step[fieldset=userc, fieldvalue={chinese}] + } + \map{%将没有设置userc,且存在editor域的默认设置为英文 + \step[fieldsource=editor,final] + \step[fieldset=userc,fieldvalue={english}] + } + \map{\step[fieldsource=bookauthor,match=\regexp{[\x{0100}-\x{017F}]},final]%\x80-\xFF + \step[fieldset=userb,fieldvalue={french}]%法语,0080开始到00ff的字符没法匹配有点奇怪 + } + \map{% + \step[fieldsource=bookauthor,match=\regexp{[\x{0400}-\x{052F}]},final] + \step[fieldset=userb,fieldvalue={russian}]%俄语 + } + \map{% + \step[fieldsource=bookauthor,match=\regexp{[\x{3040}-\x{30FF}\x{31F0}-\x{31FF}]},final] + \step[fieldset=userb,fieldvalue={japanese}]%日语 + } %确定形式后可增加类似andotherscn这样的本地化字符串处理 + \map{% + \step[fieldsource=bookauthor,match=\regexp{[\x{1100}-\x{11FF}\x{3130}-\x{318F}\x{AC00}-\x{D7AF}]},final] + \step[fieldset=userb,fieldvalue={korean}]%韩语 + } + \map{%编者的中文判断 + \step[fieldsource=bookauthor, match=\regexp{[\x{2FF0}-\x{9FA5}]},final]%直接匹配cjk字符,unicode编码位置从2FF0到9FA5 + \step[fieldset=userb, fieldvalue={chinese}] + } + \map{%将没有设置userc,且存在editor域的默认设置为英文 + \step[fieldsource=bookauthor,final] + \step[fieldset=userb,fieldvalue={english}] + } + \map{\step[fieldsource=userd,final]%userd存在则用根据标题的语言设定language + \step[fieldset=language,origfieldval]%本身language存在则不设定 + } + \map{\step[fieldsource=userf,final]%userd不存在,而userf存在则根据author的语言设定language + \step[fieldset=language,origfieldval] + }%如果没有作者和标题,那么剩下的最可能有意义的只有网址了,而网址通常是英文的,因此不用再进一步对其它域进行判断了。 + \map{%将没有设置的language设置成en,即认为不是中文的就是英文的。 + \step[fieldset=language,fieldvalue={english}] + } + \map{%一条文献的语言已经设定在language域中,由于出版项相关宏中使用userd判断, + %所以将一条文献的主体语言设定到userd中,本身前面userd已经设定,但没有处理无标题的情况, + %这里的处理等价于没有标题时,利用作者的语言设定userd,再没有作者,则默认用英文设定userd + \step[fieldsource=language] + \step[fieldset=userd,origfieldval] + } + \map{%当文献给出language域时,设置文献要使用的本地化字符串的语言 + %biblatex 3.11及以下版本仅有match是区分大小写的,而3.12版开始用matchi来区分大小,而match不区分 + %这里为兼容3.11及以下版本,所以用一个复杂一点的正则表达式 + \step[fieldsource=language,match=\regexp{(e|E)(n|N)(g|G)(l|L)(i|I)(s|S)(h|H)},final] + \step[fieldset=langid,fieldvalue={english}] + \step[fieldset=languageid,fieldvalue={english}] + \step[fieldset=lansortorder,fieldvalue=\lanenorder] + } + \map{ + \step[fieldsource=language,match=\regexp{(r|R)(u|U)(s|S)(s|S)(i|I)(a|A)(n|N)},final] + \step[fieldset=langid,fieldvalue={russian}] + \step[fieldset=languageid,fieldvalue={russian}] + \step[fieldset=lansortorder,fieldvalue=\lanruorder] + } + \map{% + \step[fieldsource=language,match=\regexp{(f|F)(r|R)(e|E)(n|N)(c|C)(h|H)},final] + \step[fieldset=langid,fieldvalue={french}] + \step[fieldset=languageid,fieldvalue={french}] + \step[fieldset=lansortorder,fieldvalue=\lanfrorder] + } + \map{% + \step[fieldsource=language,match=\regexp{(c|C)(h|H)(i|I)(n|N)(e|E)(s|S)(e|E)},final]%中日韩语目前都用english, + \step[fieldset=langid,fieldvalue={english}] + \step[fieldset=languageid,fieldvalue={chinese}] + \step[fieldset=lansortorder,fieldvalue=\lancnorder] + } + \map{% + \step[fieldsource=language,match=\regexp{(j|J)(a|A)(p|P)(a|A)(n|N)(e|E)(s|S)(e|E)},final]%中日韩语目前都用english, + \step[fieldset=langid,fieldvalue={english}] + \step[fieldset=languageid,fieldvalue={japanese}] + \step[fieldset=lansortorder,fieldvalue=\lanjporder] + } + \map{% + \step[fieldsource=language,match=\regexp{(k|K)(o|O)(r|R)(e|E)(a|A)(n|N)},final]%中日韩语目前都用english, + \step[fieldset=langid,fieldvalue={english}] + \step[fieldset=languageid,fieldvalue={korean}] + \step[fieldset=lansortorder,fieldvalue=\lankrorder] + } + \map[overwrite]{%bib中abstract和howpublished常出现特殊字符这里做一下预处理。 + \step[fieldsource={howpublished}, match=\regexp{([^\\])\%}, replace=\regexp{$1\\\%}] + } + \map[overwrite]{ + \step[fieldsource={abstract}, match=\regexp{([^\\])\%}, replace=\regexp{$1\\\%}] + } + \map[overwrite]{ + \step[fieldsource={howpublished}, match=\regexp{([^\\])\#}, replace=\regexp{$1\\\#}] + } + \map[overwrite]{ + \step[fieldsource={abstract}, match=\regexp{([^\\])\#}, replace=\regexp{$1\\\#}] + } + \map[overwrite]{%&符号处理 + \step[fieldsource={abstract}, match=\regexp{([^\\])\x26}, replace=\regexp{$1\\\x26}] + } + \map[overwrite]{%&符号处理 + \step[fieldsource={howpublished}, match=\regexp{([^\\])\x26}, replace=\regexp{$1\\\x26}] + } +} +} + + +% +% 修改输入的参考文献数据,样式层的操作 +% +% 原理方法:因为biblatex3.0版的map不使用foreach选项,所以需要一个一个写,以处理特殊字符 +\defversion{3.0}{map}{ + \DeclareStyleSourcemap{ + \maps[datatype=bibtex]{ + \map{%尝试未定义数据模型的standard类型映射为其他类型book或inbook, + %standard类型在blx-dm中有出现,但仅定义了类型,域和约束等都没有定义 + %因为可能要映射两种类型,所以不能在驱动层处理,因为要做判断 + \step[fieldsource=booktitle,final]%当存在booktitle域是映射为inbook + \step[typesource=standard, typetarget=inbook, final] + } + \map{%剩下的全部映射为book + \step[typesource=standard, typetarget=book, final] + } +% \map{%先于标准样式的driver层映射,以取消type设置 +% \step[typesource=mastersthesis, typetarget=thesis, final] +% %\step[fieldset=type, fieldvalue=mathesis] +% } +% \map{%先于标准样式的driver层映射,以取消type设置 +% \step[typesource=phdthesis, typetarget=thesis, final] +% %\step[fieldset=type, fieldvalue=phdthesis] +% } + \map{%先于标准样式的driver层映射,以取消type设置 + \step[typesource=techreport, typetarget=report, final] + %\step[fieldset=type, fieldvalue=techreport] + } + \map{% + \pertype{report} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=report,typetarget=online] + \step[fieldset=note,fieldvalue={report}] + } + \map{% + \pertype{thesis} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=thesis,typetarget=online] + } + \map{% + \pertype{manual} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=manual,typetarget=online] + } + \map{% + \pertype{unpublished} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=unpublished,typetarget=online] + } + \map{% + \pertype{database} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=databasetypetarget=online] + } + \map{% + \pertype{dataset} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=dataset,typetarget=online] + } + \map{% + \pertype{software} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=software,typetarget=online] + } + \map{% + \pertype{map} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=map,typetarget=online] + } + \map{% + \pertype{archive} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=archive,typetarget=online] + } + \map[overwrite]{%这里还必须有overwrite,注意不同版本存在差异,比如texlive2015变16后biber有变化(20161207修改正确) + \step[fieldsource=note, final]%将note域信息复制给keywords,用于输出时容易区分标准和报纸 + \step[fieldset=keywords, fieldvalue={,}, append] + \step[fieldset=keywords, origfieldval, append] + } + \map[overwrite]{%title,booktitle,journaltitle,journal,publisher,address,location,institution,organization + \step[fieldsource={title}, match=\regexp{([^\\])\x26}, replace=\regexp{$1\\\x26}] + } + \map[overwrite]{ + \step[fieldsource={booktitle}, match=\regexp{([^\\])\x26}, replace=\regexp{$1\\\x26}] + } + \map[overwrite]{ + \step[fieldsource={journaltitle}, match=\regexp{([^\\])\x26}, replace=\regexp{$1\\\x26}] + } + \map[overwrite]{ + \step[fieldsource={journal}, match=\regexp{([^\\])\x26}, replace=\regexp{$1\\\x26}] + } + \map[overwrite]{ + \step[fieldsource={publisher}, match=\regexp{([^\\])\x26}, replace=\regexp{$1\\\x26}] + } + \map[overwrite]{ + \step[fieldsource={address}, match=\regexp{([^\\])\x26}, replace=\regexp{$1\\\x26}] + } + \map[overwrite]{ + \step[fieldsource={location}, match=\regexp{([^\\])\x26}, replace=\regexp{$1\\\x26}] + } + \map[overwrite]{%&符号处理 + \step[fieldsource={institution}, match=\regexp{([^\\])\x26}, replace=\regexp{$1\\\x26}] + } + \map[overwrite]{ + \step[fieldsource={booktitle}, match=\regexp{([^\\])\#}, replace=\regexp{$1\\\#}] + } + \map[overwrite]{ + \step[fieldsource={booktitle}, match=\regexp{([^\\])\%}, replace=\regexp{$1\\\%}] + } + } + } +} + +% +% 修改输入的参考文献数据,样式层的操作 +% +% 原理方法:biblatex3.4以上版本 +\defversion{3.4}{map}{ + \DeclareStyleSourcemap{ + \maps[datatype=bibtex]{ + \map{%尝试未定义数据模型的standard类型映射为其他类型book或inbook, + %standard类型在blx-dm中有出现,但仅定义了类型,域和约束等都没有定义 + %因为可能要映射两种类型,所以不能在驱动层处理,因为要做判断 + \step[fieldsource=booktitle,final]%当存在booktitle域是映射为inbook + \step[typesource=standard, typetarget=inbook, final] + } + \map{%剩下的全部映射为book + \step[typesource=standard, typetarget=book, final] + } +% \map{%先于标准样式的driver层映射,以取消type设置 +% \step[typesource=mastersthesis, typetarget=thesis, final] +% %\step[fieldset=type, fieldvalue=mathesis] +% } +% \map{%先于标准样式的driver层映射,以取消type设置 +% \step[typesource=phdthesis, typetarget=thesis, final] +% %\step[fieldset=type, fieldvalue=phdthesis] +% } + \map{%先于标准样式的driver层映射,以取消type设置 + \step[typesource=techreport, typetarget=report, final] + %\step[fieldset=type, fieldvalue=techreport] + } + \map{% + \pertype{report} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=report,typetarget=online] + \step[fieldset=note,fieldvalue={report}] + } + \map{% + \pertype{thesis} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=thesis,typetarget=online] + } + \map{% + \pertype{manual} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=manual,typetarget=online] + } + \map{% + \pertype{unpublished} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=unpublished,typetarget=online] + } + \map{% + \pertype{database} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=databasetypetarget=online] + } + \map{% + \pertype{dataset} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=dataset,typetarget=online] + } + \map{% + \pertype{software} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=software,typetarget=online] + } + \map{% + \pertype{map} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=map,typetarget=online] + } + \map{% + \pertype{archive} + %biblatex3.7以下版本用如下方式来替代,address和location已在sourcemap中同步 + \step[fieldset=location,fieldvalue={}] + \step[fieldsource=location,notmatch=\regexp{.},final]%地址不存在且存在url那么转变为online + %3.7以上版本用notfield + %\step[notfield=address,final]%当address不存在则继续 + \step[fieldsource=url,final]%地址不存在且存在url那么转变为online + \step[typesource=archive,typetarget=online] + } + \map[overwrite]{%这里还必须有overwrite,注意不同版本存在差异,比如texlive2015变16后biber有变化(20161207修改正确) + \step[fieldsource=note, final]%将note域信息复制给keywords,用于输出时容易区分标准和报纸 + \step[fieldset=keywords, fieldvalue={,}, append] + \step[fieldset=keywords, origfieldval, append] + } + \map[overwrite, foreach={title,booktitle,journaltitle,journal,publisher,address,location,institution,organization}]{ + \step[fieldsource=\regexp{$MAPLOOP}, match=\regexp{([^\\])\#}, replace=\regexp{$1\\\#}] + } + \map[overwrite, foreach={title,booktitle,journaltitle,journal,publisher,address,location,institution,organization}]{ + \step[fieldsource=\regexp{$MAPLOOP}, match=\regexp{([^\\])\%}, replace=\regexp{$1\\\%}] + } + \map[overwrite, foreach={title,booktitle,journaltitle,journal,publisher,% + address,location,institution,organization}]{ + \step[fieldsource=\regexp{$MAPLOOP}, match=\regexp{([^\\])\x26}, replace=\regexp{$1\\\x26}] + } + } + } +} + +\iftoggle{iftlfive}% + {\switchversion{3.0}{map}}%%当采用biblatex<=3.2版本时 + {\switchversion{3.4}{map}}%%当采用3.3<=biblatex版本时 + + +% +% 不同语言分集调整的实现方式 +% +% 原理方法:利用样式层的动态数据修改lansortorder域来实现排序 +\def\dealsortlan{ + \DeclareStyleSourcemap{ + \maps[datatype=bibtex]{ + \map[overwrite]{%当文献给出language域时,设置文献要使用的本地化字符串的语言 + \step[fieldsource=language,match=english,final] + \step[fieldset=lansortorder,fieldvalue=\lanenorder] + } + \map[overwrite]{ + \step[fieldsource=language,match=russian,final] + \step[fieldset=lansortorder,fieldvalue=\lanruorder] + } + \map[overwrite]{% + \step[fieldsource=language,match=french,final] + \step[fieldset=lansortorder,fieldvalue=\lanfrorder] + } + \map[overwrite]{% + \step[fieldsource=language,match=chinese,final]%中日韩语目前都用english, + \step[fieldset=lansortorder,fieldvalue=\lancnorder] + } + \map[overwrite]{% + \step[fieldsource=language,match=japanese,final]%中日韩语目前都用english, + \step[fieldset=lansortorder,fieldvalue=\lanjporder] + } + \map[overwrite]{% + \step[fieldsource=language,match=korean,final]%中日韩语目前都用english, + \step[fieldset=lansortorder,fieldvalue=\lankrorder] + } + } + } +} + +% +%驱动别名等价于驱动层映射 +% +\DeclareBibliographyAlias{newspaper}{article}% +\DeclareBibliographyAlias{inproceedings}{inbook}%会议论文文献类型驱动 +\DeclareBibliographyAlias{conference}{inbook}%会议论文文献类型驱动 +\DeclareBibliographyAlias{incollection}{inbook}%文集中析出文献类型驱动 +\DeclareBibliographyAlias{collection}{book}%%文集类型驱动 +\DeclareBibliographyAlias{proceedings}{book}%会议论文集文献类型驱动 +\DeclareBibliographyAlias{thesis}{manual}%学位论文驱动 +\DeclareBibliographyAlias{unpublished}{manual}%其它类型驱动 +\DeclareBibliographyAlias{database}{manual} +\DeclareBibliographyAlias{dataset}{manual} +\DeclareBibliographyAlias{software}{manual} +\DeclareBibliographyAlias{map}{manual} +\DeclareBibliographyAlias{archive}{manual} + +%===================================================================== +% 设置排序格式 +%===================================================================== +% +% 排序格式,用降序,及userb域,针对biblatex3.7及以下版本 +% +\defversion{3.7}{sort}{%这是3.4版的,3.7版略有差异,但不大,后面有注释 + \DeclareSortingScheme{gb7714-2015}{ + \sort{ + \field{presort} + } + %\sort[final]{ + %\field{sortkey} + %} + \sort{ + \field{lansortorder}%language + } + \sort{ + \field{sortkey} + } + \sort{%[direction=descending] + \field{sortname} + \field{author} + \field{editor} + \field{translator} + } + \sort{ + \field{sortyear} + \field{year} + } + \sort{ + \field{sorttitle} + \field{title} + } + \sort{ + \field[padside=left,padwidth=4,padchar=0]{volume}%3.7版是\field{volume} + \literal{0000}%3.7版是\literal{0} + } + } + + %降序的nyt + \DeclareSortingScheme{gbnytd}{ + \sort{ + \field{presort} + } + %\sort[final]{ + %\field{sortkey} + %} + \sort{ + \field{lansortorder}%language + } + \sort[direction=descending]{ + \field{sortkey} + } + \sort[direction=descending]{ + \field{sortname} + \field{author} + \field{editor} + \field{translator} + } + \sort{ + \field{sortyear} + \field{year} + } + \sort{ + \field{sorttitle} + \field{title} + } + \sort{ + \field[padside=left,padwidth=4,padchar=0]{volume}%3.7版是\field{volume} + \literal{0000}%3.7版是\literal{0} + } + } + + %降序的ynt + \DeclareSortingScheme{gbyntd}{ + \sort{ + \field{presort} + } + %\sort[final]{ + %\field{sortkey} + %} + \sort{ + \field{lansortorder}%language + } + \sort[direction=descending]{ + \field{sortyear} + \field{year} + } + \sort{ + \field{sortkey} + } + \sort{ + \field{sortname} + \field{author} + \field{editor} + \field{translator} + } + \sort{ + \field{sorttitle} + \field{title} + } + \sort{ + \field[padside=left,padwidth=4,padchar=0]{volume}%3.7版是\field{volume} + \literal{0000}%3.7版是\literal{0} + } + } + + %升序的ynt + \DeclareSortingScheme{gbynta}{ + \sort{ + \field{presort} + } + %\sort[final]{ + %\field{sortkey} + %} + \sort{ + \field{lansortorder}%language + } + \sort{ + \field{sortyear} + \field{year} + } + \sort{ + \field{sortkey} + } + \sort{ + \field{sortname} + \field{author} + \field{editor} + \field{translator} + } + \sort{ + \field{sorttitle} + \field{title} + } + \sort{ + \field[padside=left,padwidth=4,padchar=0]{volume}%3.7版是\field{volume} + \literal{0000}%3.7版是\literal{0} + } + } +} + + +% +% 排序格式,用降序,及userb域,针对biblatex3.8及以上版本 +% +\defversion{3.8}{sort}{ + \DeclareSortingTemplate{gb7714-2015}{ + \sort{ + \field{presort} + } + %\sort[final]{ + %\field{sortkey} + %} + \sort{ + \field{lansortorder}%language + } + \sort{ + \field{sortkey} + } + \sort{%[direction=descending] + \field{sortname} + \field{author} + \field{editor} + \field{translator} + } + \sort{ + \field{sortyear} + \field{year} + } + \sort{ + \field{sorttitle} + \field{title} + } + \sort{ + \field{volume} + \literal{0} + } + } + + %降序的nyt + \DeclareSortingTemplate{gbnytd}{ + \sort{ + \field{presort} + } +% \sort[final]{ +% \field{sortkey} +% } + \sort{ + \field{lansortorder}%language + } + \sort[direction=descending]{ + \field{sortkey} + } + \sort[direction=descending]{% + \field{sortname} + \field{author} + \field{editor} + \field{translator} + } + \sort{ + \field{sortyear} + \field{year} + } + \sort{ + \field{sorttitle} + \field{title} + } + \sort{ + \field{volume} + \literal{0} + } + } + + %降序的ynt + \DeclareSortingTemplate{gbyntd}{ + \sort{ + \field{presort} + } +% \sort[final]{ +% \field{sortkey} +% } + \sort{ + \field{lansortorder}%language + } + \sort[direction=descending]{ + \field{sortyear} + \field{year} + } + \sort{ + \field{sortkey} + } + \sort{% + \field{sortname} + \field{author} + \field{editor} + \field{translator} + } + \sort{ + \field{sorttitle} + \field{title} + } + \sort{ + \field{volume} + \literal{0} + } + } + + %升序的ynt + \DeclareSortingTemplate{gbynta}{ + \sort{ + \field{presort} + } +% \sort[final]{ +% \field{sortkey} +% } + \sort{ + \field{lansortorder}%language + } + \sort{%[direction=ascending] + \field{sortyear} + \field{year} + } + \sort{ + \field{sortkey} + } + \sort{% + \field{sortname} + \field{author} + \field{editor} + \field{translator} + } + \sort{ + \field{sorttitle} + \field{title} + } + \sort{ + \field{volume} + \literal{0} + } + } +} + + +\ifboolexpr{ +test {\iftoggle{iftlfive}} +or +test {\iftoggle{iftlsix}} +or +test {\iftoggle{iftlseven}}%biblatex<=3.7 +}{\switchversion{3.7}{sort}}{\switchversion{3.8}{sort}}%3.8<=biblatex + +%===================================================================== +% 参考文献表环境 +%===================================================================== +% +% 列表格式 +% +% 增加一个\bibitemindent尺寸用于控制list环境的itemindent +% v1.0l,20180615,hzz +% v1.0t,20200319,hzz,增加尺寸\biblabelextend使某些字体下标签宽度不足时可增加标签宽度 +\setlength{\bibhang}{\biblabelsep}% +\newlength{\bibitemindent} +\setlength{\bibitemindent}{0pt} +\newlength{\biblabelextend} +\setlength{\biblabelextend}{0pt} + + +\defbibenvironment{bibliography} + {\list + {\printtext[labelnumberwidth]{% + \printfield{labelprefix}% + \printfield{labelnumber}}} + {\addtolength{\labelnumberwidth}{\biblabelextend}% + \setlength{\labelwidth}{\labelnumberwidth}% + \setlength{\labelsep}{\biblabelsep}% + \setlength{\leftmargin}{\bibhang}% + \addtolength{\leftmargin}{\labelnumberwidth}% + \setlength{\itemindent}{\bibitemindent}% + \setlength{\itemsep}{\bibitemsep}% + \setlength{\parsep}{\bibparsep}}% + \renewcommand*{\makelabel}[1]{\hss##1}} + {\endlist} + {\item} + +% +% 顺序编码制-标签对齐方式处理 +% +% 原理方法:利用选项提供的计数器数值做选择 +% 左对齐,右对齐为list环境下的处理,此时list环境的\labelwidth只能设置一个,是最宽标签的宽度 +% 项对齐则是在段落环境下做的处理。 +% 左对齐时,参考文献各项内容对齐,序号标签与参考文献项内容的间距可变 +% 右对齐时,参考文献各项内容对齐,序号标签与参考文献项内容的间距相等,标签与页边距离可变 +% 项对齐时,序号标签贴在页边,序号标签与参考文献项内容的间距相等 +% 修改序号标签格式为: +% \DeclareFieldFormat{shorthandwidth}{\mkbibbrackets{#1}} %源来自numeric.BBX +% \DeclareFieldFormat{labelnumberwidth}{\ttfamily\mkbibbrackets{#1}\hfill} +\DeclareFieldFormat{labelnumberwidth}{% +\ifcase\value{gbalignlabel}%右对齐,整个标签为右对齐 + \mkgbnumlabel{#1}% +\or%左对齐,整个标签为左对齐 + \mkgbnumlabel{#1}\hfill% +\or%中间对齐,比如:序号数字居于[]中间 + \hfil\mkgbnumlabel{\hfill#1\hfill}\hfil% +\fi} + +% +% 修改序号标签格式为以各条参文献为基础进行对齐的方式,即序号与条目内容间隔相等的方式。 +\def\setaligngbstyle{% +\def\blx@bibitem##1{% + \blx@ifdata{##1} + {\begingroup + \blx@getdata{##1}% + \blx@bibcheck + \iftoggle{blx@skipentry}{}{% + \blx@setdefaultrefcontext{##1}% + \global\let\blx@noitem\@empty + \blx@setoptions@type\abx@field@entrytype + \blx@setoptions@entry + \blx@thelabelnumber + \addtocounter{instcount}\@ne + \blx@initsep + \blx@namesep + \csuse{blx@item@\blx@theenv}\relax +% \blx@initsep %移动到上面去,恢复bibnamesep等的作用机制 +% \blx@namesep + \csuse{blx@hook@bibitem}% + \blx@execute + \blx@initunit + \blx@anchor + \blx@beglangbib + \bibsentence + \blx@pagetracker + \blx@driver\abx@field@entrytype + \blx@postpunct + \blx@endlangbib}% + \par\endgroup}%这里增加了一个\par + {}} +\newlength{\lengthid} +\newlength{\lengthlw} +\newcommand{\itemcmd}{% +\settowidth{\lengthid}{\mkgbnumlabel{\printfield{labelnumber}}} +\addtolength{\lengthid}{\biblabelsep} +\setlength{\lengthlw}{\textwidth} +\addtolength{\lengthlw}{-\lengthid} +\addvspace{\bibitemsep}%恢复\bibitemsep的作用 +%\parshape 2 0em \textwidth \lengthid \lengthlw +\hangindent\lengthid +\mkgbnumlabel{\printfield{labelnumber}}% +\hspace{\biblabelsep}} +% +% 简单的段落环境 +\defbibenvironment{bibliography} +{\begingroup\setlength{\parindent}{0em}} +{\endgroup} +{\itemcmd}} + +% +% 增加一个作者年制文献表格式的文献表输出环境。 +% 20210411,hzz,v1.0x +\def\setaligngbstyleay{% +\setlength{\bibhang}{1em} +\setlength{\bibitemindent}{-\bibhang} +\setlength{\bibitemsep}{4.5pt} +\defbibenvironment{bibliography} + {\list + {} + {\setlength{\leftmargin}{\bibhang}% + \setlength{\itemindent}{\bibitemindent}% + \setlength{\itemsep}{\bibitemsep}% + \setlength{\parsep}{\bibparsep}}} + {\endlist} + {\item} +} + +%===================================================================== +% 设置单元或块等的标点 +%===================================================================== +\renewrobustcmd*{\bibinithyphendelim}{\addhighpenspace}%用于处理姓名中名部分存在-的情况,比如ZHANG Yu-xin +\renewcommand*{\subtitlepunct}{\addcolon\addspace} %修改标题和其它标题信息间的标点,来源biblatex.def, +% +% 利用set实现的多语言文献不同语言间的分隔符 +% 20170411,双语之间用newline替换par,避免采用gb7714-2015的项对齐方式第二语言间分段导致没有缩进 +% +% 原理方法:set方法可以参考3.11.5 Entry Sets,4.11.1 Entry Sets +% 这里调整一下两种语言参考文献的间隔,源来自biblatex.def +\renewcommand*{\entrysetpunct}{\adddot\newline\nobreak} +\renewcommand*{\bibpagespunct}{\addcolon\addthinspace}%%页码引用格式的修改,修改为用冒号 +% 2021.08.19,增加出版地和出版社之间的标点,hzz +\newcommand{\publocpunct}{\addcolon\addspace}%出版项中:出版社地址后面的标点 +%\renewcommand{\relateddelim}{}%\par + +%===================================================================== +% 修改域的格式,重定义域的输出宏 +%===================================================================== +% +% 新增文献类型标识符的格式 +% []前的nobreak,从GB4.1节的例子看不应该加,所以去掉 +% 但因为考虑到cjk字符和[]之间可能添加空格,所以仍然加上 +% 而[]中间的内容,从4.6.2节的例子看也是可以分割的,因此内部的nobreak也可以去掉 +% +\DeclareFieldFormat{gbtypeflag}{% +\iftoggle{bbx:gbmedium}% +{\iftoggle{bbx:url}% + {\iffieldundef{url}%当存在url时,增加一个OL标识符 + {\nobreak\printtext{[}\nobreak#1\nobreak\printtext{\iffieldundef{medium}{}{\texttt{/}\thefield{medium}}]}}% + {\nobreak\printtext{[}\nobreak#1\nobreak\printtext{\texttt{/}OL]}}% + }% + {\ifentrytype{online}% + {\nobreak\printtext{[}\nobreak#1\nobreak\printtext{\texttt{/}OL]}}% + {\nobreak\printtext{[}\nobreak#1\nobreak\printtext{\iffieldundef{medium}{}{\texttt{/}\thefield{medium}}]}}% + }}% + {\nobreak\printtext{[}\nobreak#1\nobreak\printtext{]}}% +} + +% +% 新增用于报纸的文献类型标识符的格式 +% +\DeclareFieldFormat{gbtypeflagn}{%用于报纸newspaper +\iftoggle{bbx:gbmedium}% +{\iftoggle{bbx:url}% + {\iffieldundef{url}%当存在url时,增加一个OL标识符 + {\nobreak\printtext{[}\nobreak N\printtext{\iffieldundef{medium}{}{\texttt{/}\thefield{medium}}]}\nobreak}% + {\nobreak\printtext{[}\nobreak N\printtext{\texttt{/}OL]}\nobreak}% + }% + {\nobreak\printtext{[}\nobreak N\printtext{\iffieldundef{medium}{}{\texttt{/}\thefield{medium}}]}\nobreak}% +}{\nobreak\printtext{[}\nobreak N\printtext{]}\nobreak}% +} + +% +% 新增用于标准的文献类型标识符的格式 +% +\DeclareFieldFormat{gbtypeflags}{%用于标准standard +\iftoggle{bbx:gbmedium}% +{\iftoggle{bbx:url}% + {\iffieldundef{url}%当存在url时,增加一个OL标识符 + {\nobreak\printtext{[}\nobreak S\printtext{\iffieldundef{medium}{}{\texttt{/}\thefield{medium}}]}\nobreak}% + {\nobreak\printtext{[}\nobreak S\printtext{\texttt{/}OL]}\nobreak}% + }% + {\nobreak\printtext{[}\nobreak S\printtext{\iffieldundef{medium}{}{\texttt{/}\thefield{medium}}]}\nobreak}% +}{\nobreak\printtext{[}\nobreak S\printtext{]}\nobreak}% +} + +% +% 重设title等参考文献信息的输出格式 +% +% 原理方法:修改来自biblatex.def文件的原格式 +\newcommand{\bibtitlefont}{} +\newcommand{\bibauthorfont}{} +\newcommand{\bibpubfont}{} + +\DeclareFieldFormat{title}{#1\adddot\addthinspace} +\DeclareFieldFormat{journaltitle}{#1\isdot}%添加\isdot用于缩写名带点情况,将其转换为缩写点,便于标点的追踪 +\DeclareFieldFormat{issuetitle}{#1} +\DeclareFieldFormat{maintitle}{#1} +\DeclareFieldFormat{booktitle}{#1} +\DeclareFieldFormat%将期刊等文献的标题中原来带的引号去掉 + [article,patent,thesis,unpublished] + {title}{#1\adddot\addthinspace}%\mkbibquote{#1\isdot} +\DeclareFieldFormat%将期刊等文献的标题中原来带的引号去掉 + [inbook,incollection,inproceedings] + {title}{#1}%\nopunct\unspace +\DeclareFieldFormat{url}{\url{#1}} %%url相关输出,url域修改如本行,源来自biblatex.def +\def\UrlFont{\rmfamily}%设置url字体为roman字体%\ttfamily +%\urlstyle{rm} %使用这句也一样 +\setcounter{biburlnumpenalty}{100} %让url可以在数字后断行 +\setcounter{biburlucpenalty}{100} %让url可以在大写字母后断行 +\setcounter{biburllcpenalty}{100} %让url可以在小写字母后断行 +\DeclareFieldFormat{doi}{% + \rmfamily{DOI}\addcolon\space + \ifhyperref + {\href{https://doi.org/#1}{\nolinkurl{#1}}} + {\nolinkurl{#1}}} +% +% 标题的字母大小写格式修改 +% +% 注意:修改标题的字母大小写,不能用前面的title的格式而要用titlecase +% 因为titlecase is applied to the contents of the field directly,title is not +%\DeclareFieldFormat{titlecase}{\MakeCapital#1}%重设标题格式,将其修改为首字母大写 +\DeclareFieldFormat{titlecase}{\iftoggle{bbx:titlelink}{% +\iffieldundef{url}{\MakeCapital#1}{% +\href{\thefield{url}}{#1}}}{\MakeCapital#1}}%重设标题格式,将其修改为首字母大写 +\DeclareFieldFormat{pages}{#1}%去掉前面引导页码的pp.等字符,\mkpageprefix[bookpagination]{#1} +\DefineBibliographyExtras{english}{\renewcommand*{\bibrangedash}{-}}%将页码间隔符替换会英文的短横线 +\DefineBibliographyExtras{russian}{\renewcommand*{\bibrangedash}{-}}%将页码间隔符替换会英文的短横线 + +\def\execgbfdfmtstd{%恢复到标准样式的设置 +\DeclareFieldFormat{title}{\mkbibemph{##1}} +\DeclareFieldFormat + [article,inbook,incollection,inproceedings,patent,thesis,unpublished] + {title}{\mkbibquote{##1\isdot}} +\DeclareFieldFormat + [suppbook,suppcollection,suppperiodical] + {title}{##1} +\DeclareFieldFormat{journaltitle}{\mkbibemph{##1}} +\DeclareFieldFormat{issuetitle}{\mkbibemph{##1}} +\DeclareFieldFormat{maintitle}{\mkbibemph{##1}} +\DeclareFieldFormat{booktitle}{\mkbibemph{##1}} +\DeclareFieldFormat{url}{\mkbibacro{URL}\addcolon\space\url{##1}} +\DeclareFieldFormat{titlecase}{##1} +\DeclareFieldFormat{pages}{\mkpageprefix[bookpagination]{##1}} +} + +% +% 文献标题后的标点问题 +% v1.0k,20180405,为texlive2017以上版本中的beamer兼容性做的处理,Hu Zhenzhen +% +% 原理方法:如下代码处理texlive2017以上版本中,beamer中文献的标题后出现两个点的情况: +% texlive2017以上的beamer中对macro{title}做了patch,正常情况下不会出现两个点的情况,但由于 +% 之前为了处理texlive2015,2016下的title格式添加了adddot,导致出现两个点的情况,而且也影响 +% 析出文献的//符号的输出,因此再次对macro{title}做patch消除beamer中做apptocmd时添加的\newunitpunct +\ifboolexpr{% + test{\iftoggle{iftlfive}} + or + test{\iftoggle{iftlsix}} + }{}% + {%texlive 2017对应iftlseven以上版本 + \@ifclassloaded{beamer}{ + \DeclareFieldFormat{title}{#1}% + \DeclareFieldFormat[article,patent,thesis,unpublished]{title}{#1} + \AtBeginDocument{% + \patchcmd{\abx@macro@title}{\newunitpunct}{}{}{}}}{} + } + + +% +% 修改译者位置格式 +% v1.0w,20210401,hzz,增加对英文等其它语言译者的处理 +% +% 原理方法:修改来自biblatex.def文件的bytranslator+others宏的格式 +\renewbibmacro*{bytranslator+others}{\bibauthorfont% + \ifnameundef{translator} + {} + {\iffieldequalstr{usere}{chinese}{}{\usebibmacro{bytranslator+othersstrg}} + %\setunit{\addspace}% + \printnames[bytranslator]{translator}% + \clearname{translator}% + %从macro*{bytranslator+othersstrg}%中可以看到当地化字符串格式的引用前的代码处理 + %比如生成cotranslator等用于调用cotranslator所代表的当地化字符串 + \iffieldequalstr{usere}{chinese}{\usebibmacro{bytranslator+othersstrg}}{}%“译”的位置换到下面来,即放到译者后面。 + %\setunit{\addspace}% + \newunit}% + \usebibmacro{withothers}} + +\renewbibmacro*{bytranslator+othersstrg}{% + \def\abx@tempa{bytranslator}% + \ifnamesequal{translator}{commentator} + {\appto\abx@tempa{co}% + \clearname{commentator}} + {\ifnamesequal{translator}{annotator} + {\appto\abx@tempa{an}% + \clearname{annotator}} + {}}% + \ifnamesequal{translator}{introduction} + {\appto\abx@tempa{in}% + \clearname{introduction}} + {\ifnamesequal{translator}{foreword} + {\appto\abx@tempa{fo}% + \clearname{foreword}} + {\ifnamesequal{translator}{afterword} + {\appto\abx@tempa{af}% + \clearname{afterword}} + {}}}% +\iffieldequalstr{usere}{chinese}{\bibstring{bytranslatorcn}} + {\bibstring{\abx@tempa}}} + + +% +% 修改作者数量超过限定值,做省略时的处理格式 +% v1.0,20160701,hzz +% v1.0O,20190103,hzz,修改利用新定义的一个分隔符strandothersdelim +% v1.0w,20210401,hzz,针对其它语言的译者后的标点与中文不同做处理 +% 原理方法:判断作者或译者是否中文,若中文用字符等,否则用et al. 。 +% \printnames由start-stop控制项数,默认是1和maxnames/minnames +\newcommand{\aftertransdelim}{\addcomma\addthinspace} +\renewbibmacro*{name:andothers}{\bibauthorfont% + \ifboolexpr{ + test {\ifnumequal{\value{listcount}}{\value{liststop}}} + and + test \ifmorenames + }{\ifnumgreater{\value{liststop}}{1}%注意这里试图去区分姓名总数大于1的情况,当姓名总数大于1时,最后一个姓名后面先加入一个\finalandcomma + {\finalandcomma}%目前国标没有这样的区分要求,如果有需要也是可以这么去做的。 + {}% +\printdelim{andothersdelim}\printdelim{strandothersdelim}% +}{%当是译者的时候需要特殊处理:从7.2节看等,译前面加逗号,但从示例看等和译同时出现时,译前的逗号没有,比如: +%袁训来, 陈哲, 肖书海, 等. +%胡泳, 范海燕, 译. +%潘惠霞, 魏婧, 杨艳, 等译. +\ifcurrentname{translator}{\iffieldequalstr{usere}{chinese}{\aftertransdelim}{}}{}%为了实现上述第二个示例情况做的处理 +}} + + + +% 修改省略作者后的本地化字符串,比如et al. +% v1.0o,20190103,hzz +% +% 原理方法:默认情况下判断作者或译者是否中文,若中文用字符andotherscn=“等”,否则用andothers=“et al.”。 +% 非默认情况,根据选项信息,选择选择强制中文或英文 +% 首先设置全局的,然后设置文献表中的,这一等价于将所有的cite命令环境都设置过了 +% 而不用对每一个引用命令单独设置,比如cite,parancite,textcite都设置 +\DeclareDelimFormat{strandothersdelim}{% + \edef\userfieldabcde{userd}%这里使用\iffieldequalstr{labelnamesource}替代ifcurrentname因为标注中使用ifcurrentname无效 + \iffieldequalstr{labelnamesource}{translator}{\edef\userfieldabcde{usere}}{}% + \iffieldequalstr{labelnamesource}{editor}{\edef\userfieldabcde{userc}}{}% + \iffieldequalstr{labelnamesource}{author}{\edef\userfieldabcde{userf}}{}% + \iffieldequalstr{labelnamesource}{bookauthor}{\edef\userfieldabcde{userb}}{}% + \ifcase\value{gbcitelocalcase}% + \iffieldequalstr{\userfieldabcde}{chinese}{\ifbibstring{andothersincitecn}{\bibstring{andothersincitecn}}{\bibstring{andothers}}}{}%中文已经通过english本地化字符串定义 + \iffieldequalstr{\userfieldabcde}{korean}{\ifbibstring{andotherskr}{\bibstring{andotherskr}}{\bibstring{andothers}}}{}%韩语未定义,所以与bib中一致 + \iffieldequalstr{\userfieldabcde}{japanese}{\ifbibstring{andothersjp}{\bibstring{andothersjp}}{\bibstring{andothers}}}{}%日与同韩语 + \iffieldequalstr{\userfieldabcde}{english}{\ifbibstring{andothersincite}{\bibstring{andothersincite}}{\bibstring{andothers}}}{}%英语已定义 + \iffieldequalstr{\userfieldabcde}{french}{\bibstring{andothers}}{}%法语未定义,若要定义需要针对french本地化字符串定义 + \iffieldequalstr{\userfieldabcde}{russian}{\bibstring{andothers}}{}%俄语未定义,若要定义需要针对russian本地化字符串定义 + \or% + \bibstring{andothersincitecn}% + \or% + \bibstring{andothersincite}% + \fi} + + +\DeclareDelimFormat[bib,biblist]{strandothersdelim}{% + \edef\userfieldabcde{userd}% + \ifcurrentname{translator}{\edef\userfieldabcde{usere}}{}% + \ifcurrentname{editor}{\edef\userfieldabcde{userc}}{}% + \ifcurrentname{author}{\edef\userfieldabcde{userf}}{}% + \ifcurrentname{bookauthor}{\edef\userfieldabcde{userb}}{}% + \ifcase\value{gbbiblocalcase}% + \iffieldequalstr{\userfieldabcde}{chinese}{\bibstring{andotherscn}}{}% + \iffieldequalstr{\userfieldabcde}{korean}{\bibstring{andotherskr}}{}% + \iffieldequalstr{\userfieldabcde}{japanese}{\bibstring{andothersjp}}{}% + \iffieldequalstr{\userfieldabcde}{english}{\bibstring{andothers}}{}% + \iffieldequalstr{\userfieldabcde}{french}{\bibstring{andothers}}{}% + \iffieldequalstr{\userfieldabcde}{russian}{\bibstring{andothers}}{}% + \or% + \bibstring{andotherscn}% + \or% + \bibstring{andothers}% + \fi} + +% +% 修改最后一个作者前的字符串,比如 and +% v1.0o,20190103,hzz +% +% 原理方法:默认情况下判断作者或译者是否中文,若中文用字符andcn=“和”,否则用and=“and”。 +% 非默认情况,根据选项信息,选择选择强制中文或英文 +% 首先设置全局的,然后设置文献表中的,这一等价于将所有的cite命令环境都设置过了 +% 而不用对每一个引用命令单独设置,比如cite,parancite,textcite都设置 +\DeclareDelimFormat{finalnamedelim}{% + \ifnumgreater{\value{liststop}}{2}{\finalandcomma}{}% +% \addspace% + \edef\userfieldabcde{userd}% + \ifcurrentname{translator}{\edef\userfieldabcde{usere}}{}% + \ifcurrentname{editor}{\edef\userfieldabcde{userc}}{}% + \ifcurrentname{author}{\edef\userfieldabcde{userf}}{}% + \ifcurrentname{bookauthor}{\edef\userfieldabcde{userb}}{}% + \ifcase\value{gbcitelocalcase}% + \iffieldequalstr{\userfieldabcde}{chinese}{\bibstring{andincitecn}}{}% + \iffieldequalstr{\userfieldabcde}{korean}{\bibstring{andkr}}{}% + \iffieldequalstr{\userfieldabcde}{japanese}{\bibstring{andjp}}{}% + \iffieldequalstr{\userfieldabcde}{english}{\bibstring{andincite}}{}% + \iffieldequalstr{\userfieldabcde}{french}{\bibstring{and}}{}% + \iffieldequalstr{\userfieldabcde}{russian}{\bibstring{and}}{}% +%\space% + \or% + \bibstring{andincitecn}%\space% + \or% +\bibstring{andincite}% + \fi} + +\DeclareDelimFormat[bib,biblist]{finalnamedelim}{% + \ifnumgreater{\value{liststop}}{2}{\finalandcomma}{}% + \addspace% + \edef\userfieldabcde{userd}% + \ifcurrentname{translator}{\edef\userfieldabcde{usere}}{}% + \ifcurrentname{editor}{\edef\userfieldabcde{userc}}{}% + \ifcurrentname{author}{\edef\userfieldabcde{userf}}{}% + \ifcurrentname{bookauthor}{\edef\userfieldabcde{userb}}{}% + \ifcase\value{gbbiblocalcase}% + \iffieldequalstr{\userfieldabcde}{chinese}{\bibstring{andcn}}{}% + \iffieldequalstr{\userfieldabcde}{korean}{\bibstring{andkr}}{}% + \iffieldequalstr{\userfieldabcde}{japanese}{\bibstring{andjp}}{}% + \iffieldequalstr{\userfieldabcde}{english}{\bibstring{and}}{}% + \iffieldequalstr{\userfieldabcde}{french}{\bibstring{and}}{}% + \iffieldequalstr{\userfieldabcde}{russian}{\bibstring{and}}{}% +\space% + \or% + \bibstring{andcn}% + \or% + \bibstring{and}% + \fi} + + +% +% 重设title的输出 +% +% 20180425,v1.0k,为标题增加字体控制命令,Hu Zhenzhen +% 原理方法:将文献类型标识符输出出去,原输出来自biblatex.def文件 +% 利用toggle做标识符是否输出的判断 +\renewbibmacro*{title}{% + \ifboolexpr{% + test{\iffieldundef{title}}% + and + test{\iffieldundef{subtitle}}% + }% + {}% + {\printtext[title]{\bibtitlefont%增加字体控制命令 + \printfield[titlecase]{title}% + \ifboolexpr{test {\iffieldundef{subtitle}}}%这里增加了对子标题的判断,解决不判断多一个点的问题 + {}{\setunit{\subtitlepunct}% + \printfield[titlecase]{subtitle}}% + \iffieldundef{titleaddon}{}%判断一下titleaddon,否则直接加可能多一个空格 + {\setunit{\subtitlepunct}\printfield{titleaddon}}% + \iftoggle{bbx:gbtype}{% + \iffieldundef{note}{\printfield[gbtypeflag]{usera}}%在标题后直接给出文献标识字母,判断一下,是否是报纸和标准 + {\iffieldequalstr{note}{standard}{\printfield[gbtypeflags]{usera}}%判断是否为标准 + {\iffieldequalstr{note}{news}{\printfield[gbtypeflagn]{usera}}%判断是否为报纸 + {\printfield[gbtypeflag]{usera}}}%其它 + }}{}% + %\iffieldundef{booktitle}{\newunit}{}%当title是析出时,不要标点 + %\newunit +}% +}} + +% +% 作者信息的输出格式 +% +% 20180425,v1.0k,为作者增加字体控制命令,Hu Zhenzhen +% 20180603,v1.0l,增加使用nameformat域来选择姓名格式 +\DeclareNameFormat{namefmtselected}{% +\iffieldundef{namefmtid}{}% +{\defcounter{gbnamefmtcase}{\thefield{namefmtid}}}% +%\printtext{\thegbnamefmtcase}% +\ifcase\value{gbnamefmtcase}% + \ifgiveninits + {\usebibmacro{name:gbuppercase} + {\namepartfamily} + {\namepartgiveni} + {\namepartprefix} + {\namepartsuffix}} + {\usebibmacro{name:gbuppercase} + {\namepartfamily} + {\namepartgiven} + {\namepartprefix} + {\namepartsuffix}}% +\or + \ifgiveninits + {\usebibmacro{name:gblowercase} + {\namepartfamily} + {\namepartgiveni} + {\namepartprefix} + {\namepartsuffix}} + {\usebibmacro{name:gblowercase} + {\namepartfamily} + {\namepartgiven} + {\namepartprefix} + {\namepartsuffix}}% +\or + \ifgiveninits + {\usebibmacro{name:given-family} + {\namepartfamily} + {\namepartgiveni} + {\namepartprefix} + {\namepartsuffix}} + {\usebibmacro{name:given-family} + {\namepartfamily} + {\namepartgiven} + {\namepartprefix} + {\namepartsuffix}}% +\or + \ifgiveninits + {\usebibmacro{name:family-given} + {\namepartfamily} + {\namepartgiveni} + {\namepartprefix} + {\namepartsuffix}} + {\usebibmacro{name:family-given} + {\namepartfamily} + {\namepartgiven} + {\namepartprefix} + {\namepartsuffix}}% +\or +\usebibmacro{name:gbpinyin} + {\namepartfamily} + {\namepartgiven} + {\namepartprefix} + {\namepartsuffix}% +\or + \ifnumequal{\value{listcount}}{1} + {\ifgiveninits + {\usebibmacro{name:family-given} + {\namepartfamily} + {\namepartgiveni} + {\namepartprefix} + {\namepartsuffix}} + {\usebibmacro{name:family-given} + {\namepartfamily} + {\namepartgiven} + {\namepartprefix} + {\namepartsuffix}}% + \ifboolexpe{% + test {\ifdefvoid\namepartgiven} + and + test {\ifdefvoid\namepartprefix}} + {} + {\usebibmacro{name:revsdelim}}} + {\ifgiveninits + {\usebibmacro{name:given-family} + {\namepartfamily} + {\namepartgiveni} + {\namepartprefix} + {\namepartsuffix}} + {\usebibmacro{name:given-family} + {\namepartfamily} + {\namepartgiven} + {\namepartprefix} + {\namepartsuffix}}}% +\or +\usebibmacro{name:gbquanpin} + {\namepartfamily} + {\namepartgiven} + {\namepartprefix} + {\namepartsuffix}% +\fi + \usebibmacro{name:andothers}} + +\DeclareNameAlias{default}{namefmtselected}%姓名的默认格式采用可选的模式 +\DeclareNameAlias{sortname}{default}% Used in the bibliography %family-given/given-family +\DeclareNameAlias{citename}{default}% Default used by \citename + +\DeclareDelimFormat[bib,biblist]{andothersdelim}{\addcomma\addspace} +%\DeclareDelimFormat[textcite]{andothersdelim}{\addspace}% + +%GB/T 7714-2015 风格,全部大写 +\def\gbcaselocalset{\renewrobustcmd*{\bibinitperiod}{}%将名字简写后的点去掉 +\renewcommand*{\revsdnamepunct}{}%%%来源biblatex.def +} +\newbibmacro*{name:gbuppercase}[4]{\bibauthorfont% + \gbcaselocalset% + \ifuseprefix% + {\usebibmacro{name:delim}{#3#1}% + \usebibmacro{name:hook}{#3#1}% + \ifdefvoid{#3}{}{% + \ifcapital% + {\mkbibnameprefix{\MakeCapital{#3}}\isdot}% + {\mkbibnameprefix{#3}\isdot}% + \ifprefchar{}{\bibnamedelimc}}% + \ifdefvoid{#2}{\mkbibnamefamily{\MakeCapital{#1}}}{\mkbibnamefamily{\MakeUppercase{#1}}}\isdot% + \ifdefvoid{#2}{}{\revsdnamepunct\bibnamedelimd\mkbibnamegiven{\MakeUppercase{#2}}\isdot}%\MakeCapital + \ifdefvoid{#4}{}{\addcomma\bibnamedelimd\mkbibnamesuffix{#4}\isdot}}%后缀前加逗号 + {\usebibmacro{name:delim}{#1}% + \usebibmacro{name:hook}{#1}% + \ifdefvoid{#2}{\mkbibnamefamily{\MakeCapital{#1}}}{\mkbibnamefamily{\MakeUppercase{#1}}}\isdot% + \ifboolexpe{% + test {\ifdefvoid{#2}} + and + test {\ifdefvoid{#3}}} + {}{\revsdnamepunct}% + \ifdefvoid{#2}{}{\bibnamedelimd\mkbibnamegiven{\MakeUppercase{#2}}\isdot}%\MakeCapital + \ifdefvoid{#3}{}{\bibnamedelimd\mkbibnameprefix{#3}\isdot}% + \ifdefvoid{#4}{}{\addcomma\bibnamedelimd\mkbibnamesuffix{#4}\isdot}}%%后缀前加逗号 +} + +%GB/T 7714-2015 风格,大小写不变,根据bib文件内输入原样输出 +\newbibmacro*{name:gblowercase}[4]{\bibauthorfont% + \gbcaselocalset% + \ifuseprefix + {\usebibmacro{name:delim}{#3#1}% + \usebibmacro{name:hook}{#3#1}% + \ifdefvoid{#3}{}{% + \ifcapital + {\mkbibnameprefix{\MakeCapital{#3}}\isdot} + {\mkbibnameprefix{#3}\isdot}% + \ifprefchar{}{\bibnamedelimc}}% + \ifdefvoid{#2}{\mkbibnamefamily{\MakeCapital{#1}}}{\mkbibnamefamily{{#1}}}\isdot% + \ifdefvoid{#2}{}{\revsdnamepunct\bibnamedelimd\mkbibnamegiven{{#2}}\isdot}%\MakeCapital + \ifdefvoid{#4}{}{\addcomma\bibnamedelimd\mkbibnamesuffix{#4}\isdot}}%后缀前加逗号 + {\usebibmacro{name:delim}{#1}% + \usebibmacro{name:hook}{#1}% + \ifdefvoid{#2}{\mkbibnamefamily{\MakeCapital{#1}}}{\mkbibnamefamily{{#1}}}\isdot% + \ifboolexpe{% + test {\ifdefvoid{#2}} + and + test {\ifdefvoid{#3}}} + {}{\revsdnamepunct}% + \ifdefvoid{#2}{}{\bibnamedelimd\mkbibnamegiven{{#2}}\isdot}%\MakeCapital + \ifdefvoid{#3}{}{\bibnamedelimd\mkbibnameprefix{#3}\isdot} + \ifdefvoid{#4}{}{\addcomma\bibnamedelimd\mkbibnamesuffix{#4}\isdot}}%%后缀前加逗号 +} + +%中文常见风格,汉语拼音全拼模式 +\def\gbpinyinlocalset{\renewrobustcmd*{\bibinitperiod}{}%将名字简写后的点去掉,%来源biblatex2.STY +\renewcommand*{\revsdnamepunct}{}%%来源biblatex.def +\renewrobustcmd*{\bibnamedelima}{\mbox{-}}} +\newbibmacro*{name:gbpinyin}[4]{\bibauthorfont% +\gbpinyinlocalset% + \ifuseprefix + {\usebibmacro{name:delim}{#3#1}% + \usebibmacro{name:hook}{#3#1}% + \ifdefvoid{#3}{}{% + \ifcapital + {\mkbibnameprefix{\MakeCapital{#3}}\isdot} + {\mkbibnameprefix{#3}\isdot}% + \ifprefchar{}{\bibnamedelimc}}% + \ifdefvoid{#2}{\mkbibnamefamily{\MakeCapital{#1}}}{\mkbibnamefamily{\MakeUppercase{#1}}}\isdot% + \ifdefvoid{#2}{}{\revsdnamepunct\bibnamedelimd\mkbibnamegiven{\MakeSentenceCase{#2}}\isdot}%\MakeCapital + \ifdefvoid{#4}{}{\bibnamedelimd\mkbibnamesuffix{#4}\isdot}} + {\usebibmacro{name:delim}{#1}% + \usebibmacro{name:hook}{#1}% + \ifdefvoid{#2}{\mkbibnamefamily{\MakeCapital{#1}}}{\mkbibnamefamily{\MakeUppercase{#1}}}\isdot% + \ifboolexpe{% + test {\ifdefvoid{#2}} + and + test {\ifdefvoid{#3}}} + {} + {\revsdnamepunct}% + \ifdefvoid{#2}{}{\bibnamedelimd\mkbibnamegiven{\MakeCapital{#2}}\isdot}%\MakeCapital + \ifdefvoid{#3}{}{\bibnamedelimd\mkbibnameprefix{#3}\isdot} + \ifdefvoid{#4}{}{\bibnamedelimd\mkbibnamesuffix{#4}\isdot}}% +} +%中文常见风格,汉语拼音全拼模式 +\def\gbquanpinlocalset{\renewrobustcmd*{\bibinitperiod}{}%将名字简写后的点去掉,%来源biblatex2.STY +\renewcommand*{\revsdnamepunct}{}%%来源biblatex.def +\renewrobustcmd*{\bibnamedelima}{}} +\newbibmacro*{name:gbquanpin}[4]{\bibauthorfont% +\gbquanpinlocalset% + \ifuseprefix + {\usebibmacro{name:delim}{#3#1}% + \usebibmacro{name:hook}{#3#1}% + \ifdefvoid{#3}{}{% + \ifcapital + {\mkbibnameprefix{\MakeCapital{#3}}\isdot} + {\mkbibnameprefix{#3}\isdot}% + \ifprefchar{}{\bibnamedelimc}}% + \ifdefvoid{#2}{\mkbibnamefamily{\MakeCapital{#1}}}{\mkbibnamefamily{\MakeCapital{#1}}}\isdot% + \ifdefvoid{#2}{}{\revsdnamepunct\bibnamedelimd\mkbibnamegiven{\MakeSentenceCase{#2}}\isdot}%\MakeCapital + \ifdefvoid{#4}{}{\bibnamedelimd\mkbibnamesuffix{#4}\isdot}} + {\usebibmacro{name:delim}{#1}% + \usebibmacro{name:hook}{#1}% + \ifdefvoid{#2}{\mkbibnamefamily{\MakeCapital{#1}}}{\mkbibnamefamily{\MakeCapital{#1}}}\isdot% + \ifboolexpe{% + test {\ifdefvoid{#2}} + and + test {\ifdefvoid{#3}}} + {} + {\revsdnamepunct}% + \ifdefvoid{#2}{}{\bibnamedelimd\mkbibnamegiven{\MakeCapital{#2}}\isdot}%\MakeCapital + \ifdefvoid{#3}{}{\bibnamedelimd\mkbibnameprefix{#3}\isdot} + \ifdefvoid{#4}{}{\bibnamedelimd\mkbibnamesuffix{#4}\isdot}}% +} + + +\@ifpackagelater{biblatex}{2016/03/27}%biblatex<3.2版的情况 + {}{ + %GB/T 7714-2015 风格,全部大写 + \renewbibmacro*{name:gbuppercase}[4]{\bibauthorfont% + \gbcaselocalset% + \ifuseprefix + {\usebibmacro{name:delim}{#3#1}% + \usebibmacro{name:hook}{#3#1}% + \ifblank{#3}{}{% + \ifcapital + {\mkbibnameprefix{\MakeCapital{#3}}\isdot} + {\mkbibnameprefix{#3}\isdot}% + \ifpunctmark{'}{}{\bibnamedelimc}}% + %\mkbibnamelast{#1}\isdot + \ifblank{#2}{\MakeCapital#1}{\mkbibnamelast{\MakeUppercase{#1}}}\isdot%\MakeUppercase %\mkbibnamelast{\MakeUppercase{#1}} %\MakeSentenceCase + %注意上一句\MakeCapital后面如果再跟一个{}包含#1,则没有效果,可能是包在里面少了一层展开 + %因为机构名通常包括在{}内,所以要多展开一次才行,所以这里去掉#1外面的{} + %\mkbibnamelast{\MakeUppercase{#1}}\isdot + %\ifblank{#4}{}{\bibnamedelimd\mkbibnameaffix{#4}\isdot}%这句放到后面 + \ifblank{#2}{}{\revsdnamepunct\bibnamedelimd\mkbibnamefirst{\MakeUppercase{#2}}\isdot}% + \ifblank{#4}{}{\addcomma\addspace\bibnamedelimd\mkbibnameaffix{#4}\isdot}}%后缀前加逗号 + {\usebibmacro{name:delim}{#1}% + \usebibmacro{name:hook}{#1}% + %\mkbibnamelast{#1}\isdot %3.9.1 Generic Commands and Hooks,对姓重新处理,如下句: %\mkbibnamelast{\MakeUppercase{#1}} + \ifblank{#2}{\MakeCapital#1}{\mkbibnamelast{\MakeUppercase{#1}}}\isdot %大写,参考4.6.4 Miscellaneous Commands,\MakeUppercase %\MakeSentenceCase + %\mkbibnamelast{\MakeUppercase{#1}}\isdot + %\ifblank{#4}{}{\bibnamedelimd\mkbibnameaffix{#4}\isdot}%这句放到后面 + \ifblank{#2#3}{}{\revsdnamepunct}% + \ifblank{#2}{}{\bibnamedelimd\mkbibnamefirst{\MakeUppercase{#2}}\isdot}% + \ifblank{#3}{}{\bibnamedelimd\mkbibnameprefix{#3}\isdot}% + \addcomma\addspace% + \ifblank{#4}{}{\addcomma\addspace\bibnamedelimd\mkbibnameaffix{#4}\isdot}%%后缀前加逗号 + }% + } + + %GB/T 7714-2015 风格,大小写不变,根据bib文件内输入原样输出 + \renewbibmacro*{name:gblowercase}[4]{\bibauthorfont% + \gbcaselocalset% + \ifuseprefix + {\usebibmacro{name:delim}{#3#1}% + \usebibmacro{name:hook}{#3#1}% + \ifblank{#3}{}{% + \ifcapital + {\mkbibnameprefix{\MakeCapital{#3}}\isdot} + {\mkbibnameprefix{#3}\isdot}% + \ifpunctmark{'}{}{\bibnamedelimc}}% + \ifblank{#2}{\MakeCapital#1}{\mkbibnamelast{{#1}}}\isdot%\MakeUppercase %\mkbibnamelast{\MakeUppercase{#1}} %\MakeSentenceCase + \ifblank{#2}{}{\revsdnamepunct\bibnamedelimd\mkbibnamefirst{{#2}}\isdot}% + \ifblank{#4}{}{\addcomma\addspace\bibnamedelimd\mkbibnameaffix{#4}\isdot}}%后缀前加逗号 + {\usebibmacro{name:delim}{#1}% + \usebibmacro{name:hook}{#1}% + \ifblank{#2}{\MakeCapital#1}{\mkbibnamelast{{#1}}}\isdot %大写,参考4.6.4 Miscellaneous Commands,\MakeUppercase %\MakeSentenceCase + \ifblank{#2#3}{}{\revsdnamepunct}% + \ifblank{#2}{}{\bibnamedelimd\mkbibnamefirst{{#2}}\isdot}% + \ifblank{#3}{}{\bibnamedelimd\mkbibnameprefix{#3}\isdot}% + \addcomma\addspace% + \ifblank{#4}{}{\addcomma\addspace\bibnamedelimd\mkbibnameaffix{#4}\isdot}%%后缀前加逗号 + }% + } + + %中文常见风格,汉语拼音全拼模式 + \renewbibmacro*{name:gbpinyin}[4]{\bibauthorfont% + \gbpinyinlocalset% + \ifuseprefix + {\usebibmacro{name:delim}{#3#1}% + \usebibmacro{name:hook}{#3#1}% + \ifblank{#3}{}{% + \ifcapital + {\mkbibnameprefix{\MakeCapital{#3}}\isdot} + {\mkbibnameprefix{#3}\isdot}% + \ifpunctmark{'}{}{\bibnamedelimc}}% + \ifblank{#2}{\MakeCapital#1}{\mkbibnamelast{\MakeUppercase{#1}}}\isdot%\MakeUppercase %\mkbibnamelast{\MakeUppercase{#1}} %\MakeSentenceCase + \ifblank{#2}{}{\revsdnamepunct\bibnamedelimd\mkbibnamefirst{\MakeSentenceCase{#2}}\isdot}% + \ifblank{#4}{}{\addcomma\addspace\bibnamedelimd\mkbibnameaffix{#4}\isdot}} + {\usebibmacro{name:delim}{#1}% + \usebibmacro{name:hook}{#1}% + \ifblank{#2}{\MakeCapital#1}{\mkbibnamelast{\MakeUppercase{#1}}}\isdot %大写,参考4.6.4 Miscellaneous Commands,\MakeUppercase %\MakeSentenceCase + \ifblank{#2#3}{}{\revsdnamepunct}% + \ifblank{#2}{}{\bibnamedelimd\mkbibnamefirst{\MakeUppercase{#2}}\isdot}% + \ifblank{#3}{}{\bibnamedelimd\mkbibnameprefix{#3}\isdot}% + \addcomma\addspace% + \ifblank{#4}{}{\addcomma\addspace\bibnamedelimd\mkbibnameaffix{#4}\isdot}% + }% + } + %中文常见风格,汉语拼音全拼模式 + \renewbibmacro*{name:gbquanpin}[4]{\bibauthorfont% + \gbquanpinlocalset% + \ifuseprefix + {\usebibmacro{name:delim}{#3#1}% + \usebibmacro{name:hook}{#3#1}% + \ifblank{#3}{}{% + \ifcapital + {\mkbibnameprefix{\MakeCapital{#3}}\isdot} + {\mkbibnameprefix{#3}\isdot}% + \ifpunctmark{'}{}{\bibnamedelimc}}% + \ifblank{#2}{\MakeCapital#1}{\mkbibnamelast{\MakeCapital{#1}}}\isdot%\MakeUppercase %\mkbibnamelast{\MakeUppercase{#1}} %\MakeSentenceCase + \ifblank{#2}{}{\revsdnamepunct\bibnamedelimd\mkbibnamefirst{\MakeSentenceCase{#2}}\isdot}% + \ifblank{#4}{}{\addcomma\addspace\bibnamedelimd\mkbibnameaffix{#4}\isdot}} + {\usebibmacro{name:delim}{#1}% + \usebibmacro{name:hook}{#1}% + \ifblank{#2}{\MakeCapital#1}{\mkbibnamelast{\MakeCapital{#1}}}\isdot %大写,参考4.6.4 Miscellaneous Commands,\MakeUppercase %\MakeSentenceCase + \ifblank{#2#3}{}{\revsdnamepunct}% + \ifblank{#2}{}{\bibnamedelimd\mkbibnamefirst{\MakeUppercase{#2}}\isdot}% + \ifblank{#3}{}{\bibnamedelimd\mkbibnameprefix{#3}\isdot}% + \addcomma\addspace% + \ifblank{#4}{}{\addcomma\addspace\bibnamedelimd\mkbibnameaffix{#4}\isdot}% + }% + } + + %%biblatex<3.2版的情况,姓名的处理格式带参数 + \DeclareNameFormat{namefmtselected}{% + \iffieldundef{namefmtid}{}% + {\defcounter{gbnamefmtcase}{\thefield{namefmtid}}}% + \ifcase\value{gbnamefmtcase}% + \iffirstinits + {\usebibmacro{name:gbuppercase}{#1}{#4}{#5}{#7}} + {\usebibmacro{name:gbuppercase}{#1}{#3}{#5}{#7}}% + \or + \iffirstinits + {\usebibmacro{name:gblowercase}{#1}{#4}{#5}{#7}} + {\usebibmacro{name:gblowercase}{#1}{#3}{#5}{#7}}% + \or + \iffirstinits + {\usebibmacro{name:last-first}{#1}{#4}{#5}{#7}} + {\usebibmacro{name:last-first}{#1}{#3}{#5}{#7}}% + \ifblank{#3#5} + {} + {\usebibmacro{name:revsdelim}}% + \or + \iffirstinits + {\usebibmacro{name:first-last}{#1}{#4}{#5}{#7}} + {\usebibmacro{name:first-last}{#1}{#3}{#5}{#7}}% + \or + \usebibmacro{name:gbpinyin}{#1}{#3}{#5}{#7}% + \or + \ifnumequal{\value{listcount}}{1} + {\iffirstinits + {\usebibmacro{name:last-first}{#1}{#4}{#5}{#7}} + {\usebibmacro{name:last-first}{#1}{#3}{#5}{#7}}% + \ifblank{#3#5} + {} + {\usebibmacro{name:revsdelim}}} + {\iffirstinits + {\usebibmacro{name:first-last}{#1}{#4}{#5}{#7}} + {\usebibmacro{name:first-last}{#1}{#3}{#5}{#7}}}% + \or + \usebibmacro{name:gbquanpin}{#1}{#3}{#5}{#7}% + \fi + \usebibmacro{name:andothers}} +} + +% +% url和url日期格式 +% +\renewbibmacro*{url+urldate}{% + %\usebibmacro{url}%%更换url的位置,放到下面 + \iffieldundef{urlyear}% + {}{%\setunit*{\addspace}% + \usebibmacro{urldate}}% + \setunit{\addperiod\addspace}% + \usebibmacro{url}} +\renewbibmacro*{url}{\printfield{url}} + + + + +% +% 日期信息的输出格式,针对biblatex<3.7版本 +% +\defversion{3.4}{date}{ + \renewbibmacro*{urldate}{% + \addthinspace\printtext{[}\printfield{urlyear}% + \iffieldundef{urlmonth}{}{\bibrangedash\printfield{urlmonth}}% + \iffieldundef{urlday}{}{\bibrangedash\printfield{urlday}}\printtext{]}} + + \newbibmacro*{newsdate}{%%新增加一个公告日期,公开日期或新闻日期 + \iffieldundef{year}{}{\printfield{year}% + \iffieldundef{month}{}{\bibrangedash\printtext{\thefield{month}}% + \iffieldundef{day}{}{\bibrangedash\printfield{day}}}}% + } + + \newbibmacro*{modifydate}{%新增加一个带括号的日期,用于表示电子资源的更新和修改日期,而公告日期则按日期格式 + \ifboolexpr{% + test{\iffieldundef{day}} and test{\iffieldundef{endday}} and test{\iffieldundef{eventday}}% + }% + {}%更新或修改日期通常有day信息 + {\iffieldequalstr{year}{}{%替换\iffieldundef{year},因为year总是存在,但为空 + \iffieldundef{endyear}{% + \iffieldundef{eventyear}{}{\printtext{\mkbibparens{\printtext{\printfield{eventyear}}% + \iffieldundef{eventmonth}{}{\bibrangedash\thefield{eventmonth}}% + \iffieldundef{eventday}{}{\bibrangedash\printfield{eventday}}}}% + }% + }{% + \iffieldundef{endyear}{}{\printtext{\mkbibparens{\printtext{\printfield{endyear}}% + \iffieldundef{endmonth}{}{\bibrangedash\thefield{endmonth}}% + \iffieldundef{endday}{}{\bibrangedash\printfield{endday}}}}% + }% + }% + }% + {% + \iffieldundef{year}{}{\printtext{\mkbibparens{\printtext{\printfield{year}}% + \iffieldundef{month}{}{\bibrangedash\thefield{month}}% + \iffieldundef{day}{}{\bibrangedash\printfield{day}}}}% + }% + }% + }}% +} + +% +% 日期信息的输出格式,针对3.9>=biblatex>=3.7版本 +% +\defversion{3.7}{date}{ + \DeclareFieldFormat{urldate}{##1} + \renewbibmacro*{urldate}{% + \addthinspace\printtext{[}\printurldate\printtext{]}}%能用高层命令+选项尽量用命令(比如这里的\printurldate),而不用\blx@edtfdate这种更底层的命令 + + % + % 专利的公告日期、或报纸的日期的输出宏 + % 20160701,v1.0,新增加 + % 20180405,v1.0k,为biblatexv3.7-3.9版本,出现多出点bug做处理,Hu Zhenzhen + % + % 原理方法:加上printtext避免破坏异步标点机制 + % + \newbibmacro*{newsdate}{% + \printtext{\blx@edtfdate{}{}}% + } + + \newbibmacro*{modifydate}{%新增加一个带括号的日期,用于表示电子资源的更新和修改日期,而公告日期则按日期格式 + \ifboolexpr{% + test{\iffieldundef{day}} and test{\iffieldundef{endday}} and test{\iffieldundef{eventday}}% + }% + {}%更新或修改日期通常有day信息 + {\iffieldundef{year}{% + \iffieldundef{endyear}{\iffieldundef{eventyear}{}{\printtext{(}\printeventdate\printtext{)}}}% + {\printtext{(}\printenddate\printtext{)}}% + }{\iffieldequalstr{year}{}{%因为year存在,但为空 + }{\printtext{(}\blx@edtfdate{}{}\printtext{)}}% + }% + }}% +} + +% +% 日期信息的输出格式,针对biblatex>=3.10版本 +% +\defversion{3.10}{date}{ + \DeclareFieldFormat{urldate}{##1} + \renewbibmacro*{urldate}{% + \addthinspace\printtext{[}\printurldate\printtext{]}}%能用高层命令+选项尽量用命令(比如这里的\printurldate),而不用\blx@edtfdate这种更底层的命令 + + % + % 专利的公告日期、或报纸的日期的输出宏 + % 20160701,v1.0,新增加 + % 20180405,为biblatexv3.10版本,出现多出点bug做处理,Hu Zhenzhen + % + % 原理方法:加上printtext避免破坏异步标点机制 + % 本可以用\printdate,但由于date选项设置为year,所以仅会给出年份 + % 所以无法再用选项设置的方法,印象需要用底层的命令 + % 这里可以用\blx@isodate,但用\blx@gbdate试图避免版本判断 + \newbibmacro*{newsdate}{%% + \printtext{\blx@gbdate{}{}}%%\blx@isodate{}{}% + } + + % + \newbibmacro*{modifydate}{%新增加一个带括号的日期,用于表示电子资源的更新和修改日期,而公告日期则按日期格式 + \ifboolexpr{% + test{\iffieldundef{day}} and test{\iffieldundef{endday}} and test{\iffieldundef{eventday}}% + }% + {}%更新或修改日期通常有day信息 + {\iffieldundef{year}{% + \iffieldundef{endyear}{\iffieldundef{eventyear}{}{\printtext{(}\printeventdate\printtext{)}}}% + {\printtext{(}\printenddate\printtext{)}}% + }{\iffieldequalstr{year}{}{%因为year存在,但为空 + }{\printtext{(}\blx@gbdate{}{}\printtext{)}}% + }% + }}% +} + +% +% biblatex>v3.8版利用related实现双语文献的处理 +% +\defversion{3.8}{dblang}{ + %为了实现v3.8以上版本的双语文献,采用related的方法代替set方法,因为set方法已经无法实现了, + %因为set不再复制其第一个成员的信息。于是定义一个命令,用于动态的修改数据,即添加related域的信息 + %其中使用了\DeclareStyleSourcemap,但由于其只能出现在导言区中,因此\defdoublelangentry命令也只能出现在导言区中 + \newcommand{\defdoublelangentry}[2]{% + \edef\entrykeya{##1} + \edef\entrykeyb{##2} + \DeclareStyleSourcemap{ + \maps[datatype=bibtex]{ + \map{ + \step[fieldsource=entrykey, match=\entrykeya, final] + \step[fieldset=related, fieldvalue=\entrykeyb] + } + } + } + } +} + +% +% 关联文献间的分隔符 +% +\renewcommand{\relateddelim}{\adddot\newline\nobreak}%\par,而作者年样式不需要修改,因为没有项对齐的标签问题 + +% +% 关联文献的输出格式,针对3.9>=biblatex>=3.7版本 +% +% 原理方法:因为related宏中带有##了,所以无法封装到defversion中了。所以直接做判断 +% 下面这一段主要针对v3.8-3.10,因为我提问后,biblatex作者为3.11版增加了一个钩子控制relatedblock前的分隔符。 +\ifboolexpr{ +test{\iftoggle{iftleight}} +or +test{\iftoggle{iftlnine}} +}{\renewbibmacro*{related}{%standard.bbx + \ifboolexpr{ test {\iffieldundef{related}} or test {\ifrelatedloop} } + {} + {\usebibmacro{begrelated}% + \def\bbx@tempa{}% + \setcounter{bbx:relatedtotal}{0}% + \def\do##1{% + \entrydata{##1}{% + \ifrelatedloop + {} + {\stepcounter{bbx:relatedtotal}% + \gappto{\bbx@tempa}{##1,}}}}% + \docsvfield{related}% + \restorefield{related}{\bbx@tempa}% + \ifnumgreater{\value{bbx:relatedtotal}}{0} + {\listcsxadd{bbx:relatedloop}{\strfield{entrykey}}% + \iffieldundef{clonesourcekey} + {} + {\listcsxadd{bbx:relatedloop}{\strfield{clonesourcekey}}}% + \setcounter{bbx:relatedcount}{0}% + \def\do{% + \stepcounter{bbx:relatedcount}% + \ifnumgreater{\value{bbx:relatedcount}}{0}%这里从1改为0 + {\ifcsundef{relateddelim\strfield{relatedtype}} + {\printtext{\relateddelim}} + {\printtext{\csuse{relateddelim\strfield{relatedtype}}}}} + {}}% + \ifbibmacroundef{related:\strfield{relatedtype}} + {\appto{\do}{\usebibmacro{related:default}}} + {\appto{\do}{\usebibmacro*{related:\strfield{relatedtype}}}}% + \iffieldformatundef{related:\strfield{relatedtype}} + {\def\bbx@tempa{related}} + {\def\bbx@tempa{related:\strfield{relatedtype}}}% + \iffieldformatundef{relatedstring:\strfield{relatedtype}} + {\def\bbx@tempb{relatedstring:default}} + {\def\bbx@tempb{relatedstring:\strfield{relatedtype}}}% + \printtext[\bbx@tempa]{% + \usebibmacro{begrelatedloop}% + \iffieldundef{relatedstring} + {\ifboolexpr{ + test {\ifnumgreater{\value{bbx:relatedtotal}}{1}} + and + test {\ifbibxstring{\thefield{relatedtype}s}} + } + {\printtext[\bbx@tempb]{% + \bibstring[\mkrelatedstring]{\thefield{relatedtype}s}}} + {\iffieldbibstring{relatedtype} + {\printtext[\bbx@tempb]{% + \bibstring[\mkrelatedstring]{\thefield{relatedtype}}}} + {}}} + {\iffieldbibstring{relatedstring} + {\printtext[\bbx@tempb]{% + \bibstring[\mkrelatedstring]{\thefield{relatedstring}}}} + {\printfield[\bbx@tempb]{relatedstring}}}% + \docsvfield{related}% + \usebibmacro{endrelatedloop}}}% + {}% + \usebibmacro{endrelated}}} +}{} + +% +% 关联文献块前的分隔符,针对biblatex>3.11 +% +% 原理方法:因为增加了begrelateddelim钩子,所以不需要重定义related输出宏 +\defversion{3.11}{related}{ +\renewcommand{\begrelateddelim}{\adddot\newline\nobreak} +} + +\iftoggle{iftlfive}{\switchversion{3.4}{date}}{}%biblatex<=3.2 +\iftoggle{iftlsix}{\switchversion{3.4}{date}}{}%3.3<=biblatex<=3.6 +\iftoggle{iftlseven}{\switchversion{3.7}{date}}{}%biblatex=3.7 +\iftoggle{iftleight}{\switchversion{3.7}{date}\switchversion{3.8}{dblang}}{}%3.8<=biblatex<=3.9 +\iftoggle{iftlnine}{\switchversion{3.10}{date}\switchversion{3.8}{dblang}}{}%biblatex=3.10 +\iftoggle{iftlatest}{\switchversion{3.10}{date}\switchversion{3.8}{dblang}\switchversion{3.11}{related}}{}%biblatex最新3.11 + +% +% 调整doi+eprint+url格式 +% 2016.07.01 byhzz +% 2019.05.01 byhzz 在eprint前增加一个空格 +% 原理方法:源来自standard.bbx,因为页码后面直接跟引用日期,没有标点所以去掉其中的标点。 +\renewbibmacro*{doi+eprint+url}{% +% \iftoggle{bbx:doi}%把doi的位置放到url后面 +% {\printfield{doi}} +% {}% + %\newunit\newblock + \iftoggle{bbx:eprint} + {\iffieldundef{eprint}{}{\newunit\usebibmacro{eprint}}} + {}% + %\newunit\newblock + \iftoggle{bbx:url} + {\usebibmacro{url+urldate}} + {} + \newunit\newblock + \iftoggle{bbx:doi} + {\printfield{doi}} + {}} + +% +% 调整页码的格式,即chapter+pages格式 +% +\renewbibmacro*{chapter+pages}{% +\iftoggle{bbx:gbstrict}{}{% + \printfield{chapter}}% + \iffieldundef{pages}{}{%这里增加一个判断,当没有页码时就不输出 + \setunit{\bibpagespunct}% + \printfield{pages}}% + %\newunit %这里的标点去掉 +} + +% +% 当location等出版项超过maxitem缩减后不再输出etal +% +\DeclareListFormat{location}{% + \usebibmacro{list:delim}{#1}% + #1\isdot} +\DeclareListAlias{institution}{location} +\DeclareListAlias{publisher}{location} + +% 新增一个样式用于输出连续出版物的地址,单位,时间, +% 用于periodical连续出版物的出版社和地址的处理 +% +% v1.0k,20180425,为出版信息增加字体控制命令,hzz +% %类似\newbibmacro*{publisher+location+date} +\newbibmacro*{location+institution+date}{\bibpubfont% +\iftoggle{bbx:gbpub}% +{\testCJKfirst{userd}% +\ifboolexpr{% +test {\iflistundef{location}} and test {\iflistundef{institution}}% +}{\iftoggle{ifCJKforgbt}{\printtext{[\str@noaddress}\space :\space\str@nopublisher]}% +{\printtext{[S.l.\space :\space s.n.\adddot]}}% +}{% +\iflistundef{location}{\iftoggle{ifCJKforgbt}{\printtext{[\str@noaddress]}}{\printtext{[S.l.\adddot]}}}% + {\printlist{location}}% +\publocpunct% +\iflistundef{institution}{% +\iftoggle{ifCJKforgbt}{\printtext{[\str@nopublisher]}}{\printtext{\mkbibbrackets{s.n.}}}}% +{\printlist{institution}}}% +\setunit{\addcomma\addspace}% + %\usebibmacro{date}% + \printfield{year}% + \bibrangedash% + \iffieldundef{endyear}{}{\printfield{endyear}}% + \newunit}% +{\printlist{location}% + \iflistundef{institution}% + {\setunit*{\addcomma\space}} + {\setunit*{\publocpunct}}% + \printlist{institution}% + \setunit*{\addcomma\space}% + \usebibmacro{date}% + \newunit}% +} +% +% 通用的出版社和地址的处理 +% +% 原理方法:当没有出版社地址时,直接判断title的信息是否是中文,若为中文,则写出版地不详,否则用英文的字符表示。 +% 事实上title对于每个文献来说是必须的,所以用它判断是最快的,而且一般标题和出版社的语言是一样的。 +% 注意标准standard类型,因为当没有出版项时直接省略,所以做特殊处理 +\renewbibmacro*{publisher+location+date}{\bibpubfont% +\iftoggle{bbx:gbpub}% +{\testCJKfirst{userd}% + \ifboolexpr{ test {\iflistundef{location}} and test {\iflistundef{publisher}} }% + {\iffieldequalstr{note}{standard}{}{\iftoggle{ifCJKforgbt}{\printtext{[\str@noaddress}\space :\space\str@nopublisher]}{\printtext{[S.l.\space :\space s.n.\adddot]}}}}% + {\iflistundef{location}{%\adddot + \iffieldequalstr{note}{standard}{}%%从gbt7714-2015标准第19页看到,标准存在出版项时输出,没有时完全省略。 + {\iftoggle{ifCJKforgbt}{\printtext{[\str@noaddress]}\addcolon\addspace}{\printtext{[S.l.\adddot]}\publocpunct}}}% \bibstring{noaddress} + {\printlist{location}\publocpunct}%%\addcolon\addspace% + \iflistundef{publisher}{% + \iffieldequalstr{note}{standard}{}% + {\iftoggle{ifCJKforgbt}{\printtext{[\str@nopublisher]}\setunit{\adddot\addspace}\setunit*{\addcomma\addspace}}% + {\printtext{\mkbibbrackets{s.n.}}\setunit{\adddot\addspace}\setunit*{\addcomma\addspace}}}}% + {\printlist{publisher}}}% +\setunit*{\addcomma\addspace}%\addcomma\addspace% +\usebibmacro{date}%%\newunit %去掉这个标点 +}% +{\printlist{location}% + \iflistundef{publisher} + {\setunit*{\addcomma\space}} + {\setunit*{\publocpunct}}% + \printlist{publisher}% + \setunit*{\addcomma\space}% + \usebibmacro{date}%%\newunit + }% +} + +% +% 修改了一个institution+location+date用于manual、report、thesis等类型 +% +% 20180425,v1.0k,增加了字体控制命令,hzz +% 20190105,v1.0o,加了一个编组避免\usebibmacro{date}把month和day信息去掉 +\renewbibmacro*{institution+location+date}{\bibpubfont%当没有institution时不处理。 +{\printlist{location}%%加了一个编组避免\usebibmacro{date}把month和day信息去掉 + \iflistundef{institution} + {\setunit*{\addcomma\space}} + {\setunit*{\publocpunct}}% + \printlist{institution}% + \setunit*{\addcomma\space}% + \usebibmacro{date}% + %\newunit + }} + +% +% 对volume卷信息格式做出修改 +% v1.0o,20190105,hzz +% +\DeclareFieldFormat{volume}{% +\testCJKfirst{userd}% +\iftoggle{ifCJKforgbt}% +{\bibstring{serialcn}#1\bibstring{volumecn}}% +{\bibstring{volume}~#1}% +}% volume of a book +\DeclareFieldFormat[article,periodical]{volume}{#1}% volume of a journal + +% +% 对number册信息格式做出修改 +% v1.0o,20190105,hzz +% +\DeclareFieldFormat{number}{#1}% +\DeclareFieldFormat[book,collection,inbook,% +incollection,proceedings,inproceedings]{number}{% +\testCJKfirst{userd}% +\iftoggle{ifCJKforgbt}% +{\bibstring{serialcn}#1\bibstring{numbercn}}% +{#1}% +}% + +% +% 对edition版本信息格式做出修改 +% +\DeclareFieldFormat{edition}{\bibtitlefont%源来自biblatex.DEF +\testCJKfirst{userd}% +\iftoggle{ifCJKforgbt}% +{\ifinteger{#1}% +{\printtext{#1\str@edition}}% +{#1\isdot}}% +{\ifinteger{#1}% +{\mkbibordedition{#1}~\bibstring{edition}}% +{#1\isdot}}} + +% +% 对version的版本信息做出修改 +% +\DeclareFieldFormat{version}{\bibtitlefont%源来自biblatex.DEF +\testCJKfirst{userd}% +\ifinteger{#1}% +{\iftoggle{ifCJKforgbt}{\printtext{#1\str@edition}}% +{\mkbibordedition{#1}~\bibstring{version}}}% +{#1\isdot}} + +% +% 修改析出文献的文集的标题与附加标题间的符号 +% +\renewbibmacro*{booktitle}{% + \ifboolexpr{ + test {\iffieldundef{booktitle}} + and + test {\iffieldundef{booksubtitle}} + } + {} + {\printtext[booktitle]{\bibtitlefont% + \printfield[titlecase]{booktitle}% + \setunit{\subtitlepunct}% + \printfield[titlecase]{booksubtitle}}% + \newunit%标点换成下一句 + \setunit{\subtitlepunct}}% + \printfield{booktitleaddon}} + + +% +% 调整期刊名的格式 +% +% v1.0k,20180425,增加了字体控制命令,hzz +\renewbibmacro*{journal+issuetitle}{\bibpubfont%源来自standard.bbx + \usebibmacro{journal}% + %\setunit*{\addspace}% + \setunit*{\addcomma\addspace}%修改为增加一个逗号 + \iffieldundef{series} + {} + {\newunit + \printfield{series}% + \setunit{\addspace}}% + %\usebibmacro{volume+number+eid}% + %\setunit{\addspace}% + \usebibmacro{issue+date}% + %\setunit{\addcolon\space}% + \iffieldundef{volume}{}{\setunit{\addcomma\space}}% + %换成逗号和空格 + \usebibmacro{issue}% + \usebibmacro{volume+number+eid}%把卷期放到年份后面 + %\newunit + } + + + +% +% 调整期刊卷和期的格式 +% +\renewbibmacro*{volume+number+eid}{%源来自standard.bbx +\iftoggle{bbx:gbfieldstd}{% + \printfield{volume}% + \setunit*{\adddot}% + \printfield{number}% + \setunit{\addcomma\space}% + \printfield{eid}}{% + \printfield{volume}% + %\setunit*{\adddot}%去掉点号 + %\printfield{number}% + \iffieldundef{number}{}{\printtext{\mkbibparens{\printfield{number}}}}%增加一个圆括号 + \iffieldundef{eid}{}{% + \setunit{\addcomma\space}% + \printfield{eid}}}} + +% +% 调整期刊年份的格式 +% +\renewbibmacro*{issue+date}{%去掉括号 + \printtext{%去掉了[parens] + \iffieldundef{issue} + {%\usebibmacro{date} + \iffieldundef{note}{\usebibmacro{date}}%判断一下,是否是报纸 + {\iffieldequalstr{note}{news}{\usebibmacro{newsdate}}%判断是否为报纸 + {\usebibmacro{date}}% + }}% + {\iftoggle{bbx:gbstrict}{}{\printfield{issue}% + \setunit*{\addspace}}% + %\usebibmacro{date} + \iffieldundef{note}{\usebibmacro{date}}%判断一下,是否是报纸 + {\iffieldequalstr{note}{news}{\usebibmacro{newsdate}}%判断是否为报纸 + {\usebibmacro{date}}% + }}}% + %\newunit + } + +% +% 调整页码前的标点和去掉期刊文章等页码后面的标点 +% +\renewbibmacro*{note+pages}{%源来自standard.bbx + %\printfield{note}%不要note,note用来判断是否是报纸newspaper + \iffieldundef{pages}{}{ + \setunit{\bibpagespunct}% + \printfield{pages}}% + %\newunit + } + + +% +% 编者的符号修改一下 +% v1.0 2016-07-01 +% v1.0q 2019-03-01 hzz 修改editortype前的标点 +% +\renewbibmacro*{editor}{%源来自biblatex.DEF + \ifboolexpr{ + test \ifuseeditor + and + not test {\ifnameundef{editor}} + } + {\printnames{editor}% + \iffieldundef{editortype}%增加一个类型判断,用于存在editortype的情况 + {\setunit\addspace}%当没有editortype时,直接用句点 + {%\setunit{\addcomma\space}% + \usebibmacro{editorstrg}}% + %\clearname{editor} + }% + {}} + +% +% 编者类型做一修改 +% v1.0 2016-07-01 +% v1.0q 2019-03-01 hzz 修改editortype不同语言的不同本地化字符串 +% +\renewbibmacro*{editorstrg}{%源来自biblatex.DEF + \printtext[editortype]{% + \iffieldundef{editortype} + {% +% \ifboolexpr{ %这一段去掉,未定义编者类型情况下不处理 +% test {\ifnumgreater{\value{editor}}{1}} +% or +% test {\ifandothers{editor}} +% } +% {\bibstring{editors}} +% {\bibstring{editor}} + } + {\ifbibxstring{\thefield{editortype}} %定义编者类型情况下处理,以后根据需要修改 + {\ifboolexpr{ + test {\ifnumgreater{\value{editor}}{1}} + or + test {\ifandothers{editor}} + } + {\printdelim{streditortypes}} + {\printdelim{streditortype}}} + {\thefield{editortype}}}% + }} + +% +% 编者类型的本地化字符串输出 +% v1.0q 2019-03-01 hzz +% 能对不同条目类型作格式设置的域格式,能对不同环境做格式设置的分隔符 +% 能对不同文境作设置的包括排序,标签等 +% 这里因为考虑可能标注和文献表中存在不同,所以用分隔符来输出本地化字符串 +% +\DeclareDelimFormat{streditortypes}{% + \edef\userfieldabcde{userd}% + \ifcurrentname{editor}{\edef\userfieldabcde{userc}}{}% + \ifcurrentname{bookauthor}{\edef\userfieldabcde{userb}}{}% + \ifcase\value{gbbiblocalcase}% + \iffieldequalstr{\userfieldabcde}{chinese}{\bibstring{\thefield{editortype}scn}}{}% + \iffieldequalstr{\userfieldabcde}{korean}{\bibstring{\thefield{editortype}skr}}{}% + \iffieldequalstr{\userfieldabcde}{japanese}{\bibstring{\thefield{editortype}sjp}}{}% + \iffieldequalstr{\userfieldabcde}{english}{\addcomma\addthinspace\bibstring{\thefield{editortype}s}}{}% + \iffieldequalstr{\userfieldabcde}{french}{\addcomma\addthinspace\bibstring{\thefield{editortype}s}}{}% + \iffieldequalstr{\userfieldabcde}{russian}{\addcomma\addthinspace\bibstring{\thefield{editortype}s}}{}% + \or% + \bibstring{\thefield{editortype}scn}% + \or% + \addcomma\addthinspace\bibstring{\thefield{editortype}s}% + \fi} +% +\DeclareDelimFormat{streditortype}{% + \edef\userfieldabcde{userd}% + \ifcurrentname{editor}{\edef\userfieldabcde{userc}}{}% + \ifcurrentname{bookauthor}{\edef\userfieldabcde{userb}}{}% + \ifcase\value{gbbiblocalcase}% + \iffieldequalstr{\userfieldabcde}{chinese}{\bibstring{\thefield{editortype}cn}}{}% + \iffieldequalstr{\userfieldabcde}{korean}{\bibstring{\thefield{editortype}kr}}{}% + \iffieldequalstr{\userfieldabcde}{japanese}{\bibstring{\thefield{editortype}jp}}{}% + \iffieldequalstr{\userfieldabcde}{english}{\addcomma\addthinspace\bibstring{\thefield{editortype}}}{}% + \iffieldequalstr{\userfieldabcde}{french}{\addcomma\addthinspace\bibstring{\thefield{editortype}}}{}% + \iffieldequalstr{\userfieldabcde}{russian}{\addcomma\addthinspace\bibstring{\thefield{editortype}}}{}% + \or% + \bibstring{\thefield{editortype}cn}% + \or% + \addcomma\addthinspace\bibstring{\thefield{editortype}}% + \fi} + + +% +% bookauthor域的输出, +% v1.0q 2019-03-01 hzz +% 不再对editor和bookauthor做sourcemap,而是下面的宏内逻辑代替, +% 使得除使用bookauthor外也可以使用editor,便于在使用editor时使用editortype +\renewbibmacro*{bybookauthor}{% + \ifnameundef{bookauthor}% + {\ifnameundef{editor}% + {}% + {\ifnamesequal{author}{editor}% + {}{\usebibmacro{editor}}}% + }% + {\ifnamesequal{author}{bookauthor}% + {}{\printnames{bookauthor}}% + }% +} + +% 责任者如果没有author用editor或translator替代 +% 20210521 v1.0y hzz +%专著如果责任者是editor那么不用输出类型信息 +\renewbibmacro*{editor+others}{% + \ifboolexpr{ + test \ifuseeditor + and + not test {\ifnameundef{editor}} + } + {\printnames{editor}% + \clearname{editor}} + {}} +%要注意要使用translator那么需要开启usetranslator选项的。 +%注意其中的标点处理。 +\renewbibmacro*{translator+others}{% + \ifboolexpr{ + test \ifusetranslator + and + not test {\ifnameundef{translator}} + } + {\renewcommand{\aftertransdelim}{\adddot\addspace}{\adddot\addspace}\printnames{translator}% + \clearname{translator}} + {}} + + +% +% 修改期刊的标题 +% +\renewbibmacro*{periodical}{%源来自biblatex.DEF + \iffieldundef{title} + {} + {\printtext[title]{\bibtitlefont% + \printfield[titlecase]{title}% + %\setunit{\subtitlepunct}% + \ifboolexpr{test {\iffieldundef{subtitle}}}%这里增加了对子标题的判断,解决不判断多一个点的问题 + {}{\setunit{\subtitlepunct} + \printfield[titlecase]{subtitle}}% + %}%把编组结束移到后面去 + \iftoggle{bbx:gbtype}{% + \iffieldundef{usera}{}{%在标题后直接给出文献标识字母 + \printfield[gbtypeflag]{usera}}}{} + }} + } + +% +% 期刊的标题做修改 +% +\renewbibmacro*{title+issuetitle}{%源来自standard.BBX + \usebibmacro{periodical}% + %\setunit*{\addspace}% + \setunit*{\adddot\addspace}%标点修改为句点 + \iffieldundef{series} + {} + {\newunit + \printfield{series}% + \setunit{\addspace}}% + \usebibmacro{periodical+issue}%将issue调整到上面来,并修改 +\iffieldundef{number}{}{%%进一步处理有范围的数字 + \multinumberparser{\thefield{number}}}% + \iffieldundef{volume}% + {\printfield{year}% + \printtext{\mkbibparens{\multinumberfirst}}% + \bibrangedash% + \iffieldundef{endyear}{}{\printfield{endyear}\printtext{\mkbibparens{\multinumbersecond}}}% + }% + {\multivolparser{\thefield{volume}}% + \printfield{year}% + \setunit{\addcomma\space}%将冒号修改为逗号 + \printtext{\multivolfirst}% + \printtext{\mkbibparens{\multinumberfirst}}% + \bibrangedash% + \iffieldundef{endyear}{}{% + \printfield{endyear}% + \setunit{\addcomma\space}%将冒号修改为逗号 + \printtext{\multivolsecond}% + \printtext{\mkbibparens{\multinumbersecond}}}% + }% + \setunit{\addcomma\space}% + \printfield{eid}% + \setunit{\addspace}% + %\usebibmacro{issue+date}% + %\setunit{\addcolon\space}% + \usebibmacro{issue}% + \newunit} + +% +% 新增一个样式用于调整期刊年份的格式,只打印年份 +% +\newbibmacro*{periodical+issue}{% + \printtext{%去掉了[parens] + \iffieldundef{issue} + {%\usebibmacro{date}%修改为下一句 + }% + {\printfield{issue}% + \setunit*{\addspace}% + %\usebibmacro{date}%修改为下一句 + }% + }% + %\newunit +} + +% +% 重设专利title的输出,将文献类型标识符输出出去 +% +\newbibmacro*{patenttitle}{%原输出来自biblatex.def文件 + \ifboolexpr{% + test{\iffieldundef{title}}% + and% + test{\iffieldundef{subtitle}}% + }% + {}% + {\printtext[title]{\bibtitlefont% + \printfield[titlecase]{title}% + \ifboolexpr{test {\iffieldundef{subtitle}}}%这里增加了对子标题的判断,解决不判断多一个点的问题 + {}{\setunit{\subtitlepunct}% + \printfield[titlecase]{subtitle}}% + \iffieldundef{titleaddon}{}%判断一下titleaddon,否则直接加可能多一个空格 + {\setunit{\subtitlepunct}\printfield{titleaddon}}% + \setunit{\subtitlepunct}\printfield{number}%写专利号 + \iftoggle{bbx:gbtype}{\printfield[gbtypeflag]{usera}}{}% + %\iffieldundef{booktitle}{\newunit}{}%当title是析出时,不要标点 + %\newunit + }% +}% +} + + + +% +% 修改in:用于inbook、incollection、inproceedings等类型 +% 2018.04.20,v1.0k,renewed marco,by hzz +% 20190212,v1.0q,增加中英文区分,by hzz +% +% 原理方法:使用bibmacro{in:}改变了以前在driver中直接输出//的方式,同时也简化了标点控制。 +\renewbibmacro*{in:}{% + \iftoggle{bbx:gbpunctin}{\printtext{\allowbreak\texttt{//}\allowbreak}}%\addthinspace + {\setunit{\adddot\addspace}% + \iffieldequalstr{userd}{chinese}% + {\printtext{\bibstring{incn}}}% + {\printtext{\bibstring{in}}}% + }}%\newunit\newblock\intitlepunct + +% +% 修改type域的输出格式 +% 2019.02.12,v1.0q,byhzz +% 使其可以区分中英文输出不同的格式,比如博士论文英文输出PHD thesis,中文则是博士学位论文 +\DeclareFieldFormat{type}% +{\iffieldequalstr{userd}{chinese}% + {\ifbibxstring{#1cn}{\bibxstring{#1cn}}{#1}}% + {\ifbibstring{#1}{\bibstring{#1}}{#1}}% +} + +% +% 修改series域的输出格式 +% 2019.05.01,v1.0r,byhzz +\renewbibmacro*{series+number}{% + \printfield{series}% + %\setunit*{\addspace}% + %\printfield{number}% + %\newunit + } + +%===================================================================== +%设置驱动格式 +%===================================================================== +% +% book条目类的驱动 +% +\DeclareBibliographyDriver{book}{%源来自standard.bbx文件 +\usebibmacro{bibindex}% +\usebibmacro{begentry}% +\usebibmacro{author/editor+others/translator+others}% +\ifnameundef{namea}{}{\setunit{\labelnamepunct}\newblock}%这一段用于去除作者不存在时多出的标点 +\usebibmacro{maintitle+title}% +\iftoggle{bbx:gbstrict}{}{% +\newunit +\printlist{language}% +\newunit\newblock% +\usebibmacro{byauthor}% +\newunit\newblock}% +\usebibmacro{byeditor+others}% +\newunit +\printfield{edition}% +\newunit\newblock%% +\iftoggle{bbx:gbstrict}{}{% +\iffieldundef{maintitle}% +{\printfield{volume}% +\printfield{part}}% +{}% +\newunit% +\printfield{volumes}% +\newunit\newblock% +\usebibmacro{series+number}}% +\newunit\newblock% +%\printfield{note}% +%\newunit\newblock% +\usebibmacro{publisher+location+date}% +%\newunit\newblock %这里标点去掉 +\usebibmacro{chapter+pages}% + \iffieldundef{url}{}{%当没有网址时也不输出 + \usebibmacro{modifydate}}%带括号的修改或更新日期, +\usebibmacro{doi+eprint+url}%从下面移动到上面来,因为gbt2015的url需直接放在页码后面。 + \newunit\newblock% + \printfield{pagetotal}% + \newunit\newblock% + \iftoggle{bbx:isbn} + {\printfield{isbn}} + {}% + \newunit\newblock + %\usebibmacro{doi+eprint+url}% + %\newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}\usebibmacro{annotation}} + + +% +% 期刊文章,连续出版物中的析出文献的格式 +% + \DeclareBibliographyDriver{article}{% + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{author/translator+others}% +\ifnameundef{author}{}{\setunit{\labelnamepunct}\newblock}%这一段用于去除作者不存在时多出的标点 + \usebibmacro{title}% + \iftoggle{bbx:gbstrict}{}{% + \newunit% + \printlist{language}% + \newunit\newblock + \usebibmacro{byauthor}% + \newunit\newblock + \usebibmacro{bytranslator+others}% + \newunit\newblock + \printfield{version}}% + \newunit\newblock + %\usebibmacro{in:}% 不使用in来表示期刊等连续出版物 + \usebibmacro{journal+issuetitle}% + %\newunit +% \usebibmacro{byeditor+others}% +% \newunit + \usebibmacro{note+pages}% + \iffieldequalstr{note}{news}{}{%当是新闻时不输出修改或更新日期 + \iffieldundef{url}{}{%当没有网址时也不输出 + \iftoggle{bbx:url}{%当url选项为false时,也不输出 + \usebibmacro{modifydate}}{}}}%带括号的修改或更新日期, + \usebibmacro{doi+eprint+url}%从后面移上来,调整url和页码之间的位置 + \newunit\newblock + \iftoggle{bbx:isbn} + {\printfield{issn}} + {}% + \newunit\newblock + %\usebibmacro{doi+eprint+url}% + %\newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}\usebibmacro{annotation}} + + + +% +% 连续出版物的驱动 +% + \DeclareBibliographyDriver{periodical}{%源来自standard.BBX + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{editor}% + %\setunit{\labelnamepunct}\newblock + \newunit\newblock %删除上面一行,添加这一行 + \usebibmacro{title+issuetitle}% + \newunit\newblock% + \usebibmacro{location+institution+date}%添加这一行用于输出地址,单位和时间 + \newunit\newblock%添加这一行 + \iftoggle{bbx:gbstrict}{}{% + \printlist{language}% + \newunit\newblock + \usebibmacro{byeditor}% + \newunit\newblock + \printfield{note}% + \newunit\newblock} + \iftoggle{bbx:isbn} + {\printfield{issn}} + {}% + \newunit\newblock + \usebibmacro{doi+eprint+url}% + \newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}\usebibmacro{annotation}} + +% +% 专利文献驱动 +% + \DeclareBibliographyDriver{patent}{%源来自standard.BBX + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{author}% +\ifnameundef{author}{}{\setunit{\labelnamepunct}\newblock}%这一段用于去除作者不存在时多出的标点 + %\usebibmacro{title}% + \usebibmacro{patenttitle}%给出专利专用的标题输出 + \iftoggle{bbx:gbstrict}{}{% + \newunit% + \printlist{language}% + \newunit\newblock + \usebibmacro{byauthor}}% + \newunit\newblock + \printfield{type}% + \setunit*{\addspace}% + %\printfield{number}%已放到patenttitle中处理 + \iflistundef{location} + {} + {\setunit*{\addspace}% + \printtext{%[parens] + \printlist[][-\value{listtotal}]{location}}}% + \newunit\newblock + \usebibmacro{byholder}% + \newunit\newblock + \printfield{note}% + \newunit\newblock + \usebibmacro{newsdate}% + %\newunit\newblock + \usebibmacro{doi+eprint+url}% + \newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}\usebibmacro{annotation}} + + +% +% 在线文献驱动 +% +\DeclareBibliographyDriver{online}{%源来自standard.BBX + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{author/editor+others/translator+others}% +\ifnameundef{namea}{}{\setunit{\labelnamepunct}\newblock}%这一段用于去除作者不存在时多出的标点 + \usebibmacro{title}% + \iftoggle{bbx:gbstrict}{}{% + \newunit% + \printlist{language}% + \newunit\newblock + \usebibmacro{byauthor}% + \newunit\newblock + \usebibmacro{byeditor+others}% + \newunit\newblock + \printfield{note}}% + \newunit + \printfield{version}% + \newunit\newblock + %\printlist{organization}% + \printlist{institution}% + \newunit\newblock +\ifboolexpr{% +test{\iffieldundef{day}} and test{\iffieldundef{endday}} and test{\iffieldundef{eventday}}% +}{\usebibmacro{date}}% +{\usebibmacro{modifydate}}%修改或更新日期,为带括号的时间 + \usebibmacro{url+urldate}%从下面移上来 + \newunit\newblock + \iftoggle{bbx:eprint} + {\usebibmacro{eprint}} + {}% + \newunit\newblock + %\usebibmacro{url+urldate}% + %\newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}\usebibmacro{annotation}} + + +% +% 报告类型驱动 +% 当有网址无出版项时,用online输出 +% +\DeclareBibliographyDriver{report}{% + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{author/editor+others/translator+others}% +\ifnameundef{namea}{}{\setunit{\labelnamepunct}\newblock}%这一段用于去除作者不存在时多出的标点 + \usebibmacro{title}% + \iftoggle{bbx:gbstrict}{}{% + \newunit% + \printlist{language}% + \newunit\newblock + \usebibmacro{byauthor}}% + \newunit\newblock + \usebibmacro{byeditor+others}%增加的译者信息 + \newunit\newblock + \printfield{type}% + \setunit*{\addspace}% + \printfield{number}% + \newunit\newblock + \printfield{version}% + \newunit + \printfield{note}% + \newunit\newblock + \usebibmacro{publisher+location+date}% + %\newunit\newblock + \usebibmacro{chapter+pages}% + \usebibmacro{doi+eprint+url}% + \newunit + \printfield{pagetotal}% + \newunit\newblock + \iftoggle{bbx:isbn} + {\printfield{isrn}} + {}% + \newunit\newblock +% \usebibmacro{doi+eprint+url}% +% \newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}\usebibmacro{annotation}} + +% +% 论文、手册类型驱动 +% 2016-11-11,增加了译者信息 +% +\DeclareBibliographyDriver{manual}{% + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{author/editor+others/translator+others}% +\ifnameundef{namea}{}{\setunit{\labelnamepunct}\newblock}%这一段用于去除作者不存在时多出的标点 + \usebibmacro{title}% + \iftoggle{bbx:gbstrict}{}{% + \newunit% + \printlist{language}% + \newunit\newblock + \usebibmacro{byauthor}}% + \newunit\newblock + \usebibmacro{byeditor+others}%增加的译者信息 + \newunit\newblock + \iftoggle{bbx:gbfieldtype}{% + \printfield{type}% + \setunit*{\addspace}}{}% + \printfield{number}% + \newunit\newblock + \printfield{version}% + \newunit + \printfield{note}% + \newunit\newblock + \usebibmacro{institution+location+date}% + %\newunit\newblock + \usebibmacro{chapter+pages}% + \iffieldundef{url}{}{%当没有网址时也不输出修改或更新日期 + \usebibmacro{modifydate}}%修改或更新日期为带括号的时间 + \usebibmacro{doi+eprint+url}% + \newunit + \printfield{pagetotal}% + \newunit\newblock + \iftoggle{bbx:isbn} + {\printfield{isrn}} + {}% + \newunit\newblock +% \usebibmacro{doi+eprint+url}% +% \newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}\usebibmacro{annotation}} + +% +% 备选类型驱动 +% +% 利用biblatex的misc驱动 +\DeclareBibliographyDriver{misc}{% + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{author/editor+others/translator+others}% +\ifnameundef{namea}{}{\setunit{\labelnamepunct}\newblock}%这一段用于去除作者不存在时多出的标点 + \usebibmacro{title}% +\iftoggle{bbx:gbstrict}{}{% + \newunit + \printlist{language}% + \newunit\newblock + \usebibmacro{byauthor}% + \newunit\newblock + \usebibmacro{byeditor+others}}% + \newunit\newblock + \printfield{howpublished}% + \newunit\newblock + \printfield{type}% + \newunit + \printfield{version}% + \newunit + \printfield{note}% + \newunit\newblock + \usebibmacro{institution+location+date}% + %\usebibmacro{organization+location+date}% + %\newunit\newblock + \usebibmacro{doi+eprint+url}% + \newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}\usebibmacro{annotation}} + +% +% 增加inbook:parent用于辅助crossref传统功能的实现 +% 用在{crosscite}宏中 +% 20210216,v1.0w,hzz +\newbibmacro*{inbook:parent}{% +\usebibmacro{bybookauthor}% + \ifnameundef{bookauthor}{% + \ifnameundef{editor}{}{\newunit}% + }{\newunit}%替换下一句 + %\newunit\newblock +\iffieldundef{series}{}{\usebibmacro{series+number}\setunit{\addcolon\addspace}}%为处理一些存在series的情况而增加 + \usebibmacro{maintitle+booktitle}% +\iffieldundef{volume}{}{\setunit{\addcolon\addspace}\printfield{volume}}% +\iffieldundef{number}{}{\setunit{\addcolon\addspace}\printfield{number}}%增加卷和册信息 + \newunit\newblock% +% \usebibmacro{byeditor+others}% +% \newunit\newblock + \printfield{edition}% + \newunit + \iftoggle{bbx:gbstrict}{}{% +% \iffieldundef{maintitle} +% {\printfield{volume}% +% \printfield{part}} +% {}% +% \newunit +% \printfield{volumes}% +% \newunit\newblock +% \usebibmacro{series+number} + }% + \newunit\newblock + %\printfield{note}% + %\newunit\newblock + \usebibmacro{publisher+location+date}} + +% +% 专著中的析出文献的格式修改 +% +\DeclareBibliographyDriver{inbook}{%源来自standard.bbx + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{author/translator+others}% + \ifboolexpr{ + test {\ifnameundef{author}} + and + test {\ifnameundef{translator}} + }{}{\setunit{\labelnamepunct}\newblock}%这一段用于去除作者不存在时多出的标点 +\usebibmacro{title}% +\usebibmacro{in:}% +%\printtext{\texttt{//}\addthinspace}% +\usebibmacro{crosscite}{inbook:parent}% + %\newunit\newblock + \usebibmacro{chapter+pages}% + %\newunit\newblock + \usebibmacro{doi+eprint+url}%移到上面来 + \newunit\newblock + \iftoggle{bbx:isbn} + {\printfield{isbn}} + {}% + \newunit\newblock +% \usebibmacro{doi+eprint+url}% +% \newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}\usebibmacro{annotation}} diff --git a/main.tex b/main.tex index fe8daa0..27e0031 100644 --- a/main.tex +++ b/main.tex @@ -1,5 +1,4 @@ \documentclass{CCNUthesis} - \ccnusetup{ % 个人信息 info = { diff --git a/manual-body/basic-computer-knowledge.tex b/manual-body/basic-computer-knowledge.tex index 3ea34d3..fe8f32f 100644 --- a/manual-body/basic-computer-knowledge.tex +++ b/manual-body/basic-computer-knowledge.tex @@ -1,41 +1,74 @@ +\section*{FAQ:} +\begin{enumerate} + \item 我不太会\LaTeX{}有什么可以参考的资料吗?\,\,\emph{安装和升级详见}《install-latex-guide-zh-cn》,\emph{入门教程}见《Ishort-zh-cn》,\emph{都在群文件},本手册第一章内容是计算机基础知识(已完成)\emph{许多 + 常见的问题可以在这里找到}。 + 第二章是\LaTeX{}基础知识(待完善),后面是手册的使用说明(待完善)。纸质书籍推荐《LaTeX入门》,《LaTeX范例学习与试卷论文排版》。 + \item 使用哪个\LaTeX{}发行版?\,\,夏学长的新模版使用\TeX{} Live,邓老师的旧模版使用C\TeX{},两个发行版不可以混用,发行版的相关知识见\ref{subsub:fxb}节。C\TeX{}存在一些 + 无法解决的问题,因此现在不推荐,详见\ref{subsub:labmwt}节。 + \item 如何检测自己装了哪个版本?\,\,命令行(控制台)运行命令latex,观察弹出来的信息可以知道版本。本群的教程安装的是\TeX{} Live。 + \item 好多资料都提到“运行xx指令”,“命令行/控制台运行xx”都是什么意思?\,\,都是指在命令行下运行指令,相关知识见\ref{subsec:mlh}节。 + \item 新旧模版有什么区别?新模版有什么优势?\,\,在基本的语法指令方面,两个模版基本没有区别。旧模版的存在的问题详见\url{https://gitee.com/xkwxdyy/CCNUthesis}拉到下面有原因说明, + 新模版是为了解决这些问题而进行的重写。 + \item 安装好后桌面怎么没有图标?\,\,请认真阅读\ref{sub:by}节。 + \item 用Texstudio一打开模版就全是乱码,怎么办?\,\,你一定打开了邓老师的旧模板,原因和解决方案详见\ref{bm}节编码的知识。 + + \emph{补充说明:}Texstudio仅仅是个代码编辑器(详见\ref{sub:by}),能不能正常使用模版与选择的代码编辑器无关,与发行版有关! + \item 一编译就报一堆错怎么办?\,\,先确认安装的\LaTeX{}发行版和使用的模版是否配套!新模版还需要保证模版是最新的,并且将宏包升级到最新,仍然详见《install-latex-guide-zh-cn》。 + 报错信息分成两类,warning(警告)和error(错误),一般情况下只需要在意error。其次,我们应该通过翻译器等方式读懂报错信息, + 并定位错误的代码,检查自己是否有语法错误或者打错,必要时借助搜索引擎或者直接提问,查错的经验需要多多积累。 + + \emph{快速排查}:(1)首次编译模版报大量错误,基本上说明发行版和模版不匹配!请检查版本!(2)检查编译方式,新模板为xelatex,旧模版为pdflatex,编译方式的内容见\ref{subsub:yy}节。 + (3)错误\verb"“File ‘ninecolors.sty’ not found. \begin{document}”"的解决办法:如果安装的是TeX Live 2021此错误的原因是没有更新宏包,更新的方法详见群文件《install-latex-guide-zh-cn》1.4节或者在开始菜单找TeX Live Shell来更新。如果安装了版本较旧比如是2020,需要卸载后重新安装,方法仍见《install-latex-guide-zh-cn》第一章。 + \item 遇到了自己无法解决的问题应该怎么办?\,\,到链接\url{https://gitee.com/xkwxdyy/CCNUthesis},选择\emph{issues}菜单,里面有开启中和已完成, + “已完成”中的问题是有人问过且已经被解决的,应当优先查阅;“开启中”的问题是尚未解决的。如果自己的问题没有找到别人的解决方案,就选右上角的新建Issue提出问题。 + + +\end{enumerate} + +最后建议大家在动手写作前多学一些知识,先认真阅读群里的手册和本手册,许多概念都在本手册的第一章一一解释了,并且在使用模版过程中积极提问,提问优先到gitee提issue,还需要善于使用搜索引擎。祝大家顺利完成毕业论文! +\newpage \section{计算机基础知识} -开源排版系统\LaTeX{}与大家之前熟悉的软件有较多的不同,在使用过程中很可能遇到各种困难。没有任何编程基础的同学最好先阅读此部分。 -\subsection{编译环境和代码编辑器} +开源排版系统\LaTeX{}与大家之前熟悉的软件有较多的不同,在使用过程中很可能遇到各种困难。没有任何编程经验的同学最好先看这个小视频\href{https://www.bilibili.com/video/BV1t4411v78E?from=search&seid=5662014810176309518&spm_id_from=333.337.0.0}{『教程』学编程前必知的8个电脑操作}, +然后阅读此部分,能够帮助你。 + + +\subsection{编译环境和代码编辑器}\label{sub:by} 常看到这样的提问“为什么我的\LaTeX{}界面和别人不一样?”,“非得安装TeXstudio吗?”,“安装完桌面为什么没有图标?”;学习LaTeX时也会碰到许多 相似的概念如\TeX{} Live,C\TeX{},xelatex,TeXworks等,使人感到迷惑。这些问题的根源在于,\LaTeX{}是一种计算机语言,与Word等软件并不一样,下面就来一一阐述。 -\subsubsection{计算机语言} +\subsubsection{计算机语言}\label{subsub:yy} 人类社会有汉语,英语,法语等多种语言。然而,计算机并不能读懂人类的语言,要想指挥计算机完成各种任务,就要使用计算机语言。 -计算机能直接识别运行的只有由0和1组成的二进制代码,称为\emph{机器语言},由于其可读性太差,科学家又创造了C,Java等采用 +计算机能直接识别并运行的只有由0和1组成的二进制代码,称为\emph{机器语言},由于其可读性太差,科学家又创造了C,Java等采用 贴近人类语言的语法格式(主要是英语)描述程序的\emph{编程语言},并开发了对应的\emph{编译器},可以将编程语言翻译为计算机能识别的 二进制代码来运行,这个翻译的过程称作\emph{编译},在编译前的文件称为\emph{源代码}。 \LaTeX{}是一种宏语言,在排版时,通过各种各样的指令对文档的各种格式(比如字体,行距,居中,编号)进行控制,一份\LaTeX{} -源代码中既含有需要输出在文档中的具体内容,也含有控制指令。通过调用对应的\emph{编译器}进行\emph{编译},最后得到排版完成的PDF文档。 -根据不同的需求,\LaTeX{}系统有不同的编译器,下面将其称为\emph{编译引擎}。主要有xelatex(主要处理中文文档), -pdflatex(主要处理英文文档),bibtex/biber(用于引入参考文献),lualatex等。我们说“采用xelatex方式编译文档”,指的就是 -调用\emph{编译引擎}xelatex编译源代码文件。 - +源代码中既含有需要输出在文档中的具体内容,也含有控制指令。写完源代码后,通过调用各种程序对源代码进行\emph{编译},最后得到排版完成的文档。 +根据不同的需求,\LaTeX{}系统在编译时可供调用的程序有不少(其中有编译器)。最初只有\TeX{},通过命令行下的命令tex调用,后来又 +开发了不少扩展,\TeX{}程序连同这些扩展称为不同的\TeX{}\emph{引擎},常见的有\TeX{},pdf\TeX{},\XeTeX{},Lua\TeX{}。 +通过命令行下输入不同的命令,可以调用不同的引擎以不同的方式编译源代码输出不同格式的文档,这些命令称作 +\emph{编译方式},常用的有pdflatex,xelatex,lualatex,分别调用了pdf\TeX{},\XeTeX{},Lua\TeX{}引擎输出PDF文件 +\footnote{其实最早\LaTeX{}输出格式是DVI,随着时代发展,后来编译时会调用xdvipdfmx程序直接输出PDF格式。}。 \subsubsection{代码编辑器} 通过上面的介绍,你会发现,当你编写好代码后,要得到排版好的文件,起作用的其实是编译器,而采用什么样的代码编辑器 -写源代码,其实是不重要的。实际上,如果你安装正确,你也可以使用记事本来编写代码,只要知道如何调用编译引擎。 +写源代码,其实是不重要的。实际上,如果你安装正确,你也可以使用记事本来编写代码,只要知道如何调用编译引擎,选择恰当的编译方式。 那么代码编辑器有什么用呢?前面提到,代码需要通过编译才能得到我们要的PDF文档,但是,可能因为疏忽,编写某些指令有语法错误, 那么这个时候,编译就会报错,也就无法得到PDF文档(当然,有可能报错了,但是得到了正确排版的PDF文档)。此时就需要查找错误, 查找错误的过程被程序员称为\emph{Debug}。 -如果使用记事本这种编辑器,你会发现查找错误非常痛苦,因为代码和你要排版的内容直接混在了一起,都是白纸黑字。许多代码编辑器 -都含有\emph{语法高亮}的功能,会把不同的代码自动变成不同的颜色,这样,查找起来就比较方便了,语法高亮的效果如图(以VS Code为例)。 +如果使用记事本这种编辑器,你会发现查找错误非常痛苦,因为代码和你要排版的内容直接混在了一起,都是白底黑字。许多代码编辑器 +都含有\emph{语法高亮}的功能,会把不同的代码自动变成不同的颜色,这样,查找起来就比较方便了,语法高亮的效果如图(以Visual Studio Code为例)。 \begin{center} \includegraphics[scale=0.5]{1.png} \end{center} @@ -49,19 +82,19 @@ \subsubsection{代码编辑器} 第三个方面是编译运行,\LaTeX{}有些代码编辑器如TeXstudio,不仅可以写代码,也提供了一键编译的按钮,如果你的编辑器没有编译的功能,就需要使用命令行编译(详见\ref{subsec:mlh}节),还有一些功能只能通过命令行使用。 这样对初学者来说上手起来就比较快。在安装\LaTeX{}时,一般会附带安装一个编辑器TeXworks,同样提供了高亮,补全,一键编译的效果,但整体比较简陋,没有 -TeXstudio功能那么多,所以就会出现很多人推荐TeXstudio,导致很多人误解安装\LaTeX{}是安装TeXstudio。 +TeXstudio功能那么多,所以就会出现很多人推荐TeXstudio,导致很多人误解安装\LaTeX{}就是安装TeXstudio。 -个人比较喜欢的代码编辑器是VS Code,这是微软开发的开源编辑器,具有很强的自定义性,还有各种各样实用的插件,可根据自己的需求 +个人比较喜欢的代码编辑器是Visual Studio Code,这是微软开发的开源编辑器,具有很强的自定义性,还有各种各样实用的插件,可根据自己的需求 配置各种指令和快捷键,不过编译环境需要自己配置,可以参考这个链接:\href{https://zhuanlan.zhihu.com/p/38178015?utm_source=qq&utm_medium=social&utm_oi=1122597840500740096}{使用VSCode编写LaTeX}, 推荐对\LaTeX{}有一定了解后,再更换代码编辑器提高效率。 -\subsubsection{发行版} +\subsubsection{发行版}\label{subsub:fxb} 发行版指的是\LaTeX{}整个软件包的版本,\TeX{} Live,C\TeX{},MiK\TeX{}指的就是发行版,通常问安装哪个版本,指的是哪个发行版。有些模版和代码只能特定 -的发行版下编译,比如本论文模版基于\TeX{} Live,邓老师的旧模板基于C\TeX{},不同的发行版通常不能兼容,因此 +的发行版下编译,比如本论文模版基于\TeX{} Live 2021,邓老师的旧模板基于C\TeX{},不同的发行版通常不能兼容,因此 在一般情况下\emph{请勿安装超过一个发行版!} 一个发行版主要有三个部分:各种编译器,许许多多的宏包,宏包的说明文档。宏包可以理解为指令集,提供了更多的排版指令,当你需要对应指令时,只要加载对应 @@ -69,13 +102,13 @@ \subsubsection{发行版} 因此,你会发现其实安装\LaTeX{},是安装这一门语言的\emph{编译环境},使得你可以在自己的电脑上编译\LaTeX{}源文件。 前面说过,如果编辑器没有没有编译的功能,就需要使用命令行编译(详见\ref{subsec:mlh}节),本质是电脑运行程序的另一种方式。 -因此,\emph{安装完成后,桌面没有图标!}需要自己尝试编译一个含中文的文件,如果编译成功,才能说明安装成功,或者依照手册《install-latex-guide-zh-cn》。 +因此,\emph{安装完成后,桌面没有图标!}需要自己尝试编译一个含中文的文件,如果编译成功,才能说明安装成功,或者依照手册《install-latex-guide-zh-cn》\footnote{\url{https://gitee.com/OsbertWang/install-latex-guide-zh-cn}},这个手册非常重要,会被多次提到。 \subsection{命令行}\label{subsec:mlh} - +在\ref{sub:by}节,FAQ和许多资料中都常常出现“命令行/控制台运行xx”,那么这是什么意思呢?本节解决这个问题。 \subsubsection{GUI与CLI} @@ -137,7 +170,7 @@ \subsubsection{Windows 10系统下的命令行基本操作}\label{subsub:cz} \emph{Step3:编译} -输入命令\verb"xelatex --shell-escape test1.tex"后按回车键开始编译,\verb"“test1.tex”"是要编译的文件的文件名。 +输入命令\verb"xelatex --shell-escape test1.tex"后按回车键开始编译,\verb"xelatex"是调用的编译器的名称;\verb"--shell-escape"是编译器的设置参数,在调用外接程序时常用;\verb"test1.tex"是要编译的文件的文件名。请注意输入法和空格! \emph{等到再次出现命令提示符时}(如图所示),说明编译完成,此时可以回到原来的目录查看编译得到的PDF文件。 \begin{center} @@ -149,8 +182,7 @@ \subsubsection{Windows 10系统下的命令行基本操作}\label{subsub:cz} 信息都是英语,需要随时准备使用翻译软件或者搜索引擎。 这个例子展示了命令行的基本用法,通过输入磁盘的字母和\verb"cd"指令进入需要运行命令的目录,再执行相应的命名,也有很多命令行 -命令可以直接运行而不需要切换目录。希望大家看到“命令行下运行xx”这样的字眼时,能够不再害怕,而是上手操作。 - +命令可以直接运行而不需要切换目录。希望大家看到“命令行下运行xx”这样的字眼时,能够不再害怕,而是尝试上手操作。 @@ -166,28 +198,209 @@ \subsubsection{Windows Terminal} 此时,只要在你需要进入的路径下按右键选择“Open in Windows Terminal”,弹出来的命令行窗口的当前目录就是你需要进入的路径! 但这种方式默认不是“以管理员身份运行”,因此,在一些情况下还是需要采用\ref{subsub:cz}节的方法。 +\emph{总结}:本节的操作方法适用于所有需要在命令行下运行的程序,基本方法就是先用命令cd+路径或者右键菜单切换到文件的 +路径,然后用程序名+(设置参数)+(文件名)的格式运行,加括号是因为有些程序不需要输入文件,或不需要设置参数。 - -\subsubsection{重要的环境变量Path} +如果你有认真读了\LaTeX{}的安装手册《install-latex-guide-zh-cn》,你会发现里面的所有操作都是基于命令行的, +通过命令行的方式进行描述使得叙述变得简单明了,碰到对应问题,在命令行下运行对应指令即可,运行指令的方法就是本节的内容。 +\subsection{重要的环境变量Path} 你可能会想,能不能用命令行运行其他程序比如Word呢?然而,当你输入\verb"Word.exe"时,会得到如下的报错信息:\verb"'Word.exe'不是内部或外部命令,也不是可运行的程序或批处理文件。" -然而,你会发现,当你成功安装\LaTeX{}后,编译器的调用命令如\verb"xelatex,pdflatex"可以通过命令行在任意目录下使用;一些教程常常能看见这样的字眼“将xx添加到Path/环境变量”使人摸不着头脑, -其中的原因涉及到本节所讲的\emph{环境变量}。本节内容主要参考这个视频:\href{https://www.bilibili.com/video/BV1w741147G9?from=search&seid=9151606959931684460&spm_id_from=333.337.0.0}{『教程』什么是环境变量}。 +然而,你会发现,当你成功安装\LaTeX{}后,编译器的调用命令如\verb"xelatex",\verb"pdflatex"可以通过命令行在任意目录下使用;一些教程常常能看见这样的字眼“将xx添加到Path/环境变量”使人摸不着头脑, +其中的原因涉及到本节所讲的\emph{环境变量}。本节内容主要参考这个视频:\href{https://www.bilibili.com/video/BV1w741147G9?from=search&seid=9151606959931684460&spm_id_from=333.337.0.0}{『教程』什么是环境变量?} + + + +\subsubsection{环境变量}\label{subsub:hjbl} + + +环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:临时文件夹位置和系统文件夹位置等。它的主要作用,通俗来说就是\emph{指明操作系统的重要目录在哪里}。比如,环境变量 SystemRoot指明了系统目录所在的位置, +在Windows 10 的地址栏中输入\verb"%SystemRoot%"后回车,会发现跳转到C盘的Windows文件夹,这正是系统的安装目录! + +显然,环境变量不止一个,打开设置,搜索“环境变量”,选择“编辑系统环境变量”,在“高级”页签右下角可以看到“环境变量” +\begin{center} + \includegraphics[scale=0.42]{12.png} +\end{center} + +这样就打开了环境变量对话框,可以在这里进行编辑,会发现有\emph{用户变量}和\emph{系统变量},用户变量只针对当前登陆的用户,系统变量针对所有使用这台电脑的人,因此一般情况下只要编辑系统变量就行了。 +但为了保险起见,在添加环境变量时,最好同时在系统变量和用户变量中都添加。 +\begin{center} + \includegraphics[scale=0.5]{13.png} +\end{center} + + + + +\subsubsection{环境变量Path}\label{subsub:pa} + + +Path是非常重要的环境变量,表示\emph{系统指定可执行文件的搜索路径},当在“运行”中或者命令行中输入程序的名称时,系统就会 +在Path指明的目录里搜索对应的程序,找到则运行,找不到就会报错。也就是说,\emph{如果将程序A放到Path指定的目录下,这个程序就可以 +随时随地通过“运行”或命令行运行!} +\begin{center} + \includegraphics[scale=0.55]{14.png} +\end{center} + +现在让我们看看Path的内容, 单击系统变量中Path那一行后再单击编辑,显示出来的路径就是Path指定的目录。 + +注意图中框起来的两个路径 +\begin{enumerate} + \item \verb"%SystemRoot%\system32"是命令提示符\verb"cmd.exe"的存放路径。 + \item \verb"E:\texlive\2021\bin\win32"是\TeX{} Live 2021的编译器和编译需要调用的程序的存放路径。安装盘符 + 与安装时的选择有关,默认为C盘,我的电脑安装在E盘。 +\end{enumerate} +\begin{center} + \includegraphics[scale=0.5]{15.png} +\end{center} + +在Path中含有的路径下所有的可执行文件(.exe)都可以在任何地方通过“运行”或命令行直接运行, +\emph{如果发行版\TeX{} Live 2021被正确安装了,那么在电脑的系统变量Path条目中就会出现前面的路径2}。 +此时,在代码编辑器点击“一键编译”或者使用第\ref{subsub:cz}节的方法在命令行下编译时,计算机才能正确的到 +\TeX{} Live编译器的安装路径下找到相应的编译器运行,从而编译源代码,生成PDF文件。 + +也就是说,如果环境变量没有路径2,那么就无法在命令行下直接调用编译器,在编译源代码时会报错,说明\LaTeX{}安装有 +问题或者根本没有安装。 + + + +\subsubsection{发行版C\TeX{}对环境变量的影响} + + +如果你曾经安装过C\TeX{}现在想要更换为\TeX{} Live 那么请注意,卸载C\TeX{}后, +环境变量Path可能会丢失路径\verb"%SystemRoot%\system32",请自行检查,如果丢失,则 +单击“新建”,手动添加该路径到环境变量Path中。此外,如果环境变量中有mingw或jdk相关的内容,也请暂时删除,安装之后再添加到\TeX{} Live的环境变量的后面。 + +特别提醒,如果电脑里安装了2345好压\footnote{\textcolor{red}{警告!请务必远离所有带“2345”的软件,并且卸载时要时刻小心文字游戏!必要时借助强力卸载工具。}}这个压缩软件,也会对安装构成影响,建议卸载并更换其他压缩软件 +\footnote{推荐\href{https://sourceforge.net/projects/sevenzip/}{7-Zip},\href{https://www.bandisoft.com/bandizip/}{Bandizip 6.27-6.29}或\href{http://www.winrar.com.cn/}{WinRAR}。}。 + +本部分详细内容见《install-latex-guide-zh-cn》的开头。 + + + +\subsubsection{添加到Path} +如果我们想让某个程序能够通过“运行”或者在命令行下直接运行,有两种方法。第一种方法是把这个程序 +添加到环境变量Path指明的目录中比如提到过的system32文件夹,但这样不方便管理。 +第二种方法是把这个程序所在的目录加入到环境变量Path,\emph{这就是许多教程中的“添加xx到Path”}。 -\subsection{编码} +在把一个程序添加到Path时,首先要找到那个程序的存放路径,方法同\ref{subsub:cz}节的Step1,然后通过\ref{subsub:hjbl}节开头的操作步骤打开环境变量,并且在Path条目里点击 +“新建”,将路径粘贴进去后,先按回车键再点击确定,这样就添加完成。 + +有许多强力开源软件或框架\emph{只能使用命令行}操作,如Git\footnote{本手册的编写依靠它进行协作\url{https://git-scm.com/downloads}},Pandoc\footnote{强力格式转换\url{https://pandoc.org}},FFmpeg\footnote{多媒体视频处理软件,许多软件里都有\url{https://ffmpeg.org}}, +Hexo\footnote{基于Git的开源博客框架\url{https://hexo.io/zh-cn/index.html}} +在安装时,如果有安装包,运行时就会自动添加相关的路径到Path,如果只有运行程序,就需要自己把程序的目录添加到Path, +这之后才能通过命令行在任意路径下使用。细心的同学可以发现在\ref{subsub:pa}节的第二张图(其实是我的电脑里的Path的截图)中有许多的软件, +比如Matlab,Pandoc,Git,Octave,FFmpeg,Python。 + +实际上,与\LaTeX{}相同,安装其他编程语言比如C,Python时,其实主要也是两步, +首先把编译器放到一个指定的文件夹,然后把这个文件夹的路径添加到Path中,而安装包,实际上是将这个过程包装好方便用户使用! + +请特别注意,有些程序的安装包默认不把路径添加到Path,比如Visual Studio Code和Python,而是在安装时作为可选项,因此安装时 +\emph{千万不要无脑点击下一步!}而是要注意勾选“添加到Path(Add to the Path)”。 + + +\subsection{编码}\label{bm} 当你打开某些文件时,你可能发现眼前是完全无法阅读的一团乱码(比如用TeXstudio打开邓老师的旧模版),这里涉及到了编码的问题, -下面的介绍主要参考了这个视频:\href{https://www.bilibili.com/video/BV1ai4y1x7Uz?spm_id_from=333.999.0.0}{『教程』文字频频乱码 这背后是显卡的扭曲还是规则的沦丧?} +下面的介绍主要参考了这个视频:\href{https://www.bilibili.com/video/BV1ai4y1x7Uz?spm_id_from=333.999.0.0}{『教程』文字频频乱码,这背后是显卡的扭曲还是规则的沦丧?} + + + +\subsubsection{编码——数字与文字的一一对应} + + +人类社会不仅有语言,还有各种各样的文字,承载了大量的信息,但计算机内部储存的全是二进制的0和1,如何在计算机中储存文字呢? + +计算机最早诞生在美国,因此我们从英语开始。虽然美国人在做研究和说瞎话时用到的单词很多,但所有英语单词都是由26个字母组成的, +只要通过设计,让数字能够代表每一个字母,也就是建立26个字母与0和1组成的二进制代码的一一对应关系(这是一个双射!),计算机就能处理文字了。 + +于是,当时的科学家设计了一张表,给每一个字母(区分大小写)或符号分配一个数字,这个数字称为该字符的\emph{编码}。比如,A在这个表上对应的数字为65(在计算机里为二进制数1000001) +这张表还有一个名字,叫做\emph{美国信息交换标准代码,简称ASCII\footnote{American Standard Code for Information Interchange}} + +随着时间的推移,计算机在全世界传播开来,不同的国家和地区针对自己的文字也设计了对应的编码表,比如中国设计了中文的编码表\emph{GBK},还有一个近义词叫\emph{GB 2312}.但与英文不同,汉字的 +个数非常多,因此这张表很大。在中国大陆使用的Windows系统简体中文版,处理字符时默认采用GBK编码方式;中国台湾\emph{省}也有一张编码表叫做\emph{Big5}针对繁体中文。 + + + +\subsubsection{乱码问题与Unicode编码} +各个国家和地区在设计编码表时都是相互独立进行的,因此,同一段二进制代码在不同的编码表上,几乎不可能对应相同的文字。 +一段文字在A国的电脑上保存时,A国电脑上的Windows系统会默认按A国的编码表把每一个字符对应的编码储存到文件里,但是,当这个文件 +在B国的电脑上打开时,B国电脑上的Windows系统读取这些编码时,却会默认按照B国的编码表反推这些编码对应的字符,结果自然而然 +显示出一堆乱七八糟的无意义文字,这种现象就叫做\emph{乱码}! + +不同国家和地区间交换文件,不同操作系统间交换文件,都有可能出现类似的乱码情况。 +\emph{乱码的本质,就是对于相同的数字编码,却用不同的编码表反推对应的字符。}这样得到的结果当然不一样,就像 +破译密码时拿错了密码本。 + +显然,乱码问题阻碍了国际交流,一个国际组织另起炉灶,设计了一张特别大的表,叫做\emph{Unicode},这张表足够大,可以包含全人类所有的字符,这样,只要采用 +这张编码表,就不会出现乱码的问题了。但在对字符分配编码的方式上,出现了许多标准,其中有一种方式是目前的主流,叫做\emph{UTF-8}。 + +不同的编码还给编程带来了许多麻烦,你也许听过这样的说法“安装xx时,路径不能含有中文”,“在编程时,文件夹和源代码都不能含有中文”,“系统用户名不能含有中文”。 +这些问题的根源都在于简体中文版Windows系统默认采用GBK编码,而一些程序可能不支持GBK,这就产生了各种各样的问题!比如 +在安装\TeX{} Live 2021时,如果系统用户名含有中文,就可能导致无法安装,解决方法还是参见《install-latex-guide-zh-cn》的1.1.3节。 + +然而,Mac系统却很少出现上一段的这些麻烦的问题,这是因为Mac系统默认采用UTF-8编码,兼容性好,因此Mac是非常适合编程的电脑。 +一些厉害的程序员使用Mac系统编程,某些大型互联网公司甚至提供Mac作为办公电脑。 -人类语言有各种各样文字,承载了大量的信息,那么如何在计算机中储存文字呢,由于计算机内部只有0和1,故问题转化为用数字表示文字,科学家通过建立数字和文字的一一映射, -比如英语是由26个字母组成的 +\subsubsection{\LaTeX{}中的编码问题}\label{subsub:labmwt} + + +许多编程语言都对源代码采用的编码方式有要求,否则无法正常编译,比如Python要求代码采用UTF-8编码方式。\LaTeX{} +比较特别,与发行版,编译引擎以及是否输入中文有关。 + +最早的\TeX{}系统只支持ASCII编码,但可以通过设置使得扩展ASCII编码能正常排版。在排版英文文档时, +可以直接使用pdflatex方式进行排版。 + +为了使得\LaTeX{}能够排版中文,Werner Lemberg开发了CJK\footnote{CJK实际上是中日韩三国语言英文单词的首字母}宏包。 +由于汉字编码方式GB 2312,GBK和UTF-8都是兼容ASCII的编码,通过CJK宏包,可以把多个字符 +对应到一个汉字上,支持中文的排版,在实际使用时,只要加载了CJK宏包,就可以使用pdflatex +方式进行排版。发行版CTEX支持这种方式排版中文文档,同时也是邓老师的旧模板采用的处理方式。 + +这种处理方法要求源文件采用GBK编码方式,存在许多问题,简单列举几个: +\begin{enumerate} + \item CJK宏包的这种方法是一种黑客手段,没有彻底解决中文排版的问题,采用这种方式编译得到的PDF文件,其中的中文字符复制出来全是乱码! + 许多老师用C\TeX{}做的课件,里面的汉字都无法正常复制。 + \item 上面的这个问题,导致17级的同学在论文查重时,查重报告乱码! + \item C\TeX{}目前只支持Windows系统,旧模板无法在Mac和Linux系统上使用! + \item C\TeX{}已经停止更新,论坛已经关闭,许多遗留的bug没有修复,新的功能无法使用,网上正确且有效的资料少(英文资源几乎为零)! +\end{enumerate} +更多问题详见\href{https://zhuanlan.zhihu.com/p/45174503}{2018年,为什么不推荐使用 CTeX 套装了}。 + +新排版引擎\XeTeX{}和Lua\TeX{}都直接支持UTF-8编码,新的中文排版方式应运而生,孙文昌开发了xeCJK宏包,配合 +xelatex方式进行中文排版,后来又出现了功能更强大的ctex宏集。\emph{新模版使用的就是这种方式,源文件采用 +UTF-8编码方式,利用ctex宏集,xelatex方式进行编译}。解决了原有方式存在的许多问题。 + +因此,新旧模板的源代码的编码方式不同!但主流通用的代码编辑器默认都是UTF-8编码,比如TeXstudio,Visual Studio Code。 +因此打开旧模板时,会直接乱码,要么采用记事本等文本编辑器,要么更改文件的编码,这就带来了许多麻烦。 + + + +\subsubsection{更改文件的编码} + + +通过上面的内容我们知道,当遇到乱码时或者编程语言对编码有要求时,我们都需要更改文件的编码方式。 +手册《install-latex-guide-zh-cn》的第5.1.2节中提供了通过TeXstudio更改tex文件的编码方式的方法,该教程 +基于英文版的TeXstudio,如果已经把界面设置为中文,请自行对照相应按键。 + +下面介绍使用记事本更改编码的方法: +\begin{enumerate} + \item 找到要修改的文件,单击右键,选择“打开方式”,然后选择使用记事本打开。 + \item 菜单栏点击文件,选择另存为,在下方的编码选项中将其改为UTF-8。 + \item 最后点击保存,得到的新文件就会以UTF-8方式编码,原文件编码方式不变。 +\end{enumerate} +\begin{center} + \includegraphics[scale=0.5]{16.png} +\end{center} + +记事本在保存时,默认的编码为ANSI,表示当地计算机的默认编码,在中国大陆就是GBK! +因此使用记事本写代码容易因为编码而不能编译,而许多代码编辑器默认都是UTF-8编码,这 +又是一个不推荐使用记事本写代码的理由。 \subsection{PDF阅读器} @@ -206,13 +419,17 @@ \subsubsection{Adobe Acrobat Reader} 支持PDF的所有功能(如JavaScript脚本、动画、3D对象等),\LaTeX{}的一些高级功能的效果只有使用这个阅读器才能完全显示。并且 可以查看PDF的许多属性比如使用的字体,在精细排版中会用到。 -但有两个缺点,首先,安装时强制安在C盘,所以要记得腾空间。其次,\emph{Adobe Acrobat Reader会锁定PDF!在 +但有两个缺点,首先,安装时会强制安装在C盘,所以要记得腾空间。其次,\emph{Adobe Acrobat Reader会锁定PDF!在 Windows中重复编译时,要先关闭已经由Adobe Reader打开的PDF文档,否则PDF文件会被锁定而不能更新(同时会报错)},因此 一般在写论文途中采用其他的PDF阅读器。 下载地址:\url{https://www.adobe.com/cn/acrobat/pdf-reader.html} + + \subsubsection{SumatraPDF} -SumatraPDF是一个很小的开源PDF阅读器,具有免安装版,可以放在U盘随身携带,并且打开速度非常快,适合在写作途中查看文档效果, + + +SumatraPDF是一个很小的开源PDF阅读器,具有免安装版(Portable),可以放在U盘随身携带,并且打开速度非常快,适合在写作途中查看文档效果, 可以通过设置使得PDF可以反向搜索(定位到对应的代码)。当然,如果只是预览,Texwork编译后会自动弹出预览窗口。 下载地址:\url{https://www.sumatrapdfreader.org/download-free-pdf-viewer}\\或\url{https://sourceforge.net/projects/sumatrapdf-reader.mirror/} diff --git a/manual-body/basic-latex-knowledge.tex b/manual-body/basic-latex-knowledge.tex index 4c4fb13..bb29314 100644 --- a/manual-body/basic-latex-knowledge.tex +++ b/manual-body/basic-latex-knowledge.tex @@ -4,7 +4,7 @@ \subsection{安装相关} 因为没有用过Linux系统,所以下面仅针对Windows系统和Mac系统展开,Linux系统是类似的。 -\subsubsection{ 安装 \TeX Live } +\subsubsection{ 安装 \TeX{} Live } 安装必读的中文官方文档:\href{https://gitee.com/OsbertWang/install-latex-guide-zh-cn/releases}{install-latex-guide-zh-cn} 这篇文档已经千锤百炼,非常成熟了。其中Windows用户遇到的问题是最多的,Windows用户一定要\emph{先把Windows系统的部分完整认真读完再去跟着安装},要心里有数,自己的电脑是个什么状态。 @@ -20,11 +20,12 @@ \subsubsection{ 安装外置PDF阅读器 } \subsubsection{ 安装 Visual Studio Code } -虽然你安装完 \TeX Live 后会有一个编辑器,但是个人是非常推荐使用Visual Studio Code的,有几个理由: +虽然你安装完 \TeX{} Live 后会有一个编辑器,但是个人是非常推荐使用Visual Studio Code的,有几个理由: \begin{enumerate} - \item Visual Studio Code打开速度快,比 \TeX studio 是肉眼可见地快 - \item 配置非常简单,下载一个插件,把别人弄好的 + \item Visual Studio Code打开速度快,比 \TeX{}studio 是肉眼可见地快。 + \item 配置非常简单,下载一个插件LaTeX Workshop,把别人弄好的配置文件代码复制粘贴后即可使用。 + \item 详细配置教程详见 \href{https://zhuanlan.zhihu.com/p/38178015?utm_source=qq&utm_medium=social&utm_oi=1122597840500740096}{使用VSCode编写LaTeX}。 \end{enumerate} diff --git a/manual-figure/12.png b/manual-figure/12.png new file mode 100644 index 0000000..0fc5021 Binary files /dev/null and b/manual-figure/12.png differ diff --git a/manual-figure/13.png b/manual-figure/13.png new file mode 100644 index 0000000..bd90b38 Binary files /dev/null and b/manual-figure/13.png differ diff --git a/manual-figure/14.png b/manual-figure/14.png new file mode 100644 index 0000000..639e6aa Binary files /dev/null and b/manual-figure/14.png differ diff --git a/manual-figure/15.png b/manual-figure/15.png new file mode 100644 index 0000000..b71b932 Binary files /dev/null and b/manual-figure/15.png differ diff --git a/manual-figure/16.png b/manual-figure/16.png new file mode 100644 index 0000000..8c0c5d0 Binary files /dev/null and b/manual-figure/16.png differ diff --git a/tabularray.sty b/tabularray.sty deleted file mode 100644 index f5ad547..0000000 --- a/tabularray.sty +++ /dev/null @@ -1,6743 +0,0 @@ -%%% % -*- coding: utf-8 -*- -%%% ---------------------------------------------------------------------------- -%%% Tabularray: Typeset tabulars and arrays with LaTeX3 -%%% Author : Jianrui Lyu -%%% Repository: https://github.com/lvjr/tabularray -%%% License : The LaTeX Project Public License 1.3 -%%% ---------------------------------------------------------------------------- - -%%% -------------------------------------------------------- -%% \section{Scratch Variables and Function Variants} -%%% -------------------------------------------------------- - -\NeedsTeXFormat{LaTeX2e} -\RequirePackage{expl3} -\ProvidesExplPackage{tabularray}{2021-12-01}{2021Q} - {Typeset tabulars and arrays with LaTeX3} - -\RequirePackage{xparse} - -\AtBeginDocument{\@ifpackageloaded{xcolor}{\RequirePackage{ninecolors}}{}} - -%% Backport \tl_if_eq:NnTF for old texlive 2020 -\cs_if_exist:NF \tl_if_eq:NnTF - { - \tl_new:N \l__tblr_backport_b_tl - \prg_new_protected_conditional:Npnn \tl_if_eq:Nn #1 #2 { T, F, TF } - { - \group_begin: - \tl_set:Nn \l__tblr_backport_b_tl {#2} - \exp_after:wN - \group_end: - \if_meaning:w #1 \l__tblr_backport_b_tl - \prg_return_true: - \else: - \prg_return_false: - \fi: - } - \prg_generate_conditional_variant:Nnn \tl_if_eq:Nn { c } { TF, T, F } - } - -%% Compatible with texlive 2020 -\cs_if_exist:NF \seq_map_indexed_function:NN - { - \cs_set_eq:NN \seq_map_indexed_function:NN \seq_indexed_map_function:NN - } - -\cs_generate_variant:Nn \msg_error:nnnn { nnVn } -\cs_generate_variant:Nn \prop_item:Nn { Ne, NV } -\cs_generate_variant:Nn \prop_put:Nnn { Nxn, Nxx, NxV } -\cs_generate_variant:Nn \regex_replace_all:NnN { NVN } -\cs_generate_variant:Nn \seq_map_indexed_inline:Nn { cn } -\cs_generate_variant:Nn \tl_const:Nn { ce } -\cs_generate_variant:Nn \tl_log:n { x } -\cs_generate_variant:Nn \tl_gput_right:Nn { Nf } -\cs_generate_variant:Nn \tl_put_left:Nn { Nv } -\prg_generate_conditional_variant:Nnn \clist_if_in:Nn { Nx } { TF } -\prg_generate_conditional_variant:Nnn \prop_if_in:Nn { c } { T } -\prg_generate_conditional_variant:Nnn \str_if_eq:nn { xn } { TF } -\prg_generate_conditional_variant:Nnn \tl_if_eq:nn { en } { T, TF } -\prg_generate_conditional_variant:Nnn \tl_if_head_eq_catcode:nN { VN } { TF } -\prg_generate_conditional_variant:Nnn \tl_if_head_eq_meaning:nN { VN } { T, TF } - -\tl_new:N \l__tblr_a_tl -\tl_new:N \l__tblr_b_tl -\tl_new:N \l__tblr_c_tl -\tl_new:N \l__tblr_d_tl -\tl_new:N \l__tblr_e_tl -\tl_new:N \l__tblr_f_tl -\tl_new:N \l__tblr_h_tl -\tl_new:N \l__tblr_i_tl % for row index -\tl_new:N \l__tblr_j_tl % for column index -\tl_new:N \l__tblr_k_tl -\tl_new:N \l__tblr_n_tl -\tl_new:N \l__tblr_o_tl -\tl_new:N \l__tblr_r_tl -\tl_new:N \l__tblr_s_tl -\tl_new:N \l__tblr_t_tl -\tl_new:N \l__tblr_u_tl -\tl_new:N \l__tblr_v_tl -\tl_new:N \l__tblr_w_tl -\tl_new:N \l__tblr_x_tl -\tl_new:N \l__tblr_y_tl -\int_new:N \l__tblr_a_int -\int_new:N \l__tblr_c_int % for column number -\int_new:N \l__tblr_r_int % for row number -\dim_new:N \l__tblr_d_dim % for depth -\dim_new:N \l__tblr_h_dim % for height -\dim_new:N \l__tblr_o_dim -\dim_new:N \l__tblr_p_dim -\dim_new:N \l__tblr_q_dim -\dim_new:N \l__tblr_r_dim -\dim_new:N \l__tblr_s_dim -\dim_new:N \l__tblr_t_dim -\dim_new:N \l__tblr_v_dim -\dim_new:N \l__tblr_w_dim % for width -\box_new:N \l__tblr_a_box -\box_new:N \l__tblr_b_box -\box_new:N \l__tblr_c_box % for cell box -\box_new:N \l__tblr_d_box - -%% Total number of tblr tables -\int_new:N \g__tblr_table_count_int - -%% Some commands for horizontal alignment -\cs_new_eq:NN \__tblr_halign_command_l: \raggedright -\cs_new_eq:NN \__tblr_halign_command_c: \centering -\cs_new_eq:NN \__tblr_halign_command_r: \raggedleft - -%% Some counters for row and column numbering. -%% We may need to restore all LaTeX counters in measuring and building cells, -%% so we must not define these counters with \newcounter command. -\int_new:N \c@rownum -\int_new:N \c@colnum -\int_new:N \c@rowcount -\int_new:N \c@colcount - -%% Add missing \therownum, \thecolnum, \therowcount, \thecolcount (issue #129) -\NewExpandableDocumentCommand \therownum {} { \@arabic \c@rownum } -\NewExpandableDocumentCommand \thecolnum {} { \@arabic \c@colnum } -\NewExpandableDocumentCommand \therowcount {} { \@arabic \c@rowcount } -\NewExpandableDocumentCommand \thecolcount {} { \@arabic \c@colcount } - -%% Some dimensions for row and column spacing -\dim_new:N \abovesep -\dim_new:N \belowsep -\dim_new:N \leftsep -\dim_new:N \rightsep - -%%% -------------------------------------------------------- -%% \section{Data Structures Based on Property Lists} -%%% -------------------------------------------------------- - -\int_new:N \g_tblr_level_int % store table nesting level - -\cs_new_protected:Npn \__tblr_clear_prop_lists: - { - \prop_gclear_new:c { g__tblr_text_ \int_use:N \g_tblr_level_int _prop } - \prop_gclear_new:c { g__tblr_command_ \int_use:N \g_tblr_level_int _prop } - \prop_gclear_new:c { g__tblr_inner_ \int_use:N \g_tblr_level_int _prop } - \prop_gclear_new:c { g__tblr_note_ \int_use:N \g_tblr_level_int _prop } - \prop_gclear_new:c { g__tblr_remark_ \int_use:N \g_tblr_level_int _prop } - \prop_gclear_new:c { g__tblr_more_ \int_use:N \g_tblr_level_int _prop } - \prop_gclear_new:c { g__tblr_row_ \int_use:N \g_tblr_level_int _prop } - \prop_gclear_new:c { g__tblr_column_ \int_use:N \g_tblr_level_int _prop } - \prop_gclear_new:c { g__tblr_cell_ \int_use:N \g_tblr_level_int _prop } - \prop_gclear_new:c { g__tblr_hline_ \int_use:N \g_tblr_level_int _prop } - \prop_gclear_new:c { g__tblr_vline_ \int_use:N \g_tblr_level_int _prop } - } - -\cs_new_protected:Npn \__tblr_prop_gput:nnn #1 #2 #3 - { - \prop_gput:cnn - { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 } { #3 } - } -\cs_generate_variant:Nn \__tblr_prop_gput:nnn { nnx, nnV, nxn, nxx, nxV } - -\cs_new:Npn \__tblr_prop_item:nn #1 #2 - { - \prop_item:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 } - } -\cs_generate_variant:Nn \__tblr_prop_item:nn { ne } - -\cs_new_protected:Npn \__tblr_prop_if_in:nnT #1 - { - \prop_if_in:cnT { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } - } -\cs_new_protected:Npn \__tblr_prop_if_in:nnF #1 - { - \prop_if_in:cnF { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } - } -\cs_new_protected:Npn \__tblr_prop_if_in:nnTF #1 - { - \prop_if_in:cnTF { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } - } -\prg_generate_conditional_variant:Nnn \__tblr_prop_if_in:nn { nx } { T, F, TF } - -\cs_new_protected:Npn \__tblr_prop_log:n #1 - { - \prop_log:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } - } - -\cs_new_protected:Npn \__tblr_prop_map_inline:nn #1 #2 - { - \prop_map_inline:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } {#2} - } - -\cs_new_protected:Npn \__tblr_prop_gput_if_larger:nnn #1 #2 #3 - { - \__tblr_gput_if_larger:cnn - { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 } { #3 } - } -\cs_generate_variant:Nn \__tblr_prop_gput_if_larger:nnn { nnx, nnV, nxn, nxx, nxV } - -\cs_new_protected:Npn \__tblr_prop_gadd_dimen_value:nnn #1 #2 #3 - { - \__tblr_gadd_dimen_value:cnn - { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 } { #3 } - } -\cs_generate_variant:Nn \__tblr_prop_gadd_dimen_value:nnn { nnx, nnV, nxn, nxx } - -%% Put the dimension to the prop list only if it's larger than the old one - -\tl_new:N \l__tblr_put_if_larger_tl - -\cs_new_protected:Npn \__tblr_put_if_larger:Nnn #1 #2 #3 - { - \tl_set:Nx \l__tblr_put_if_larger_tl { \prop_item:Nn #1 { #2 } } - \bool_lazy_or:nnT - { \tl_if_empty_p:N \l__tblr_put_if_larger_tl } - { \dim_compare_p:nNn { #3 } > { \l__tblr_put_if_larger_tl } } - { \prop_put:Nnn #1 { #2 } { #3 } } - } -\cs_generate_variant:Nn \__tblr_put_if_larger:Nnn { Nnx, Nxn, Nxx, NnV } - -\cs_new_protected:Npn \__tblr_gput_if_larger:Nnn #1 #2 #3 - { - \tl_set:Nx \l__tblr_put_if_larger_tl { \prop_item:Nn #1 { #2 } } - \bool_lazy_or:nnT - { \tl_if_empty_p:N \l__tblr_put_if_larger_tl } - { \dim_compare_p:nNn { #3 } > { \l__tblr_put_if_larger_tl } } - { \prop_gput:Nnn #1 { #2 } { #3 } } - } -\cs_generate_variant:Nn \__tblr_gput_if_larger:Nnn { Nnx, Nxn, Nxx, cnn } - -%% Add the dimension to some key value of the prop list -%% #1: the prop list, #2: the key, #3: the dimen to add - -\cs_new_protected:Npn \__tblr_add_dimen_value:Nnn #1 #2 #3 - { - \prop_put:Nnx #1 { #2 } { \dim_eval:n { \prop_item:Nn #1 { #2 } + #3 } } - } -\cs_generate_variant:Nn \__tblr_add_dimen_value:Nnn { cnn } - -\cs_new_protected:Npn \__tblr_gadd_dimen_value:Nnn #1 #2 #3 - { - \prop_gput:Nnx #1 { #2 } { \dim_eval:n { \prop_item:Nn #1 { #2 } + #3 } } - } -\cs_generate_variant:Nn \__tblr_gadd_dimen_value:Nnn { cnn } - -%%% -------------------------------------------------------- -%% \section{Data Structures Based on Token Lists} -%%% -------------------------------------------------------- - -\cs_new_protected:Npn \__tblr_clear_spec_lists: - { - %\__tblr_clear_one_spec_lists:n { row } - %\__tblr_clear_one_spec_lists:n { column } - %\__tblr_clear_one_spec_lists:n { cell } - \__tblr_clear_one_spec_lists:n { text } - \__tblr_clear_one_spec_lists:n { hline } - \__tblr_clear_one_spec_lists:n { vline } - \__tblr_clear_one_spec_lists:n { outer } - } - -\cs_new_protected:Npn \__tblr_clear_one_spec_lists:n #1 - { - \clist_if_exist:cTF { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist } - { - \clist_map_inline:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist } - { - \tl_gclear:c { g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_##1_tl } - } - } - { \clist_new:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist } } - } - -\cs_new_protected:Npn \__tblr_spec_gput:nnn #1 #2 #3 - { - \tl_gset:cn - { g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_#2_tl } {#3} - \clist_gput_right:cx { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist } {#2} - } -\cs_generate_variant:Nn \__tblr_spec_gput:nnn { nne, nnV, nen, nee, neV } - -\cs_new:Npn \__tblr_spec_item:nn #1 #2 - { - \tl_if_exist:cT { g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_#2_tl } - { - \exp_args:Nv \exp_not:n - { g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_#2_tl } - } - } -\cs_generate_variant:Nn \__tblr_spec_item:nn { ne } - -\cs_new_protected:Npn \__tblr_spec_gput_if_larger:nnn #1 #2 #3 - { - \tl_set:Nx \l__tblr_put_if_larger_tl { \__tblr_spec_item:nn {#1} {#2} } - \bool_lazy_or:nnT - { \tl_if_empty_p:N \l__tblr_put_if_larger_tl } - { \dim_compare_p:nNn {#3} > { \l__tblr_put_if_larger_tl } } - { \__tblr_spec_gput:nnn {#1} {#2} {#3} } - } -\cs_generate_variant:Nn \__tblr_spec_gput_if_larger:nnn { nne, nnV, nen, nee, neV } - -\cs_new_protected:Npn \__tblr_spec_gadd_dimen_value:nnn #1 #2 #3 - { - \__tblr_spec_gput:nne {#1} {#2} - { \dim_eval:n { \__tblr_spec_item:ne {#1} {#2} + #3 } } - } -\cs_generate_variant:Nn \__tblr_spec_gadd_dimen_value:nnn { nne, nnV, nen, nee } - -\cs_new_protected:Npn \__tblr_spec_log:n #1 - { - \clist_gremove_duplicates:c - { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist } - \tl_log:x - { - The ~ spec ~ list ~ #1 _ \int_use:N \g_tblr_level_int - \space contains ~ the ~ pairs: - } - \clist_map_inline:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist } - { - \tl_log:x - { - \space { ##1 } ~\space=>~\space { \__tblr_spec_item:nn {#1} {##1} } - } - } - } - -%%% -------------------------------------------------------- -%% \section{Data Structures Based on Integer Arrays} -%%% -------------------------------------------------------- - -\msg_new:nnn { tabularray } { intarray-beyond-bound } - { Position ~ #2 ~ is ~ beyond ~ the ~ bound ~ of ~ intarray ~ #1.} - -\cs_new_protected:Npn \__tblr_intarray_gset:Nnn #1 #2 #3 - { - \bool_lazy_or:nnTF - { \int_compare_p:nNn {#2} < {0} } - { \int_compare_p:nNn {#2} > {\intarray_count:N #1} } - { - \bool_if:NT \g__tblr_tracing_intarray_bool - { \msg_warning:nnnn { tabularray } { intarray-beyond-bound } {#1} {#2} } - } - { \intarray_gset:Nnn #1 {#2} {#3} } - } -\cs_generate_variant:Nn \__tblr_intarray_gset:Nnn { cnn } - -%% #1: data name; #2: key name; #3: value type -\cs_new_protected:Npn \__tblr_data_new_key:nnn #1 #2 #3 - { - \int_gincr:c { g__tblr_data_#1_key_count_int } - \tl_const:ce - { - g__tblr_data_#1_key_name_ - \int_use:c { g__tblr_data_#1_key_count_int } _tl - } - { #2 } - \tl_const:ce { g__tblr_data_#1_key_number_#2_tl } - { \int_use:c { g__tblr_data_#1_key_count_int } } - \tl_const:cn { g__tblr_data_#1_key_type_#2_tl } {#3} - } - -\int_new:N \g__tblr_data_row_key_count_int -\__tblr_data_new_key:nnn { row } { height } { dim } -\__tblr_data_new_key:nnn { row } { coefficient } { dec } -\__tblr_data_new_key:nnn { row } { abovesep } { dim } -\__tblr_data_new_key:nnn { row } { belowsep } { dim } -\__tblr_data_new_key:nnn { row } { @row-height } { dim } -\__tblr_data_new_key:nnn { row } { @row-head } { dim } -\__tblr_data_new_key:nnn { row } { @row-foot } { dim } -\__tblr_data_new_key:nnn { row } { @row-upper } { dim } -\__tblr_data_new_key:nnn { row } { @row-lower } { dim } -\__tblr_data_new_key:nnn { row } { break } { int } - -\int_new:N \g__tblr_data_column_key_count_int -\__tblr_data_new_key:nnn { column } { width } { dim } -\__tblr_data_new_key:nnn { column } { coefficient } { dec } -\__tblr_data_new_key:nnn { column } { leftsep } { dim } -\__tblr_data_new_key:nnn { column } { rightsep } { dim } -\__tblr_data_new_key:nnn { column } { @col-width } { dim } - -\int_new:N \g__tblr_data_cell_key_count_int -\__tblr_data_new_key:nnn { cell } { width } { dim } -\__tblr_data_new_key:nnn { cell } { rowspan } { int } -\__tblr_data_new_key:nnn { cell } { colspan } { int } -\__tblr_data_new_key:nnn { cell } { halign } { str } -\__tblr_data_new_key:nnn { cell } { valign } { str } -\__tblr_data_new_key:nnn { cell } { background } { str } -\__tblr_data_new_key:nnn { cell } { foreground } { str } -\__tblr_data_new_key:nnn { cell } { font } { str } -\__tblr_data_new_key:nnn { cell } { mode } { str } -\__tblr_data_new_key:nnn { cell } { cmd } { str } -\__tblr_data_new_key:nnn { cell } { omit } { int } -\__tblr_data_new_key:nnn { cell } { @cell-width } { dim } -\__tblr_data_new_key:nnn { cell } { @cell-height } { dim } -\__tblr_data_new_key:nnn { cell } { @cell-depth } { dim } - -\clist_const:Nn \g__tblr_data_clist { row, column, cell } -\tl_const:Nn \g__tblr_data_row_count_tl { \c@rowcount } -\tl_const:Nn \g__tblr_data_column_count_tl { \c@colcount } -\tl_const:Nn \g__tblr_data_cell_count_tl { \c@rowcount * \c@colcount } -\tl_const:Nn \g__tblr_data_row_index_number_tl {1} -\tl_const:Nn \g__tblr_data_column_index_number_tl {1} -\tl_const:Nn \g__tblr_data_cell_index_number_tl {2} -\int_new:N \g__tblr_array_int - -\cs_new_protected:Npn \__tblr_init_table_data: - { - \clist_map_function:NN \g__tblr_data_clist \__tblr_init_one_data:n - } - -\cs_new_protected:Npn \__tblr_init_one_data:n #1 - { - \int_gincr:N \g__tblr_array_int - \intarray_new:cn { g__tblr_#1_ \int_use:N \g__tblr_array_int _intarray } - { - \int_use:c { g__tblr_data_#1_key_count_int } - * \tl_use:c { g__tblr_data_#1_count_tl } - } - \cs_set_eq:cc { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray } - { g__tblr_#1_ \int_use:N \g__tblr_array_int _intarray } - %\intarray_log:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray } - } - -%% #1: data name; #2: data index; #3: key name -\cs_new:Npn \__tblr_data_key_to_int:nnn #1 #2 #3 - { - ( #2 - 1 ) * \int_use:c { g__tblr_data_#1_key_count_int } - + \tl_use:c { g__tblr_data_#1_key_number_#3_tl } - } - -%% #1: data name; #2: data index 1; #3: data index 2; #4: key name -\cs_new:Npn \__tblr_data_key_to_int:nnnn #1 #2 #3 #4 - { - ( #2 - 1 ) * \c@colcount * \int_use:c { g__tblr_data_#1_key_count_int } - + ( #3 - 1 ) * \int_use:c { g__tblr_data_#1_key_count_int } - + \tl_use:c { g__tblr_data_#1_key_number_#4_tl } - } - -\int_new:N \l__tblr_key_count_int -\int_new:N \l__tblr_key_quotient_int -\int_new:N \l__tblr_key_quotient_two_int -\int_new:N \l__tblr_key_remainder_int - -%% #1: data name; #2: array position; -%% #3: returning tl with index; #4: returning tl with key name -\cs_new:Npn \__tblr_data_int_to_key:nnNN #1 #2 #3 #4 - { - \int_set_eq:Nc \l__tblr_key_count_int { g__tblr_data_#1_key_count_int } - \int_set:Nn \l__tblr_key_quotient_int - { - \int_div_truncate:nn - { #2 + \l__tblr_key_count_int - 1 } { \l__tblr_key_count_int } - } - \int_set:Nn \l__tblr_key_remainder_int - { - #2 + \l__tblr_key_count_int - - \l__tblr_key_quotient_int * \l__tblr_key_count_int - } - \int_compare:nNnT { \l__tblr_key_remainder_int } = { 0 } - { \int_set_eq:NN \l__tblr_key_remainder_int \l__tblr_key_count_int } - \tl_set:Nx #3 { \int_use:N \l__tblr_key_quotient_int } - \tl_set_eq:Nc #4 - { g__tblr_data_#1_key_name_ \int_use:N \l__tblr_key_remainder_int _tl } - } - -%% #1: data name; #2: array position; -%% #3: returning tl with index 1; #4: returning tl with index 2; -%% #5: returning tl with key name -\cs_new:Npn \__tblr_data_int_to_key:nnNNN #1 #2 #3 #4 #5 - { - \int_set_eq:Nc \l__tblr_key_count_int { g__tblr_data_#1_key_count_int } - \int_set:Nn \l__tblr_key_quotient_int - { - \int_div_truncate:nn - { #2 + \l__tblr_key_count_int - 1 } { \l__tblr_key_count_int } - } - \int_set:Nn \l__tblr_key_remainder_int - { - #2 + \l__tblr_key_count_int - - \l__tblr_key_quotient_int * \l__tblr_key_count_int - } - \int_compare:nNnT { \l__tblr_key_remainder_int } = { 0 } - { \int_set_eq:NN \l__tblr_key_remainder_int \l__tblr_key_count_int } - \tl_set_eq:Nc #5 - { g__tblr_data_#1_key_name_ \int_use:N \l__tblr_key_remainder_int _tl } - \int_set:Nn \l__tblr_key_quotient_two_int - { - \int_div_truncate:nn - { \l__tblr_key_quotient_int + \c@colcount - 1 } { \c@colcount } - } - \int_set:Nn \l__tblr_key_remainder_int - { - \l__tblr_key_quotient_int + \c@colcount - - \l__tblr_key_quotient_two_int * \c@colcount - } - \int_compare:nNnT { \l__tblr_key_remainder_int } = { 0 } - { \int_set_eq:NN \l__tblr_key_remainder_int \c@colcount } - \tl_set:Nx #4 { \int_use:N \l__tblr_key_remainder_int } - \tl_set:Nx #3 { \int_use:N \l__tblr_key_quotient_two_int } - } - -\tl_new:N \g__tblr_data_int_from_value_tl - -%% #1: data name; #2: key name; #3: value -%% The result will be stored in \g__tblr_data_int_from_value_tl -\cs_new_protected:Npn \__tblr_data_int_from_value:nnn #1 #2 #3 - { - \cs:w - __tblr_data_int_from_ \tl_use:c { g__tblr_data_#1_key_type_#2_tl } :n - \cs_end: - {#3} - } - -%% #1: data name; #2: key name; #3: int -\cs_new:Npn \__tblr_data_int_to_value:nnn #1 #2 #3 - { - \cs:w - __tblr_data_int_to_ \tl_use:c { g__tblr_data_#1_key_type_#2_tl } :n - \cs_end: - {#3} - } -\cs_generate_variant:Nn \__tblr_data_int_to_value:nnn { nne, nVe } - -\cs_new_protected:Npn \__tblr_data_int_from_int:n #1 - { - \tl_gset:Nn \g__tblr_data_int_from_value_tl {#1} - } - -\cs_new:Npn \__tblr_data_int_to_int:n #1 - { - #1 - } - -\cs_new_protected:Npn \__tblr_data_int_from_dim:n #1 - { - \tl_gset:Nx \g__tblr_data_int_from_value_tl { \dim_to_decimal_in_sp:n {#1} } - } - -%% Return a dimension in pt so that it's easier to understand in tracing messages -\cs_new:Npn \__tblr_data_int_to_dim:n #1 - { - %#1 sp - %\dim_eval:n { #1 sp } - \dim_to_decimal:n { #1 sp } pt - } - -\cs_new_protected:Npn \__tblr_data_int_from_dec:n #1 - { - \tl_gset:Nx \g__tblr_data_int_from_value_tl - { \dim_to_decimal_in_sp:n {#1 pt} } - } - -\cs_new:Npn \__tblr_data_int_to_dec:n #1 - { - \dim_to_decimal:n {#1 sp} - } - -\int_new:N \g__tblr_data_str_value_count_int -\tl_set:cn { g__tblr_data_0_to_str_tl } { } - -\cs_new_protected:Npn \__tblr_data_int_from_str:n #1 - { - \tl_if_exist:cTF { g__tblr_data_ \tl_to_str:n {#1} _to_int_tl } - { - \tl_gset_eq:Nc \g__tblr_data_int_from_value_tl - { g__tblr_data_ \tl_to_str:n {#1} _to_int_tl } - } - { - \int_gincr:N \g__tblr_data_str_value_count_int - \tl_gset:cx { g__tblr_data_ \tl_to_str:n {#1} _to_int_tl } - { \int_use:N \g__tblr_data_str_value_count_int } - \tl_gset:cn - { g__tblr_data_ \int_use:N \g__tblr_data_str_value_count_int _to_str_tl } - { \exp_not:n {#1} } - \tl_gset:Nx \g__tblr_data_int_from_value_tl - { \int_use:N \g__tblr_data_str_value_count_int } - } - } - -\cs_new:Npn \__tblr_data_int_to_str:n #1 - { - \tl_use:c { g__tblr_data_#1_to_str_tl } - } - -%% #1: data name; #2: data index; #3: key; #4: value -\cs_new_protected:Npn \__tblr_data_gput:nnnn #1 #2 #3 #4 - { - \__tblr_data_int_from_value:nnn {#1} {#3} {#4} - \__tblr_intarray_gset:cnn - { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray } - { \__tblr_data_key_to_int:nnn {#1} {#2} {#3} } - { \g__tblr_data_int_from_value_tl } - } -\cs_generate_variant:Nn \__tblr_data_gput:nnnn - { nnne, nnnV, nenn, nene, nenV, nVnn } - -%% #1: data name; #2: data index 1; #3: data index 2; #4: key; #5: value -\cs_new_protected:Npn \__tblr_data_gput:nnnnn #1 #2 #3 #4 #5 - { - \__tblr_data_int_from_value:nnn {#1} {#4} {#5} - \__tblr_intarray_gset:cnn - { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray } - { \__tblr_data_key_to_int:nnnn {#1} {#2} {#3} {#4} } - { \g__tblr_data_int_from_value_tl } - } -\cs_generate_variant:Nn \__tblr_data_gput:nnnnn - { nnnne, nnnnV, neenn, neene, neenV, neeen, nVVnn } - -%% #1: data name; #2: data index; #3: key -\cs_new:Npn \__tblr_data_item:nnn #1 #2 #3 - { - \__tblr_data_int_to_value:nne {#1} {#3} - { - \intarray_item:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray } - { \__tblr_data_key_to_int:nnn {#1} {#2} {#3} } - } - } -\cs_generate_variant:Nn \__tblr_data_item:nnn { nen } - -%% #1: data name; #2: data index 1; #3: data index 2; #4: key -\cs_new:Npn \__tblr_data_item:nnnn #1 #2 #3 #4 - { - \__tblr_data_int_to_value:nne {#1} {#4} - { - \intarray_item:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray } - { \__tblr_data_key_to_int:nnnn {#1} {#2} {#3} {#4} } - } - } -\cs_generate_variant:Nn \__tblr_data_item:nnnn { neen } - -\tl_new:N \l__tblr_data_key_tl -\tl_new:N \l__tblr_data_index_tl -\tl_new:N \l__tblr_data_index_two_tl - -\cs_new_protected:Npn \__tblr_data_log:n #1 - { - \use:c { __tblr_data_log_ \use:c { g__tblr_data_#1_index_number_tl } :n } {#1} - \__tblr_prop_log:n {#1} - } - -\cs_new_protected:cpn { __tblr_data_log_1:n } #1 - { - %\intarray_log:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray } - \tl_set:Nx \l_tmpa_tl { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray } - \tl_log:n { ----------~----------~----------~----------~---------- } - \int_step_inline:nn - { \intarray_count:c { \l_tmpa_tl } } - { - \__tblr_data_int_to_key:nnNN {#1} {##1} - \l__tblr_data_index_tl \l__tblr_data_key_tl - \tl_log:x - { - \space - { #1 [\l__tblr_data_index_tl] / \l__tblr_data_key_tl } - ~\space => ~\space - { - \__tblr_data_int_to_value:nVe {#1} \l__tblr_data_key_tl - { \intarray_item:cn { \l_tmpa_tl } {##1} } - } - } - } - } - -\cs_new_protected:cpn { __tblr_data_log_2:n } #1 - { - %\intarray_log:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray } - \tl_set:Nx \l_tmpa_tl { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray } - \tl_log:n { ----------~----------~----------~----------~---------- } - \int_step_inline:nn - { \intarray_count:c { \l_tmpa_tl } } - { - \__tblr_data_int_to_key:nnNNN {#1} {##1} - \l__tblr_data_index_tl \l__tblr_data_index_two_tl \l__tblr_data_key_tl - \tl_log:x - { - \space - { - #1 [\l__tblr_data_index_tl][\l__tblr_data_index_two_tl] - / \l__tblr_data_key_tl - } - ~\space => ~\space - { - \__tblr_data_int_to_value:nVe {#1} \l__tblr_data_key_tl - { \intarray_item:cn { \l_tmpa_tl } {##1} } - } - } - } - } - -%% #1: data name; #2: row index; #3: key; #4: value -\cs_new_protected:Npn \__tblr_data_gput_if_larger:nnnn #1 #2 #3 #4 - { - \__tblr_data_int_from_value:nnn {#1} {#3} {#4} - \__tblr_array_gput_if_larger:cnn - { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray } - { \__tblr_data_key_to_int:nnn {#1} {#2} {#3} } - { \g__tblr_data_int_from_value_tl } - } -\cs_generate_variant:Nn \__tblr_data_gput_if_larger:nnnn { nnne, nnnV, nene, nenV } - -\cs_new_protected:Npn \__tblr_array_gput_if_larger:Nnn #1 #2 #3 - { - \int_compare:nNnT {#3} > { \intarray_item:Nn #1 {#2} } - { \__tblr_intarray_gset:Nnn #1 {#2} {#3} } - } -\cs_generate_variant:Nn \__tblr_array_gput_if_larger:Nnn { cnn } - -%% #1: data name; #2: data index; #3: key; #4: value -\cs_new_protected:Npn \__tblr_data_gadd_dimen_value:nnnn #1 #2 #3 #4 - { - \__tblr_data_int_from_value:nnn {#1} {#3} {#4} - \__tblr_array_gadd_value:cnn - { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray } - { \__tblr_data_key_to_int:nnn {#1} {#2} {#3} } - { \g__tblr_data_int_from_value_tl } - } -\cs_generate_variant:Nn \__tblr_data_gadd_dimen_value:nnnn - { nnne, nnnV, nenn, nene } - -\cs_new_protected:Npn \__tblr_array_gadd_value:Nnn #1 #2 #3 - { - \__tblr_intarray_gset:Nnn #1 {#2} { \intarray_item:Nn #1 {#2} + #3 } - } -\cs_generate_variant:Nn \__tblr_array_gadd_value:Nnn { cnn } - -\bool_new:N \g__tblr_use_intarray_bool -\bool_set_true:N \g__tblr_use_intarray_bool - -\AtBeginDocument - { - \bool_if:NF \g__tblr_use_intarray_bool - { - \cs_set_protected:Npn \__tblr_data_gput:nnnn #1 #2 #3 #4 - { - \__tblr_spec_gput:nnn {#1} { [#2] / #3 } {#4} - } - \cs_set_protected:Npn \__tblr_data_gput:nnnnn #1 #2 #3 #4 #5 - { - \__tblr_spec_gput:nnn {#1} { [#2][#3] / #4 } {#5} - } - \cs_set:Npn \__tblr_data_item:nnn #1 #2 #3 - { - \__tblr_spec_item:nn {#1} { [#2] / #3 } - } - \cs_set:Npn \__tblr_data_item:nnnn #1 #2 #3 #4 - { - \__tblr_spec_item:nn {#1} { [#2][#3] / #4 } - } - \cs_set_protected:Npn \__tblr_data_log:n #1 - { - \__tblr_spec_log:n {#1} - } - \cs_set_protected:Npn \__tblr_data_gput_if_larger:nnnn #1 #2 #3 #4 - { - \__tblr_spec_gput_if_larger:nnn {#1} { [#2] / #3 } {#4} - } - \cs_set_protected:Npn \__tblr_data_gput_if_larger:nnnnn #1 #2 #3 #4 #5 - { - \__tblr_spec_gput_if_larger:nnn {#1} { [#2][#3] / #4 } {#5} - } - \cs_set_protected:Npn \__tblr_data_gadd_dimen_value:nnnn #1 #2 #3 #4 - { - \__tblr_spec_gadd_dimen_value:nnn {#1} { [#2] / #3 } {#4} - } - \cs_set_protected:Npn \__tblr_data_gadd_dimen_value:nnnnn #1 #2 #3 #4 #5 - { - \__tblr_spec_gadd_dimen_value:nnn {#1} { [#2][#3] / #4 } {#5} - } - } - } - -%%% -------------------------------------------------------- -%% \section{Child Selectors} -%%% -------------------------------------------------------- - -\clist_new:N \g_tblr_used_child_selectors_clist - -\tl_new:N \l__tblr_childs_arg_spec_tl - -\msg_new:nnn { tabularray } { used-child-selector } - { Child ~ selector ~ name ~ "#1" ~ has ~ been ~ used! } - -\NewDocumentCommand \NewChildSelector { m O{0} o m } - { - \__tblr_new_child_selector_aux:xnnn { \tl_trim_spaces:n {#1} } {#2} {#3} {#4} - } - -\cs_new_protected:Npn \__tblr_new_child_selector_aux:nnnn #1 #2 #3 #4 - { - \clist_if_in:NnTF \g_tblr_used_child_selectors_clist { #1 } - { - \msg_error:nnn { tabularray } { used-child-selector } { #1 } - \clist_log:N \g_tblr_used_child_selectors_clist - } - { - \__tblr_make_xparse_arg_spec:nnN { #2 } { #3 } \l__tblr_childs_arg_spec_tl - \exp_args:NcV \NewDocumentCommand - { __tblr_child_selector_ #1 :w } \l__tblr_childs_arg_spec_tl { #4 } - \clist_gput_right:Nn \g_tblr_used_child_selectors_clist { #1 } - } - } -\cs_generate_variant:Nn \__tblr_new_child_selector_aux:nnnn { xnnn } - -%% #1: argument number, #2: optional argument default, #3: result tl -\cs_new_protected:Npn \__tblr_make_xparse_arg_spec:nnN #1 #2 #3 - { - \tl_clear:N #3 - \int_compare:nNnT { #1 } > { 0 } - { - \IfValueTF { #2 } - { \tl_set:Nn #3 { O{#2} } } - { \tl_set:Nn #3 { m } } - \tl_put_right:Nx #3 { \prg_replicate:nn { #1 - 1 } { m } } - } - } - -\clist_new:N \l_tblr_childs_clist -\tl_new:N \l_tblr_childs_total_tl - -\NewChildSelector { odd } - { - \int_step_inline:nnnn {1} {2} { \l_tblr_childs_total_tl } - { \clist_put_right:Nn \l_tblr_childs_clist {##1} } - } - -\NewChildSelector { even } - { - \int_step_inline:nnnn {2} {2} { \l_tblr_childs_total_tl } - { \clist_put_right:Nn \l_tblr_childs_clist {##1} } - } - -\regex_const:Nn \c__tblr_split_selector_name_regex { ^ ( [A-Za-z] {2,} ) ( . * ) } -\seq_new:N \l__tblr_childs_split_seq -\seq_new:N \l__tblr_childs_regex_seq -\tl_new:N \l__tblr_childs_selector_tl - -%% #1, child specifications; #2, total number. -%% The result will be put into \l_tblr_childs_clist -\cs_new_protected:Npn \__tblr_get_childs:nn #1 #2 - { - \clist_clear:N \l_tblr_childs_clist - \tl_set:Nx \l_tblr_childs_total_tl {#2} - \regex_extract_once:NnNTF \c__tblr_split_selector_name_regex {#1} - \l__tblr_childs_regex_seq - { - \tl_set:No \l__tblr_childs_selector_tl - { - \cs:w - __tblr_child_selector_ \seq_item:Nn \l__tblr_childs_regex_seq {2} :w - \cs_end: - } - \exp_args:Nx \l__tblr_childs_selector_tl - { \seq_item:Nn \l__tblr_childs_regex_seq{3} } - } - { - \tl_if_eq:nnTF {#1} {-} - { \__tblr_get_childs_normal:nn {1-#2} {#2} } - { \__tblr_get_childs_normal:nn {#1} {#2} } - } - %\clist_log:N \l_tblr_childs_clist - } -\cs_generate_variant:Nn \__tblr_get_childs:nn { nx } - -\cs_new_protected:Npn \__tblr_get_childs_normal:nn #1 #2 - { - \seq_set_split:Nnn \l__tblr_childs_split_seq {,} {#1} - \seq_map_inline:Nn \l__tblr_childs_split_seq - { - \tl_if_in:nnTF {##1} {-} - { \__tblr_get_childs_normal_aux:w ##1 \scan_stop } - { \__tblr_get_childs_normal_aux:w ##1 - ##1 \scan_stop } - } - } - -\tl_new:N \l__tblr_child_from_tl -\tl_new:N \l__tblr_child_to_tl - -\cs_new_protected_nopar:Npn \__tblr_get_childs_normal_aux:w #1 - #2 \scan_stop - { - \__tblr_child_name_to_index:nN {#1} \l__tblr_child_from_tl - \__tblr_child_name_to_index:nN {#2} \l__tblr_child_to_tl - \int_step_inline:nnn { \l__tblr_child_from_tl } { \l__tblr_child_to_tl } - { \clist_put_right:Nn \l_tblr_childs_clist {##1} } - } - -\regex_const:Nn \c__tblr_child_name_regex { ^ [X-Z] $ } - -%% Convert X, Y, Z to the indexes of the last three childs, respectively -\cs_new_protected_nopar:Npn \__tblr_child_name_to_index:nN #1 #2 - { - \regex_match:NnTF \c__tblr_child_name_regex {#1} - { - \tl_set:Nx #2 - { \int_eval:n { \l_tblr_childs_total_tl + \int_from_alph:n {#1} - 26 } } - } - { \tl_set:Nx #2 { #1 } } - } - -%%% -------------------------------------------------------- -%% \section{New Table Commands} -%%% -------------------------------------------------------- - -%% We need some commands to modify table/row/column/cell specifications. -%% These commands must be defined with \NewTableCommand command, -%% so that we could extract them, execute them once, then disable them. - -\clist_new:N \g__tblr_table_commands_clist - -\msg_new:nnn { tabularray } { defined-table-command } - { Table ~ commnad ~ #1 has ~ been ~ defined! } - -\NewDocumentCommand \NewTableCommand { m O{0} o m } - { - \clist_if_in:NnTF \g__tblr_table_commands_clist { #1 } - { - \msg_error:nnn { tabularray } { defined-table-command } { #1 } - \clist_log:N \g__tblr_table_commands_clist - } - { - \__tblr_make_xparse_arg_spec:nnN { #2 } { #3 } \l__tblr_a_tl - \exp_args:NcV \NewDocumentCommand - { __tblr_table_command_ \cs_to_str:N #1 :w } \l__tblr_a_tl { #4 } - \exp_args:NcV \NewDocumentCommand - { __tblr_table_command_ \cs_to_str:N #1 _gobble :w } \l__tblr_a_tl { } - \IfValueTF { #3 } - { - \tl_gset:cn { g__tblr_table_cmd_ \cs_to_str:N #1 _arg_numb_tl } {-#2} - } - { - \tl_gset:cn { g__tblr_table_cmd_ \cs_to_str:N #1 _arg_numb_tl } {#2} - } - \clist_gput_right:Nn \g__tblr_table_commands_clist { #1 } - } - } - -\cs_new_protected:Npn \__tblr_enable_table_commands: - { - \clist_map_inline:Nn \g__tblr_table_commands_clist - { \cs_set_eq:Nc ##1 { __tblr_table_command_ \cs_to_str:N ##1 :w } } - } - -\cs_new_protected:Npn \__tblr_disable_table_commands: - { - \clist_map_inline:Nn \g__tblr_table_commands_clist - { \cs_set_eq:Nc ##1 { __tblr_table_command_ \cs_to_str:N ##1 _gobble:w } } - } - -\cs_new_protected:Npn \__tblr_execute_table_commands: - { - \__tblr_prop_map_inline:nn { command } - { - \__tblr_set_row_col_from_key_name:w ##1 - ##2 - } - \LogTblrTracing { cell } - } - -\cs_new_protected:Npn \__tblr_set_row_col_from_key_name:w [#1][#2] - { - \int_set:Nn \c@rownum {#1} - \int_set:Nn \c@colnum {#2} - } - -%% Table commands are defined only inside tblr environments, -%% but some packages such as csvsimple need to use them outside tblr environments, -%% therefore we define some of them first here. -\ProvideDocumentCommand \SetHlines { o m m } {} -\ProvideDocumentCommand \SetHline { o m m } {} -\ProvideDocumentCommand \SetVlines { o m m } {} -\ProvideDocumentCommand \SetVline { o m m } {} -\ProvideDocumentCommand \SetCells { o m } {} -\ProvideDocumentCommand \SetCell { o m } {} -\ProvideDocumentCommand \SetRows { o m } {} -\ProvideDocumentCommand \SetRow { o m } {} -\ProvideDocumentCommand \SetColumns { o m } {} -\ProvideDocumentCommand \SetColumn { o m } {} - -%%% -------------------------------------------------------- -%%> \section{New Content Commands} -%%% -------------------------------------------------------- - -%% We need to emulate or fix some commands such as \diagbox in other packages -%% These commands must be defined with \NewContentCommand command -%% We only enable them inside tblr environment to avoid potential conflict - -\clist_new:N \g__tblr_content_commands_clist - -\msg_new:nnn { tabularray } { defined-content-command } - { Content ~ commnad ~ #1 has ~ been ~ defined! } - -\NewDocumentCommand \NewContentCommand { m O{0} o m } - { - \clist_if_in:NnTF \g__tblr_content_commands_clist { #1 } - { - \msg_warning:nnn { tabularray } { defined-content-command } { #1 } - \clist_log:N \g__tblr_content_commands_clist - } - { - \__tblr_make_xparse_arg_spec:nnN { #2 } { #3 } \l__tblr_a_tl - \exp_args:NcV \NewDocumentCommand - { __tblr_content_command_ \cs_to_str:N #1 :w } \l__tblr_a_tl { #4 } - \clist_gput_right:Nn \g__tblr_content_commands_clist { #1 } - } - } - -\cs_new_protected:Npn \__tblr_enable_content_commands: - { - \clist_map_inline:Nn \g__tblr_content_commands_clist - { \cs_set_eq:Nc ##1 { __tblr_content_command_ \cs_to_str:N ##1 :w } } - } - -%%% -------------------------------------------------------- -%% \section{New Dash Styles} -%%% -------------------------------------------------------- - -%% \NewDashStyle commands - -\dim_zero_new:N \rulewidth -\dim_set:Nn \rulewidth {0.4pt} - -\prop_gset_from_keyval:Nn \g__tblr_defined_hdash_styles_prop - { solid = \hrule height \rulewidth } -\prop_gset_from_keyval:Nn \g__tblr_defined_vdash_styles_prop - { solid = \vrule width \rulewidth } - -\NewDocumentCommand \NewDashStyle { m m } - { - \seq_set_split:Nnn \l_tmpa_seq { ~ } {#2} - \tl_set:Nx \l__tblr_a_tl { \seq_item:Nn \l_tmpa_seq {1} } - \tl_set:Nx \l__tblr_b_tl { \seq_item:Nn \l_tmpa_seq {2} } - \tl_set:Nx \l__tblr_c_tl { \seq_item:Nn \l_tmpa_seq {3} } - \tl_set:Nx \l__tblr_d_tl { \seq_item:Nn \l_tmpa_seq {4} } - \tl_if_eq:NnT \l__tblr_a_tl { on } - { - \tl_if_eq:NnT \l__tblr_c_tl { off } - { - \__tblr_dash_style_make_boxes:nxx {#1} - { \dim_eval:n {\l__tblr_b_tl} } { \dim_eval:n {\l__tblr_d_tl} } - } - } - } - -\cs_new_protected:Npn \__tblr_dash_style_make_boxes:nnn #1 #2 #3 - { - \dim_set:Nn \l_tmpa_dim { #2 + #3 } - \tl_set:Nn \l__tblr_h_tl { \hbox_to_wd:nn } - \tl_put_right:Nx \l__tblr_h_tl { { \dim_use:N \l_tmpa_dim } } - \tl_put_right:Nn \l__tblr_h_tl - { - { \hss \vbox:n { \hbox_to_wd:nn {#2} {} \hrule height \rulewidth } \hss } - } - \prop_gput:NnV \g__tblr_defined_hdash_styles_prop {#1} \l__tblr_h_tl - %\prop_log:N \g__tblr_defined_hdash_styles_prop - \tl_set:Nn \l__tblr_v_tl { \vbox_to_ht:nn } - \tl_put_right:Nx \l__tblr_v_tl { { \dim_use:N \l_tmpa_dim } } - \tl_put_right:Nn \l__tblr_v_tl - { - { \vss \hbox:n { \vbox_to_ht:nn {#2} {} \vrule width \rulewidth } \vss } - } - \prop_gput:NnV \g__tblr_defined_vdash_styles_prop {#1} \l__tblr_v_tl - %\prop_log:N \g__tblr_defined_vdash_styles_prop - } -\cs_generate_variant:Nn \__tblr_dash_style_make_boxes:nnn { nxx } - -\cs_new_protected:Npn \__tblr_get_hline_dash_style:N #1 - { - \tl_set:Nx \l_tmpa_tl - { \prop_item:NV \g__tblr_defined_hdash_styles_prop #1 } - \tl_if_empty:NF \l_tmpa_tl { \tl_set_eq:NN #1 \l_tmpa_tl } - } - -\cs_new_protected:Npn \__tblr_get_vline_dash_style:N #1 - { - \tl_set:Nx \l_tmpa_tl - { \prop_item:NV \g__tblr_defined_vdash_styles_prop #1 } - \tl_if_empty:NF \l_tmpa_tl { \tl_set_eq:NN #1 \l_tmpa_tl } - } - -\NewDashStyle {dashed} {on ~ 2pt ~ off ~ 2pt} -\NewDashStyle {dotted} {on ~ 0.4pt ~ off ~ 1pt} - -%%% -------------------------------------------------------- -%% \section{Set Hlines and Vlines} -%%% -------------------------------------------------------- - -\tl_set:Nn \@tblr@dash { dash } -\tl_set:Nn \@tblr@text { text } - -\regex_const:Nn \c__tblr_is_color_key_regex { ^[A-Za-z] } - -%% \SetHlines command for setting every hline in the table -\NewTableCommand \SetHlines [3] [+] - { - \tblr_set_every_hline:nnn {#1} {#2} {#3} - } - -%% We put all code inside a group to avoid affecting other table commands -\cs_new_protected:Npn \tblr_set_every_hline:nnn #1 #2 #3 - { - \group_begin: - \int_step_inline:nn { \int_eval:n { \c@rowcount + 1 } } - { - \int_set:Nn \c@rownum {##1} - \tblr_set_hline:nnn {#1} {#2} {#3} - } - \group_end: - } - -%% Check the number of arguments and call \tblr_set_every_hline in different ways -%% This function is called when parsing table specifications -\cs_new_protected:Npn \__tblr_set_every_hline_aux:n #1 - { - \tl_if_head_is_group:nTF {#1} - { - \int_compare:nNnTF { \tl_count:n {#1} } = {3} - { \tblr_set_every_hline:nnn #1 } - { \tblr_set_every_hline:nnn {1} #1 } - } - { \tblr_set_every_hline:nnn {1} {-} {#1} } - } - -%% Add \SetHline, \hline and \cline commands - -\tl_new:N \l__tblr_hline_count_tl % the count of all hlines -\tl_new:N \l__tblr_hline_num_tl % the index of the hline -\tl_new:N \l__tblr_hline_cols_tl % the columns of the hline -\tl_new:N \l__tblr_hline_dash_tl % dash style -\tl_new:N \l__tblr_hline_fg_tl % dash foreground -\tl_new:N \l__tblr_hline_wd_tl % dash width -\tl_new:N \l__tblr_hline_leftpos_tl % left position -\tl_new:N \l__tblr_hline_rightpos_tl % right position -\bool_new:N \l__tblr_hline_endpos_bool % whether set positions only for both ends - -\NewTableCommand \cline [2] [] { \SetHline [=] {#2} {#1} } - -\NewTableCommand \hline [1] [] { \SetHline [+] {-} {#1} } - -%% Some keys can be set by any hline, such as abovespace and belowspace keys. -%% Using special hline of index 0, you can set these keys without adding any hlines. -\NewTableCommand \SetVspace [1] { \SetHline [0] {-} {#1} } - -%% #1: the index of the hline (may be + or =) -%% #2: which columns of the hline, separate by commas -%% #3: key=value pairs -\NewTableCommand \SetHline [3] [+] - { - \tblr_set_hline:nnn {#1} {#2} {#3} - } - -%% We need to check "text" key first -%% If it does exist and has empty value, then do nothing -\cs_new_protected:Npn \tblr_set_hline:nnn #1 #2 #3 - { - \group_begin: - %% We can not use \int_compare:nNnTF here since #1 may be + or = . - %% Also we treat hline of index 0 specially, not adding hline count. - \tl_if_eq:nnTF {#1} {0} - { \keys_set:nn { tblr-hline } {#3} } - { - \keys_set_groups:nnn { tblr-hline } { text } {#3} - \tl_if_eq:NnF \l__tblr_hline_dash_tl { \exp_not:N \@tblr@text } - { - \__tblr_set_hline_num:n {#1} - \tl_clear:N \l__tblr_hline_dash_tl - \keys_set:nn { tblr-hline } { dash = solid, #3 } - \__tblr_set_hline_cmd:n {#2} - } - } - \group_end: - } - -\cs_new_protected:Npn \tblr_set_hline:nnnn #1 #2 #3 #4 - { - \group_begin: - \__tblr_get_childs:nx {#1} { \int_eval:n { \c@rowcount + 1 } } - \clist_map_inline:Nn \l_tblr_childs_clist - { - \int_set:Nn \c@rownum {##1} - \tblr_set_hline:nnn {#2} {#3} {#4} - } - \group_end: - } - -%% Check the number of arguments and call \tblr_set_hline in different ways -%% Note that #1 always includes an outer pair of braces -%% This function is called when parsing table specifications -\cs_new_protected:Npn \__tblr_set_hline_aux:nn #1 #2 - { - \tl_if_head_is_group:nTF {#2} - { - \int_compare:nNnTF { \tl_count:n {#2} } = {3} - { \tblr_set_hline:nnnn #1 #2 } - { \tblr_set_hline:nnnn #1 {1} #2 } - } - { \tblr_set_hline:nnnn #1 {1} {-} {#2} } - } -\cs_generate_variant:Nn \__tblr_set_hline_aux:nn { Vn } - -%% #1: the index of hline to set (may be + or =) -\cs_new_protected:Npn \__tblr_set_hline_num:n #1 - { - \tl_clear:N \l__tblr_hline_num_tl - \tl_set:Nx \l__tblr_hline_count_tl - { \__tblr_spec_item:ne { hline } { [\int_use:N \c@rownum] / @hline-count } } - %% \l__tblr_hline_count_tl may be empty when rowspec has extra |'s - \int_compare:nNnTF { \l__tblr_hline_count_tl + 0 } = {0} - { - \tl_set:Nx \l__tblr_hline_num_tl { 1 } - \__tblr_spec_gput:nen { hline } - { [\int_use:N \c@rownum] / @hline-count } { 1 } - } - { - \tl_if_eq:nnTF {#1} {+} - { \__tblr_set_hline_num_incr: } - { - \tl_if_eq:nnTF {#1} {=} - { \tl_set_eq:NN \l__tblr_hline_num_tl \l__tblr_hline_count_tl } - { - \int_compare:nNnTF {#1} > { \l__tblr_hline_count_tl } - { \__tblr_set_hline_num_incr: } - { \tl_set:Nn \l__tblr_hline_num_tl {#1} } - } - } - } - } - -\cs_new_protected:Npn \__tblr_set_hline_num_incr: - { - \tl_set:Nx \l__tblr_hline_count_tl - { \int_eval:n { \l__tblr_hline_count_tl + 1 } } - \__tblr_spec_gput:nee { hline } - { [\int_use:N \c@rownum] / @hline-count } { \l__tblr_hline_count_tl } - \tl_set_eq:NN \l__tblr_hline_num_tl \l__tblr_hline_count_tl - } - -\keys_define:nn { tblr-hline } - { - dash .code:n = \tl_set:Nn \l__tblr_hline_dash_tl { \exp_not:N \@tblr@dash #1 }, - text .code:n = \tl_set:Nn \l__tblr_hline_dash_tl { \exp_not:N \@tblr@text #1 }, - text .groups:n = { text }, - wd .code:n = \tl_set:Nn \l__tblr_hline_wd_tl { \dim_eval:n {#1} }, - fg .code:n = \tl_set:Nn \l__tblr_hline_fg_tl {#1}, - baseline .code:n = \__tblr_hline_set_baseline:n {#1}, - leftpos .code:n = \tl_set:Nx \l__tblr_hline_leftpos_tl {#1}, - rightpos .code:n = \tl_set:Nx \l__tblr_hline_rightpos_tl {#1}, - l .meta:n = { leftpos = #1 }, - l .default:n = { -0.8 }, - r .meta:n = { rightpos = #1 }, - r .default:n = { -0.8 }, - lr .meta:n = { leftpos = #1, rightpos = #1 }, - lr .default:n = { -0.8 }, - endpos .bool_set:N = \l__tblr_hline_endpos_bool, - abovespace .code:n = \__tblr_row_gput_above:ne { belowsep } { \dim_eval:n {#1} }, - belowspace .code:n = \__tblr_row_gput:ne { abovesep } { \dim_eval:n {#1} }, - abovespace+ .code:n = \__tblr_row_gadd_dimen_above:ne - { belowsep } { \dim_eval:n {#1} }, - belowspace+ .code:n = \__tblr_row_gadd_dimen:ne - { abovesep } { \dim_eval:n {#1} }, - unknown .code:n = \__tblr_hline_unknown_key:V \l_keys_key_str, - } - -\cs_new_protected:Npn \__tblr_hline_unknown_key:n #1 - { - \prop_if_in:NnTF \g__tblr_defined_hdash_styles_prop {#1} - { \tl_set:Nn \l__tblr_hline_dash_tl { \exp_not:N \@tblr@dash #1 } } - { - \regex_match:NnTF \c__tblr_is_color_key_regex {#1} - { \tl_set:Nn \l__tblr_hline_fg_tl {#1} } - { - \tl_set_rescan:Nnn \l__tblr_v_tl {} {#1} - \tl_set:Nn \l__tblr_hline_wd_tl { \dim_eval:n {\l__tblr_v_tl} } - } - } - } -\cs_generate_variant:Nn \__tblr_hline_unknown_key:n { V } - -\cs_new_protected_nopar:Npn \__tblr_set_hline_cmd:n #1 - { - \__tblr_get_childs:nx {#1} { \int_use:N \c@colcount } - \clist_map_inline:Nn \l_tblr_childs_clist - { - \__tblr_set_hline_option:nnn { ##1 } { @dash } { \l__tblr_hline_dash_tl } - \tl_if_empty:NF \l__tblr_hline_wd_tl - { - \__tblr_set_hline_option:nnn { ##1 } { wd } { \l__tblr_hline_wd_tl } - } - \tl_if_empty:NF \l__tblr_hline_fg_tl - { - \__tblr_set_hline_option:nnn { ##1 } { fg } { \l__tblr_hline_fg_tl } - } - } - \tl_if_empty:NF \l__tblr_hline_leftpos_tl - { - \bool_if:NTF \l__tblr_hline_endpos_bool - { - \__tblr_set_hline_option:nnn - { \clist_item:Nn \l_tblr_childs_clist {1} } - { leftpos } - { \l__tblr_hline_leftpos_tl } - } - { - \clist_map_inline:Nn \l_tblr_childs_clist - { - \__tblr_set_hline_option:nnn - { ##1 } { leftpos } { \l__tblr_hline_leftpos_tl } - } - } - } - \tl_if_empty:NF \l__tblr_hline_rightpos_tl - { - \bool_if:NTF \l__tblr_hline_endpos_bool - { - \__tblr_set_hline_option:nnn - { \clist_item:Nn \l_tblr_childs_clist {-1} } - { rightpos } - { \l__tblr_hline_rightpos_tl } - } - { - \clist_map_inline:Nn \l_tblr_childs_clist - { - \__tblr_set_hline_option:nnn - { ##1 } { rightpos } { \l__tblr_hline_rightpos_tl } - } - } - } - } - -%% #1: column; #2: key; #3: value -\cs_new_protected_nopar:Npn \__tblr_set_hline_option:nnn #1 #2 #3 - { - \__tblr_spec_gput:nee { hline } - { [\int_use:N \c@rownum][#1](\l__tblr_hline_num_tl) / #2 } { #3 } - } - -\NewTableCommand \firsthline [1] [] { \SetHline [+] {-} { #1, baseline=below } } -\NewTableCommand \lasthline [1] [] { \SetHline [+] {-} { #1, baseline=above } } - -\cs_new_protected:Npn \__tblr_hline_set_baseline:n #1 - { - \tl_if_eq:nnTF {#1} {above} - { - \__tblr_prop_gput:nnx { inner } - { baseline } { \int_eval:n { \c@rownum - 1 } } - } - { - \tl_if_eq:nnT {#1} {below} - { - \__tblr_prop_gput:nnx { inner } { baseline } { \int_use:N \c@rownum } - } - } - } - -%% \SetVlines command for setting every vline in the table -\NewTableCommand \SetVlines [3] [+] - { - \tblr_set_every_vline:nnn {#1} {#2} {#3} - } - -%% We put all code inside a group to avoid affecting other table commands -\cs_new_protected:Npn \tblr_set_every_vline:nnn #1 #2 #3 - { - \group_begin: - \int_step_inline:nn { \int_eval:n { \c@colcount + 1 } } - { - \int_set:Nn \c@colnum {##1} - \tblr_set_vline:nnn {#1} {#2} {#3} - } - \group_end: - } - -%% Check the number of arguments and call \tblr_set_every_vline in different ways -%% This function is called when parsing table specifications -\cs_new_protected:Npn \__tblr_set_every_vline_aux:n #1 - { - \tl_if_head_is_group:nTF {#1} - { - \int_compare:nNnTF { \tl_count:n {#1} } = {3} - { \tblr_set_every_vline:nnn #1 } - { \tblr_set_every_vline:nnn {1} #1 } - } - { \tblr_set_every_vline:nnn {1} {-} {#1} } - } - -%% Add \SetVline, \vline and \rline commands - -\tl_new:N \l__tblr_vline_count_tl % the count of all vlines -\tl_new:N \l__tblr_vline_num_tl % the index of the vline -\tl_new:N \l__tblr_vline_rows_tl % the rows of the vline -\tl_new:N \l__tblr_vline_dash_tl % dash style -\tl_new:N \l__tblr_vline_fg_tl % dash foreground -\tl_new:N \l__tblr_vline_wd_tl % dash width -\tl_new:N \l__tblr_vline_abovepos_tl % above position -\tl_new:N \l__tblr_vline_belowpos_tl % below position - -\NewTableCommand \rline [2] [] { \SetVline [=] {#2} {#1} } - -\NewTableCommand \vline [1] [] { \SetVline [+] {-} {#1} } - -%% #1: the index of the vline (may be + or =) -%% #2: which rows of the vline, separate by commas -%% #3: key=value pairs -\NewTableCommand \SetVline [3] [+] - { - \tblr_set_vline:nnn {#1} {#2} {#3} - } - -%% We need to check "text" key first -%% If it does exist and has empty value, then do nothing -\cs_new_protected:Npn \tblr_set_vline:nnn #1 #2 #3 - { - \group_begin: - \keys_set_groups:nnn { tblr-vline } { text } {#3} - \tl_if_eq:NnF \l__tblr_vline_dash_tl { \exp_not:N \@tblr@text } - { - \__tblr_set_vline_num:n {#1} - \tl_clear:N \l__tblr_vline_dash_tl - \keys_set:nn { tblr-vline } { dash = solid, #3 } - \__tblr_set_vline_cmd:n {#2} - } - \group_end: - } - -\cs_new_protected:Npn \tblr_set_vline:nnnn #1 #2 #3 #4 - { - \group_begin: - \__tblr_get_childs:nx {#1} { \int_eval:n { \c@colcount + 1} } - \clist_map_inline:Nn \l_tblr_childs_clist - { - \int_set:Nn \c@colnum {##1} - \tblr_set_vline:nnn {#2} {#3} {#4} - } - \group_end: - } - -%% Check the number of arguments and call \tblr_set_vline in different ways -%% Note that #1 always includes an outer pair of braces -%% This function is called when parsing table specifications -\cs_new_protected:Npn \__tblr_set_vline_aux:nn #1 #2 - { - \tl_if_head_is_group:nTF {#2} - { - \int_compare:nNnTF { \tl_count:n {#2} } = {3} - { \tblr_set_vline:nnnn #1 #2 } - { \tblr_set_vline:nnnn #1 {1} #2 } - } - { \tblr_set_vline:nnnn #1 {1} {-} {#2} } - } -\cs_generate_variant:Nn \__tblr_set_vline_aux:nn { Vn } - -%% #1: the index of vline to set (may be + or =) -\cs_new_protected:Npn \__tblr_set_vline_num:n #1 - { - \tl_clear:N \l__tblr_vline_num_tl - \tl_set:Nx \l__tblr_vline_count_tl - { \__tblr_spec_item:ne { vline } { [\int_use:N \c@colnum] / @vline-count } } - %% \l__tblr_vline_count_tl may be empty when colspec has extra |'s - \int_compare:nNnTF { \l__tblr_vline_count_tl + 0 } = {0} - { - \tl_set:Nx \l__tblr_vline_num_tl { 1 } - \__tblr_spec_gput:nen { vline } - { [\int_use:N \c@colnum] / @vline-count } { 1 } - } - { - \tl_if_eq:nnTF {#1} {+} - { \__tblr_set_vline_num_incr: } - { - \tl_if_eq:nnTF {#1} {=} - { \tl_set_eq:NN \l__tblr_vline_num_tl \l__tblr_vline_count_tl } - { - \int_compare:nNnTF {#1} > { \l__tblr_vline_count_tl } - { \__tblr_set_vline_num_incr: } - { \tl_set:Nn \l__tblr_vline_num_tl {#1} } - } - } - } - } - -\cs_new_protected:Npn \__tblr_set_vline_num_incr: - { - \tl_set:Nx \l__tblr_vline_count_tl - { \int_eval:n { \l__tblr_vline_count_tl + 1 } } - \__tblr_spec_gput:nee { vline } - { [\int_use:N \c@colnum] / @vline-count } { \l__tblr_vline_count_tl } - \tl_set_eq:NN \l__tblr_vline_num_tl \l__tblr_vline_count_tl - } - -\keys_define:nn { tblr-vline } - { - dash .code:n = \tl_set:Nn \l__tblr_vline_dash_tl { \exp_not:N \@tblr@dash #1 }, - text .code:n = \tl_set:Nn \l__tblr_vline_dash_tl { \exp_not:N \@tblr@text #1 }, - text .groups:n = { text }, - wd .code:n = \tl_set:Nn \l__tblr_vline_wd_tl { \dim_eval:n {#1} }, - fg .code:n = \tl_set:Nn \l__tblr_vline_fg_tl {#1}, - abovepos .code:n = \tl_set:Nx \l__tblr_vline_abovepos_tl {#1}, - belowpos .code:n = \tl_set:Nx \l__tblr_vline_belowpos_tl {#1}, - unknown .code:n = \__tblr_vline_unknown_key:V \l_keys_key_str, - } - -\cs_new_protected:Npn \__tblr_vline_unknown_key:n #1 - { - \prop_if_in:NnTF \g__tblr_defined_vdash_styles_prop {#1} - { \tl_set:Nn \l__tblr_vline_dash_tl { \exp_not:N \@tblr@dash #1 } } - { - \regex_match:NnTF \c__tblr_is_color_key_regex {#1} - { \tl_set:Nn \l__tblr_vline_fg_tl {#1} } - { - \tl_set_rescan:Nnn \l__tblr_v_tl {} {#1} - \tl_set:Nn \l__tblr_vline_wd_tl { \dim_eval:n {\l__tblr_v_tl} } - } - } - } -\cs_generate_variant:Nn \__tblr_vline_unknown_key:n { V } - -\cs_new_protected_nopar:Npn \__tblr_set_vline_cmd:n #1 - { - \__tblr_get_childs:nx {#1} { \int_use:N \c@rowcount } - \clist_map_inline:Nn \l_tblr_childs_clist - { - \__tblr_spec_gput:nee { vline } - { [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / @dash } - { \l__tblr_vline_dash_tl } - \tl_if_empty:NF \l__tblr_vline_wd_tl - { - \__tblr_spec_gput:nee { vline } - { [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / wd } - { \l__tblr_vline_wd_tl } - } - \tl_if_empty:NF \l__tblr_vline_fg_tl - { - \__tblr_spec_gput:nee { vline } - { [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / fg } - { \l__tblr_vline_fg_tl } - } - \tl_if_empty:NF \l__tblr_vline_abovepos_tl - { - \__tblr_spec_gput:nee { vline } - { [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / abovepos } - { \l__tblr_vline_abovepos_tl } - } - \tl_if_empty:NF \l__tblr_vline_belowpos_tl - { - \__tblr_spec_gput:nee { vline } - { [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / belowpos } - { \l__tblr_vline_belowpos_tl } - } - } - } - -%%% -------------------------------------------------------- -%% \section{Set Cells} -%%% -------------------------------------------------------- - -%% \SetCells command for setting every cell in the table -\NewTableCommand \SetCells [2] [] - { - \tblr_set_every_cell:nn {#1} {#2} - } - -%% We put all code inside a group to avoid affecting other table commands -\cs_new_protected:Npn \tblr_set_every_cell:nn #1 #2 - { - \group_begin: - \int_step_inline:nn { \c@rowcount } - { - \int_set:Nn \c@rownum {##1} - \int_step_inline:nn { \c@colcount } - { - \int_set:Nn \c@colnum {####1} - \tblr_set_cell:nn {#1} {#2} - } - } - \group_end: - } - -%% Check the number of arguments and call \tblr_set_every_cell in different ways -%% This function is called when parsing table specifications -\cs_new_protected:Npn \__tblr_set_every_cell_aux:n #1 - { - \tl_if_head_is_group:nTF {#1} - { \tblr_set_every_cell:nn #1 } - { \tblr_set_every_cell:nn {} {#1} } - } - -%% \SetCell command for multirow and/or multicolumn cells - -\NewTableCommand \SetCell [2] [] - { - \tblr_set_cell:nn { #1 } { #2 } - } - -\tl_new:N \l__tblr_row_span_num_tl -\tl_new:N \l__tblr_col_span_num_tl - -\cs_new_protected:Npn \tblr_set_cell:nn #1 #2 - { - \tl_set:Nn \l__tblr_row_span_num_tl { 1 } - \tl_set:Nn \l__tblr_col_span_num_tl { 1 } - \keys_set:nn { tblr-cell-span } { #1 } - \keys_set:nn { tblr-cell-spec } { #2 } - \__tblr_set_span_spec:VV \l__tblr_row_span_num_tl \l__tblr_col_span_num_tl - } -\cs_generate_variant:Nn \tblr_set_cell:nn { nV } - -\cs_new_protected:Npn \tblr_set_cell:nnnn #1 #2 #3 #4 - { - \group_begin: - \__tblr_get_childs:nx {#1} { \int_use:N \c@rowcount } - \clist_set_eq:NN \l_tmpa_clist \l_tblr_childs_clist - \__tblr_get_childs:nx {#2} { \int_use:N \c@colcount } - \clist_set_eq:NN \l_tmpb_clist \l_tblr_childs_clist - \clist_map_inline:Nn \l_tmpa_clist - { - \int_set:Nn \c@rownum {##1} - \clist_map_inline:Nn \l_tmpb_clist - { - \int_set:Nn \c@colnum {####1} - \tblr_set_cell:nn {#3} {#4} - } - } - \group_end: - } - -%% Check the number of arguments and call \tblr_set_cell in different ways -%% Note that #1 is always of the type {}{} -%% This function is called when parsing table specifications -\cs_new_protected:Npn \__tblr_set_cell_aux:nn #1 #2 - { - \tl_if_head_is_group:nTF {#2} - { \tblr_set_cell:nnnn #1 #2 } - { \tblr_set_cell:nnnn #1 {} {#2} } - } -\cs_generate_variant:Nn \__tblr_set_cell_aux:nn { Vn } - -\keys_define:nn { tblr-cell-span } - { - r .tl_set:N = \l__tblr_row_span_num_tl, - c .tl_set:N = \l__tblr_col_span_num_tl, - } - -\keys_define:nn { tblr-cell-spec } - { - halign .code:n = \__tblr_cell_gput:nn { halign } {#1}, - valign .code:n = \__tblr_cell_gput:nn { valign } {#1}, - j .meta:n = { halign = j }, - l .meta:n = { halign = l }, - c .meta:n = { halign = c }, - r .meta:n = { halign = r }, - t .meta:n = { valign = t }, - p .meta:n = { valign = t }, - m .meta:n = { valign = m }, - b .meta:n = { valign = b }, - h .meta:n = { valign = h }, - f .meta:n = { valign = f }, - wd .code:n = \__tblr_cell_gput:ne { width } {#1}, - bg .code:n = \__tblr_cell_gput:ne { background } {#1}, - fg .code:n = \__tblr_cell_gput:ne { foreground } {#1}, - font .code:n = \__tblr_cell_gput:nn { font } { #1 \selectfont }, - mode .code:n = \__tblr_cell_gput:nn { mode } {#1}, - $ .meta:n = { mode = math }, - $$ .meta:n = { mode = dmath }, - cmd .code:n = \__tblr_cell_gput:nn { cmd } {#1}, - preto .code:n = \__tblr_cell_preto_text:n {#1}, - appto .code:n = \__tblr_cell_appto_text:n {#1}, - unknown .code:n = \__tblr_cell_unknown_key:V \l_keys_key_str, - } - -\cs_new_protected:Npn \__tblr_cell_gput:nn #1 #2 - { - \__tblr_data_gput:neenn { cell } - { \int_use:N \c@rownum } { \int_use:N \c@colnum } {#1} {#2} - } -\cs_generate_variant:Nn \__tblr_cell_gput:nn { ne } - -\cs_new_protected:Npn \__tblr_cell_gput:nnnn #1 #2 #3 #4 - { - \__tblr_data_gput:nnnnn { cell } {#1} {#2} {#3} {#4} - } -\cs_generate_variant:Nn \__tblr_cell_gput:nnnn - { nenn, ennn, eenn, nene, enne, eene } - -\tl_new:N \l__tblr_cell_text_tl - -\cs_new_protected:Npn \__tblr_cell_preto_text:n #1 - { - \__tblr_cell_preto_text:een - { \int_use:N \c@rownum } { \int_use:N \c@colnum } {#1} - } - -\cs_new_protected:Npn \__tblr_cell_preto_text:nnn #1 #2 #3 - { - \tl_set:Nx \l__tblr_cell_text_tl { \__tblr_spec_item:nn { text } { [#1][#2] } } - \tl_put_left:Nn \l__tblr_cell_text_tl {#3} - \__tblr_spec_gput:nnV { text } { [#1][#2] } \l__tblr_cell_text_tl - } -\cs_generate_variant:Nn \__tblr_cell_preto_text:nnn { nen, enn, een } - -\cs_new_protected:Npn \__tblr_cell_appto_text:n #1 - { - \__tblr_cell_appto_text:een - { \int_use:N \c@rownum } { \int_use:N \c@colnum } {#1} - } - -\cs_new_protected:Npn \__tblr_cell_appto_text:nnn #1 #2 #3 - { - \tl_set:Nx \l__tblr_cell_text_tl { \__tblr_spec_item:ne { text } { [#1][#2] } } - \tl_put_right:Nn \l__tblr_cell_text_tl {#3} - \__tblr_spec_gput:neV { text } { [#1][#2] } \l__tblr_cell_text_tl - } -\cs_generate_variant:Nn \__tblr_cell_appto_text:nnn { nen, enn, een } - -\cs_new_protected:Npn \__tblr_cell_unknown_key:n #1 - { - \regex_match:NnTF \c__tblr_is_color_key_regex {#1} - { - \__tblr_data_gput:neene { cell } - { \int_use:N \c@rownum } { \int_use:N \c@colnum } { background } {#1} - } - { - \tl_set_rescan:Nnn \l__tblr_v_tl {} {#1} - \__tblr_data_gput:neene { cell } - { \int_use:N \c@rownum } { \int_use:N \c@colnum } { width } - { \dim_eval:n { \l__tblr_v_tl } } - } - } -\cs_generate_variant:Nn \__tblr_cell_unknown_key:n { V } - -\cs_new_protected:Npn \__tblr_set_span_spec:nn #1 #2 - { - \int_compare:nNnT { #1 } > { 1 } - { - \__tblr_prop_gput:nnn { inner } { rowspan } { true } - \__tblr_data_gput:neenn { cell } - { \int_use:N \c@rownum } { \int_use:N \c@colnum } { rowspan } {#1} - } - \int_compare:nNnT { #2 } > { 1 } - { - \__tblr_prop_gput:nnn { inner } { colspan } { true } - \__tblr_data_gput:neenn { cell } - { \int_use:N \c@rownum } { \int_use:N \c@colnum } { colspan } {#2} - } - \int_step_variable:nnNn - { \int_use:N \c@rownum } { \int_eval:n { \c@rownum + #1 - 1 } } \l__tblr_i_tl - { - \int_step_variable:nnNn - { \int_use:N \c@colnum } { \int_eval:n { \c@colnum + #2 - 1 } } - \l__tblr_j_tl - { - \bool_lazy_and:nnF - { \int_compare_p:nNn { \l__tblr_i_tl } = { \c@rownum } } - { \int_compare_p:nNn { \l__tblr_j_tl } = { \c@colnum } } - { - \__tblr_data_gput:neenn { cell } - { \l__tblr_i_tl } { \l__tblr_j_tl } { omit } {1} - } - \int_compare:nNnF { \l__tblr_i_tl } = { \c@rownum } - { - \__tblr_spec_gput:nen { hline } - { [\l__tblr_i_tl][\l__tblr_j_tl] / omit } {true} - } - \int_compare:nNnF { \l__tblr_j_tl } = { \c@colnum } - { - \__tblr_spec_gput:nee { vline } - { [\l__tblr_i_tl][\l__tblr_j_tl] / omit } {true} - } - } - } - %% Make continuous borders for multirow cells - \tl_set:Nx \l__tblr_n_tl - { - \int_max:nn - { - \__tblr_spec_item:ne { vline } { [\int_use:N \c@colnum] / @vline-count } - } - { 1 } - } - \int_step_variable:nnNn - { \c@rownum } { \int_eval:n { \c@rownum + #1 -1 } } \l__tblr_i_tl - { - \__tblr_spec_gput:nee { vline } - { [\l__tblr_i_tl][\int_use:N \c@colnum](\l__tblr_n_tl) / belowpos } {1} - \__tblr_spec_gput:nee { vline } - { [\l__tblr_i_tl][\int_eval:n {\c@colnum + #2}](1) / belowpos } {1} - } - } -\cs_generate_variant:Nn \__tblr_set_span_spec:nn { VV } - -%% Legacy \multicolumn and \multirow commands -%% Both of them could be replaced with \SetCell command -%% Note that they don't have cell text as the last arguments - -%% If \multicolumn is followed by \multirow, -%% We need to call \tblr_set_cell together -%% in order to omit all hlines inside the span cell. -\tl_new:N \g__tblr_multicolumn_num_tl -\tl_new:N \g__tblr_multicolumn_spec_tl - -%% There maybe p{2em} inside #2 of \multicolumn command -\NewTableCommand \multicolumn [2] - { - \tl_gclear:N \g__tblr_multicolumn_num_tl - \tl_gclear:N \g__tblr_multicolumn_spec_tl - \tl_map_inline:nn {#2} - { - \bool_lazy_and:nnF - { \tl_if_single_token_p:n {##1} } - { \token_if_eq_charcode_p:NN ##1 | } - { \tl_put_right:Nn \g__tblr_multicolumn_spec_tl {,##1} } - } - \peek_meaning:NTF \multirow - { \tl_gset:Nn \g__tblr_multicolumn_num_tl {#1} } - { \tblr_set_cell:nV { c = #1 } \g__tblr_multicolumn_spec_tl } - } - -\NewTableCommand \multirow [3] [m] - { - \tl_if_eq:nnTF {#1} {c} - { \tl_set:Nn \l_tmpa_tl {, m} } - { - \tl_if_eq:nnTF {#1} {t} - { \tl_set:Nn \l_tmpa_tl {, h} } - { \tl_if_eq:nnTF {#1} {b} - { \tl_set:Nn \l_tmpa_tl {, f} } - { \tl_set:Nn \l_tmpa_tl {, #1} } - } - } - \tl_if_eq:nnF {#3} {*} - { \tl_if_eq:nnF {#3} {=} { \tl_put_right:Nn \l_tmpa_tl {, wd=#3} } } - \tl_if_empty:NTF \g__tblr_multicolumn_num_tl - { \tblr_set_cell:nV { r = #2 } \l_tmpa_tl } - { - \tl_put_left:NV \l_tmpa_tl \g__tblr_multicolumn_spec_tl - \exp_args:Nx \tblr_set_cell:nV - { c = \g__tblr_multicolumn_num_tl, r = #2 } \l_tmpa_tl - \tl_gclear:N \g__tblr_multicolumn_num_tl - } - } - -%%% -------------------------------------------------------- -%% \section{Set Columns and Rows} -%%% -------------------------------------------------------- - -%% \SetColumns command for setting every column in the table -\NewTableCommand \SetColumns [2] [] - { - \tblr_set_every_column:nn {#1} {#2} - } - -%% We put all code inside a group to avoid affecting other table commands -\cs_new_protected:Npn \tblr_set_every_column:nn #1 #2 - { - \group_begin: - \int_step_inline:nn { \c@colcount } - { - \int_set:Nn \c@colnum {##1} - \tblr_set_column:nn {#1} {#2} - } - \group_end: - } - -%% Check the number of arguments and call \tblr_set_every_column in different ways -%% This function is called when parsing table specifications -\cs_new_protected:Npn \__tblr_set_every_column_aux:n #1 - { - \tl_if_head_is_group:nTF {#1} - { \tblr_set_every_column:nn #1 } - { \tblr_set_every_column:nn {} {#1} } - } - -%% \SetColumn command for current column or each cells in the column - -\NewTableCommand \SetColumn [2] [] - { - \tblr_set_column:nn {#1} {#2} - } - -\cs_new_protected:Npn \tblr_set_column:nn #1 #2 - { - \keys_set:nn { tblr-column } {#2} - } - -\cs_new_protected:Npn \tblr_set_column:nnn #1 #2 #3 - { - \group_begin: - \__tblr_get_childs:nx {#1} { \int_use:N \c@colcount } - \clist_map_inline:Nn \l_tblr_childs_clist - { - \int_set:Nn \c@colnum {##1} - \tblr_set_column:nn {#2} {#3} - } - \group_end: - } - -%% Check the number of arguments and call \tblr_set_column in different ways -%% Note that #1 always includes an outer pair of braces -%% This function is called when parsing table specifications -\cs_new_protected:Npn \__tblr_set_column_aux:nn #1 #2 - { - \tl_if_head_is_group:nTF {#2} - { \tblr_set_column:nnn #1 #2 } - { \tblr_set_column:nnn #1 {} {#2} } - } -\cs_generate_variant:Nn \__tblr_set_column_aux:nn { Vn } - -\keys_define:nn { tblr-column } - { - halign .code:n = \__tblr_column_gput_cell:nn { halign } {#1}, - valign .code:n = \__tblr_column_gput_cell:nn { valign } {#1}, - j .meta:n = { halign = j }, - l .meta:n = { halign = l }, - c .meta:n = { halign = c }, - r .meta:n = { halign = r }, - t .meta:n = { valign = t }, - p .meta:n = { valign = t }, - m .meta:n = { valign = m }, - b .meta:n = { valign = b }, - h .meta:n = { valign = h }, - f .meta:n = { valign = f }, - bg .code:n = \__tblr_column_gput_cell:nn { background } {#1}, - fg .code:n = \__tblr_column_gput_cell:nn { foreground } {#1}, - font .code:n = \__tblr_column_gput_cell:nn { font } { #1 \selectfont }, - mode .code:n = \__tblr_column_gput_cell:nn { mode } {#1}, - $ .meta:n = { mode = math }, - $$ .meta:n = { mode = dmath }, - cmd .code:n = \__tblr_column_gput_cell:nn { cmd } {#1}, - wd .code:n = \__tblr_column_gput:ne { width } { \dim_eval:n {#1} }, - co .code:n = \__tblr_column_gput:ne { coefficient } {#1}, - preto .code:n = \__tblr_preto_text_for_every_column_cell:n {#1}, - appto .code:n = \__tblr_appto_text_for_every_column_cell:n {#1}, - leftsep .code:n = \__tblr_column_gput:ne { leftsep } { \dim_eval:n {#1} }, - rightsep .code:n = \__tblr_column_gput:ne { rightsep } { \dim_eval:n {#1} }, - colsep .meta:n = { leftsep = #1, rightsep = #1}, - leftsep+ .code:n = \__tblr_column_gadd_dimen:ne - { leftsep } { \dim_eval:n {#1} }, - rightsep+ .code:n = \__tblr_column_gadd_dimen:ne - { rightsep } { \dim_eval:n {#1} }, - colsep+ .meta:n = { leftsep+ = #1, rightsep+ = #1}, - unknown .code:n = \__tblr_column_unknown_key:V \l_keys_key_str, - } - -%% #1: key; #2: value -\cs_new_protected:Npn \__tblr_column_gput:nn #1 #2 - { - \__tblr_data_gput:nenn { column } { \int_use:N \c@colnum } {#1} {#2} - } -\cs_generate_variant:Nn \__tblr_column_gput:nn { ne } - -\cs_new_protected:Npn \__tblr_column_gadd_dimen:nn #1 #2 - { - \__tblr_data_gadd_dimen_value:nenn { column } - { \int_use:N \c@colnum } {#1} {#2} - } -\cs_generate_variant:Nn \__tblr_column_gadd_dimen:nn { ne } - -%% #1: key; #2: value -\cs_new_protected:Npn \__tblr_column_gput_cell:nn #1 #2 - { - \int_step_inline:nn { \c@rowcount } - { - \__tblr_cell_gput:nenn {##1} { \int_use:N \c@colnum } {#1} {#2} - } - } -\cs_generate_variant:Nn \__tblr_column_gput_cell:nn { ne } - -\cs_new_protected:Npn \__tblr_preto_text_for_every_column_cell:n #1 - { - \int_step_inline:nn { \c@rowcount } - { - \__tblr_cell_preto_text:nen {##1} { \int_use:N \c@colnum } {#1} - } - } - -\cs_new_protected:Npn \__tblr_appto_text_for_every_column_cell:n #1 - { - \int_step_inline:nn { \c@rowcount } - { - \__tblr_cell_appto_text:nen {##1} { \int_use:N \c@colnum } {#1} - } - } - -\regex_const:Nn \c__tblr_is_number_key_regex { ^[\+\-]? (\d+|\d*\.\d+)$ } - -\cs_new_protected:Npn \__tblr_column_unknown_key:n #1 - { - \regex_match:NnTF \c__tblr_is_number_key_regex {#1} - { \__tblr_column_gput:ne { coefficient } {#1} } - { - \regex_match:NnTF \c__tblr_is_color_key_regex {#1} - { \__tblr_column_gput_cell:nn { background } {#1} } - { - \tl_set_rescan:Nnn \l__tblr_v_tl {} {#1} - \__tblr_column_gput:ne { width } { \dim_eval:n { \l__tblr_v_tl } } - } - } - } -\cs_generate_variant:Nn \__tblr_column_unknown_key:n { V } - -%% \SetRows command for setting every row in the table -\NewTableCommand \SetRows [2] [] - { - \tblr_set_every_row:nn {#1} {#2} - } - -%% We put all code inside a group to avoid affecting other table commands -\cs_new_protected:Npn \tblr_set_every_row:nn #1 #2 - { - \group_begin: - \int_step_inline:nn { \c@rowcount } - { - \int_set:Nn \c@rownum {##1} - \tblr_set_row:nn {#1} {#2} - } - \group_end: - } - -%% Check the number of arguments and call \tblr_set_every_row in different ways -%% This function is called when parsing table specifications -\cs_new_protected:Npn \__tblr_set_every_row_aux:n #1 - { - \tl_if_head_is_group:nTF {#1} - { \tblr_set_every_row:nn #1 } - { \tblr_set_every_row:nn {} {#1} } - } - -%% \SetRow command for current row or each cells in the row - -\NewTableCommand \SetRow [2] [] - { - \tblr_set_row:nn {#1} {#2} - } - -\cs_new_protected:Npn \tblr_set_row:nn #1 #2 - { - \keys_set:nn { tblr-row } {#2} - } - -\cs_new_protected:Npn \tblr_set_row:nnn #1 #2 #3 - { - \group_begin: - \__tblr_get_childs:nx {#1} { \int_use:N \c@rowcount } - \clist_map_inline:Nn \l_tblr_childs_clist - { - \int_set:Nn \c@rownum {##1} - \tblr_set_row:nn {#2} {#3} - } - \group_end: - } - -%% Check the number of arguments and call \tblr_set_row in different ways -%% Note that #1 always includes an outer pair of braces -%% This function is called when parsing table specifications -\cs_new_protected:Npn \__tblr_set_row_aux:nn #1 #2 - { - \tl_if_head_is_group:nTF {#2} - { \tblr_set_row:nnn #1 #2 } - { \tblr_set_row:nnn #1 {} {#2} } - } -\cs_generate_variant:Nn \__tblr_set_row_aux:nn { Vn } - -\keys_define:nn { tblr-row } - { - halign .code:n = \__tblr_row_gput_cell:nn { halign } {#1}, - valign .code:n = \__tblr_row_gput_cell:nn { valign } {#1}, - j .meta:n = { halign = j }, - l .meta:n = { halign = l }, - c .meta:n = { halign = c }, - r .meta:n = { halign = r }, - t .meta:n = { valign = t }, - p .meta:n = { valign = t }, - m .meta:n = { valign = m }, - b .meta:n = { valign = b }, - h .meta:n = { valign = h }, - f .meta:n = { valign = f }, - bg .code:n = \__tblr_row_gput_cell:nn { background } {#1}, - fg .code:n = \__tblr_row_gput_cell:nn { foreground } {#1}, - font .code:n = \__tblr_row_gput_cell:nn { font } { #1 \selectfont }, - mode .code:n = \__tblr_row_gput_cell:nn { mode } {#1}, - $ .meta:n = { mode = math }, - $$ .meta:n = { mode = dmath }, - cmd .code:n = \__tblr_row_gput_cell:nn { cmd } {#1}, - ht .code:n = \__tblr_row_gput:ne { height } { \dim_eval:n {#1} }, - co .code:n = \__tblr_row_gput:ne { coefficient } {#1}, - preto .code:n = \__tblr_preto_text_for_every_row_cell:n {#1}, - appto .code:n = \__tblr_appto_text_for_every_row_cell:n {#1}, - abovesep .code:n = \__tblr_row_gput:ne { abovesep } { \dim_eval:n {#1} }, - belowsep .code:n = \__tblr_row_gput:ne { belowsep } { \dim_eval:n {#1} }, - rowsep .meta:n = { abovesep = #1, belowsep = #1}, - abovesep+ .code:n = \__tblr_row_gadd_dimen:ne { abovesep } { \dim_eval:n {#1} }, - belowsep+ .code:n = \__tblr_row_gadd_dimen:ne { belowsep } { \dim_eval:n {#1} }, - rowsep+ .meta:n = { abovesep+ = #1, belowsep+ = #1}, - break .code:n = \__tblr_row_gput:nn { break } {#1}, - pagebreak .meta:n = { break = 1 }, - nopagebreak .meta:n = { break = -1 }, - unknown .code:n = \__tblr_row_unknown_key:V \l_keys_key_str, - } - -%% #1: key; #2: value -\cs_new_protected:Npn \__tblr_row_gput:nn #1 #2 - { - \__tblr_data_gput:nenn { row } { \int_use:N \c@rownum } {#1} {#2} - } -\cs_generate_variant:Nn \__tblr_row_gput:nn { ne } - -\cs_new_protected:Npn \__tblr_row_gput_above:nn #1 #2 - { - \__tblr_data_gput:nenn { row } { \int_eval:n { \c@rownum - 1 } } {#1} {#2} - } -\cs_generate_variant:Nn \__tblr_row_gput_above:nn { ne } - -\cs_new_protected:Npn \__tblr_row_gadd_dimen:nn #1 #2 - { - \__tblr_data_gadd_dimen_value:nenn { row } { \int_use:N \c@rownum } {#1} {#2} - } -\cs_generate_variant:Nn \__tblr_row_gadd_dimen:nn { ne } - -\cs_new_protected:Npn \__tblr_row_gadd_dimen_above:nn #1 #2 - { - \__tblr_data_gadd_dimen_value:nenn { row } - { \int_eval:n { \c@rownum - 1 } } {#1} {#2} - } -\cs_generate_variant:Nn \__tblr_row_gadd_dimen_above:nn { ne } - -%% #1: key; #2: value -\cs_new_protected:Npn \__tblr_row_gput_cell:nn #1 #2 - { - \int_step_inline:nn { \c@colcount } - { - \__tblr_cell_gput:ennn { \int_use:N \c@rownum } {##1} {#1} {#2} - } - } -\cs_generate_variant:Nn \__tblr_row_gput_cell:nn { ne } - -\cs_new_protected:Npn \__tblr_preto_text_for_every_row_cell:n #1 - { - \int_step_inline:nn { \c@colcount } - { - \__tblr_cell_preto_text:enn { \int_use:N \c@rownum } {##1} {#1} - } - } - -\cs_new_protected:Npn \__tblr_appto_text_for_every_row_cell:n #1 - { - \int_step_inline:nn { \c@colcount } - { - \__tblr_cell_appto_text:enn { \int_use:N \c@rownum } {##1} {#1} - } - } - -\cs_new_protected:Npn \__tblr_row_unknown_key:n #1 - { - \regex_match:NnTF \c__tblr_is_number_key_regex {#1} - { - \__tblr_data_gput:nene { row } { \int_use:N \c@rownum } - { coefficient } {#1} - } - { - \regex_match:NnTF \c__tblr_is_color_key_regex {#1} - { \__tblr_row_gput_cell:nn { background } {#1} } - { - \tl_set_rescan:Nnn \l__tblr_v_tl {} {#1} - \__tblr_row_gput:ne { height } { \dim_eval:n { \l__tblr_v_tl } } - } - } - } -\cs_generate_variant:Nn \__tblr_row_unknown_key:n { V } - -\NewTableCommand \pagebreak - { - \tblr_set_row:nn {} { break = 1 } - } - -\NewTableCommand \nopagebreak - { - \tblr_set_row:nn {} { break = -1 } - } - -%%% -------------------------------------------------------- -%% \section{Column Types and Row Types} -%%% -------------------------------------------------------- - -%% Some primitive column/row types - -\str_const:Nn \c_tblr_primitive_colrow_types_str { Q | < > } -\tl_new:N \g__tblr_expanded_colrow_spec_tl - -\exp_args:Nc \NewDocumentCommand { tblr_primitive_column_type_ Q } { O{} } - { - \keys_set:nn { tblr-column } { #1 } - \int_incr:N \c@colnum - \__tblr_execute_colrow_spec_next:N - } -\exp_args:Nc \NewDocumentCommand { tblr_column_type_ Q } { O{} } - { - \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { Q[#1] } - \__tblr_expand_colrow_spec_next:N - } - -\exp_args:Nc \NewDocumentCommand { tblr_primitive_row_type_ Q } { O{} } - { - \keys_set:nn { tblr-row } { #1 } - \int_incr:N \c@rownum - \__tblr_execute_colrow_spec_next:N - } -\exp_args:Nc \NewDocumentCommand { tblr_row_type_ Q } { O{} } - { - \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { Q[#1] } - \__tblr_expand_colrow_spec_next:N - } - -\exp_args:Nc \NewDocumentCommand { tblr_primitive_column_type_ | } { O{} } - { - \vline [#1] - \__tblr_execute_colrow_spec_next:N - } -\exp_args:Nc \NewDocumentCommand { tblr_column_type_ | } { O{} } - { - \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { |[#1] } - \__tblr_expand_colrow_spec_next:N - } - -\exp_args:Nc \NewDocumentCommand { tblr_primitive_row_type_ | } { O{} } - { - \hline [#1] - \__tblr_execute_colrow_spec_next:N - } -\exp_args:Nc \NewDocumentCommand { tblr_row_type_ | } { O{} } - { - \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { |[#1] } - \__tblr_expand_colrow_spec_next:N - } - -\exp_args:Nc \NewDocumentCommand { tblr_primitive_column_type_ > } { O{} m } - { - \tl_if_blank:nF {#1} - { - \__tblr_data_gput:nene - { column } - { \int_use:N \c@colnum } { leftsep } - { \dim_eval:n {#1} } - } - \tl_if_blank:nF {#2} - { - \__tblr_preto_text_for_every_column_cell:n {#2} - } - \__tblr_execute_colrow_spec_next:N - } -\exp_args:Nc \NewDocumentCommand { tblr_column_type_ > } { O{} m } - { - \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { >[#1]{#2} } - \__tblr_expand_colrow_spec_next:N - } - -\exp_args:Nc \NewDocumentCommand { tblr_primitive_row_type_ > } { O{} m } - { - \tl_if_blank:nF {#1} - { - \__tblr_data_gput:nene { row } { \int_use:N \c@rownum } - { abovesep } { \dim_eval:n { #1 } } - } - \tl_if_blank:nF {#2} - { - \__tblr_preto_text_for_every_row_cell:n {#2} - } - \__tblr_execute_colrow_spec_next:N - } -\exp_args:Nc \NewDocumentCommand { tblr_row_type_ > } { O{} m } - { - \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { >[#1]{#2} } - \__tblr_expand_colrow_spec_next:N - } - -\exp_args:Nc \NewDocumentCommand { tblr_primitive_column_type_ < } { O{} m } - { - \tl_if_blank:nF {#1} - { - \__tblr_data_gput:nene { column } - { \int_eval:n {\c@colnum - 1} } { rightsep } { \dim_eval:n {#1} } - } - \tl_if_blank:nF {#2} - { - \group_begin: - \int_decr:N \c@colnum - \__tblr_appto_text_for_every_column_cell:n {#2} - \group_end: - } - \__tblr_execute_colrow_spec_next:N - } -\exp_args:Nc \NewDocumentCommand { tblr_column_type_ < } { O{} m } - { - \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { <[#1]{#2} } - \__tblr_expand_colrow_spec_next:N - } - -\exp_args:Nc \NewDocumentCommand { tblr_primitive_row_type_ < } { O{} m } - { - \tl_if_blank:nF {#1} - { - \__tblr_data_gput:nene { row } { \int_eval:n {\c@rownum - 1} } - { belowsep } { \dim_eval:n {#1} } - } - \tl_if_blank:nF {#2} - { - \group_begin: - \int_decr:N \c@rownum - \__tblr_appto_text_for_every_row_cell:n {#2} - \group_end: - } - \__tblr_execute_colrow_spec_next:N - } -\exp_args:Nc \NewDocumentCommand { tblr_row_type_ < } { O{} m } - { - \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { <[#1]{#2} } - \__tblr_expand_colrow_spec_next:N - } - -%% \NewColumnType/\NewRowType command and predefined column/row types - -\str_new:N \g_tblr_used_column_types_str -\str_gset_eq:NN \g_tblr_used_column_types_str \c_tblr_primitive_colrow_types_str - -\str_new:N \g_tblr_used_row_types_str -\str_gset_eq:NN \g_tblr_used_row_types_str \c_tblr_primitive_colrow_types_str - -\bool_new:N \g__tblr_colrow_spec_expand_stop_bool -\tl_new:N \g__tblr_column_or_row_tl - -\msg_new:nnn { tabularray } { used-colrow-type } - { #1 ~ type ~ name ~ #2 ~ has ~ been ~ used! } - -\NewDocumentCommand \NewColumnType { m O{0} o m } - { - \tl_set:Nn \g__tblr_column_or_row_tl { column } - \__tblr_new_column_or_row_type:nnnn {#1} {#2} {#3} {#4} - } - -\NewDocumentCommand \NewRowType { m O{0} o m } - { - \tl_set:Nn \g__tblr_column_or_row_tl { row } - \__tblr_new_column_or_row_type:nnnn {#1} {#2} {#3} {#4} - } - -\NewDocumentCommand \NewColumnRowType { m O{0} o m } - { - \tl_set:Nn \g__tblr_column_or_row_tl { column } - \__tblr_new_column_or_row_type:nnnn {#1} {#2} {#3} {#4} - \tl_set:Nn \g__tblr_column_or_row_tl { row } - \__tblr_new_column_or_row_type:nnnn {#1} {#2} {#3} {#4} - } - -\cs_new_protected:Npn \__tblr_new_column_or_row_type:nnnn #1 #2 #3 #4 - { - \str_if_in:cnTF { g_tblr_used_ \g__tblr_column_or_row_tl _types_str } {#1} - { - \tl_if_eq:NnTF \g__tblr_column_or_row_tl { row } - { \msg_warning:nnnn { tabularray } { used-colrow-type } { Row } {#1} } - { \msg_warning:nnnn { tabularray } { used-colrow-type } { Column } {#1} } - \str_log:c { g_tblr_used_ \g__tblr_column_or_row_tl _types_str } - } - { - \__tblr_make_xparse_arg_spec:nnN {#2} {#3} \l__tblr_a_tl - \exp_args:NcV \NewDocumentCommand - { tblr_ \g__tblr_column_or_row_tl _type_ #1 } \l__tblr_a_tl - { - \bool_gset_false:N \g__tblr_colrow_spec_expand_stop_bool - \tl_gput_right:Nf \g__tblr_expanded_colrow_spec_tl {#4} - \__tblr_expand_colrow_spec_next:N - } - \str_gput_right:cn - { g_tblr_used_ \g__tblr_column_or_row_tl _types_str } {#1} - } - } - -\NewColumnRowType { l } { Q[l] } -\NewColumnRowType { c } { Q[c] } -\NewColumnRowType { r } { Q[r] } -\NewColumnRowType { j } { Q[j] } - -\NewColumnType { t } [1] { Q[t,wd=#1] } -\NewColumnType { p } [1] { Q[p,wd=#1] } -\NewColumnType { m } [1] { Q[m,wd=#1] } -\NewColumnType { b } [1] { Q[b,wd=#1] } -\NewColumnType { h } [1] { Q[h,wd=#1] } -\NewColumnType { f } [1] { Q[f,wd=#1] } - -\NewRowType { t } [1] { Q[t,ht=#1] } -\NewRowType { p } [1] { Q[p,ht=#1] } -\NewRowType { m } [1] { Q[m,ht=#1] } -\NewRowType { b } [1] { Q[b,ht=#1] } -\NewRowType { h } [1] { Q[h,ht=#1] } -\NewRowType { f } [1] { Q[f,ht=#1] } - -\NewColumnRowType { X } [1][] { Q[co=1,#1] } - -\NewColumnRowType { ! } [1] { |[text={#1}] } -\NewColumnRowType { @ } [1] { <[0pt]{} |[text={#1}] >[0pt]{} } -\NewColumnRowType { * } [2] { \prg_replicate:nn {#1} {#2} } - -\cs_new_protected:Npn \__tblr_parse_colrow_spec:nn #1 #2 - { - \tl_gset:Nn \g__tblr_column_or_row_tl {#1} - \tl_gset:Nn \g__tblr_expanded_colrow_spec_tl {#2} - \__tblr_expand_colrow_spec:N \g__tblr_expanded_colrow_spec_tl - \__tblr_execute_colrow_spec:N \g__tblr_expanded_colrow_spec_tl - } - -%% Expand defined column/row types - -\cs_new_protected:Npn \__tblr_expand_colrow_spec:N #1 - { - \bool_do_until:Nn \g__tblr_colrow_spec_expand_stop_bool - { - \LogTblrTracing { colspec, rowspec } - \bool_gset_true:N \g__tblr_colrow_spec_expand_stop_bool - \tl_set_eq:NN \l_tmpa_tl #1 - \tl_gclear:N #1 - \exp_last_unbraced:NV - \__tblr_expand_colrow_spec_next:N \l_tmpa_tl \scan_stop: - } - } - -\msg_new:nnn { tabularray } { unexpandable-colrow-type } - { Unexpandable ~ command ~ #2 inside ~ #1 ~ type! } - -\msg_new:nnn { tabularray } { unknown-colrow-type } - { Unknown ~ #1 ~ type ~ #2! } - -\cs_new_protected:Npn \__tblr_expand_colrow_spec_next:N #1 - { - \token_if_eq_catcode:NNTF #1 \scan_stop: - { - \token_if_eq_meaning:NNF #1 \scan_stop: - { - \msg_error:nnVn { tabularray } { unexpandable-colrow-type } - \g__tblr_column_or_row_tl {#1} - } - } - { - \str_if_in:cnTF { g_tblr_used_ \g__tblr_column_or_row_tl _types_str } {#1} - { - %% Note that #1 may be an active character (see issue #58) - \cs:w tblr_ \g__tblr_column_or_row_tl _type_ \token_to_str:N #1 \cs_end: - } - { - \msg_error:nnVn { tabularray } { unknown-colrow-type } - \g__tblr_column_or_row_tl {#1} - \str_log:c { g_tblr_used_ \g__tblr_column_or_row_tl _types_str } - } - } - } - -%% Execute primitive column/row types - -\cs_new_protected:Npn \__tblr_execute_colrow_spec:N #1 - { - \tl_if_eq:NnTF \g__tblr_column_or_row_tl { row } - { \int_set:Nn \c@rownum {1} } - { \int_set:Nn \c@colnum {1} } - \exp_last_unbraced:NV \__tblr_execute_colrow_spec_next:N #1 \scan_stop: - } - -\cs_new_protected:Npn \__tblr_execute_colrow_spec_next:N #1 - { - \token_if_eq_meaning:NNF #1 \scan_stop: - { \cs:w tblr_primitive_ \g__tblr_column_or_row_tl _type_ #1 \cs_end: } - } - -%%% -------------------------------------------------------- -%% \section{Set Environments and New Environments} -%%% -------------------------------------------------------- - -\tl_new:N \l__tblr_initial_tblr_outer_tl -\tl_set:Nn \l__tblr_initial_tblr_outer_tl - { - halign = c, valign = m, headsep = 6pt, footsep = 6pt, - presep = 1.5\bigskipamount, postsep = 1.5\bigskipamount, - } - -%% #1: env name; #2: specifications -\NewDocumentCommand \SetTblrInner { O{tblr} m } - { - \tl_put_right:cn { l__tblr_default_ #1 _inner_tl } { , #2 } - \ignorespaces - } -\cs_new_eq:NN \SetTblrDefault \SetTblrInner - -%% #1: env name; #2: specifications -\NewDocumentCommand \SetTblrOuter { O{tblr} m } - { - \tl_put_right:cn { l__tblr_default_ #1 _outer_tl } { , #2 } - \ignorespaces - } - -%% #1: env name -\NewDocumentCommand \NewTblrEnviron { m } - { - \tl_new:c { l__tblr_default_ #1 _outer_tl } - \tl_set_eq:cN { l__tblr_default_ #1 _outer_tl } \l__tblr_initial_tblr_outer_tl - \tl_new:c { l__tblr_default_ #1 _inner_tl } - \NewDocumentEnvironment {#1} { O{c} m +b } - { - \__tblr_environ_code:nnnn {#1} {##1} {##2} {##3} - } { } - \ignorespaces - } - -%% Create tblr and longtblr environments -\NewTblrEnviron { tblr } -\NewTblrEnviron { longtblr } -\SetTblrOuter [ longtblr ] { long } -\NewTblrEnviron { talltblr } -\SetTblrOuter [ talltblr ] { tall } - -\tl_new:N \l__tblr_env_name_tl -\bool_new:N \l__tblr_math_mode_bool - -%% Main environment code -\cs_new_protected:Npn \__tblr_environ_code:nnnn #1 #2 #3 #4 - { - \int_gincr:N \g__tblr_table_count_int - \tl_set:Nn \l__tblr_env_name_tl {#1} - \mode_if_math:TF - { \bool_set_true:N \l__tblr_math_mode_bool } - { \bool_set_false:N \l__tblr_math_mode_bool } - \__tblr_builder:nnn {#2} {#3} {#4} - } - -%% Read, split and build the table -\cs_new_protected:Npn \__tblr_builder:nnn #1 #2 #3 - { - \int_gincr:N \g_tblr_level_int - \__tblr_clear_prop_lists: - \__tblr_clear_spec_lists: - \LogTblrTracing { step = init ~ table ~ outer ~ spec} - \__tblr_init_table_outer_spec: - \LogTblrTracing { step = parse ~ table ~ options } - \__tblr_parse_table_option:n {#1} - \LogTblrTracing { outer } - \LogTblrTracing { option } - \__tblr_enable_table_commands: - \LogTblrTracing { step = split ~ table} - \__tblr_split_table:n {#3} - \LogTblrTracing { command } - \bool_if:NT \g__tblr_use_intarray_bool { \__tblr_init_table_data: } - \LogTblrTracing { step = init ~ table ~ inner ~ spec} - \__tblr_init_table_inner_spec: - \LogTblrTracing { inner } - \LogTblrTracing { step = parse ~ table ~ inner ~ spec} - \__tblr_parse_table_spec:n {#2} - \LogTblrTracing { step = execute ~ table ~ commands} - \__tblr_execute_table_commands: - \__tblr_disable_table_commands: - \LogTblrTracing { step = calculate ~ cell ~ and ~ line ~ sizes} - \__tblr_enable_content_commands: - \__tblr_calc_cell_and_line_sizes: - \LogTblrTracing { step = build ~ the ~ whole ~ table} - \__tblr_build_whole: - \int_gdecr:N \g_tblr_level_int - } - -%%% -------------------------------------------------------- -%% \section{Split Table Contents} -%%% -------------------------------------------------------- - -%% Insert and remove braces for nesting environments inside cells -%% These make line split and cell split workable -%% We need to replace N times for N level nestings -\regex_const:Nn \c__tblr_insert_braces_regex - { - \c{begin} \cB\{ (\c[^BE].*) \cE\} (.*?) \c{end} \cB\{ (\c[^BE].*) \cE\} - } -\tl_const:Nn \c__tblr_insert_braces_tl - { - \c{begin} \cB\{ \cB\{ \1 \cE\} \2 \c{end} \cE\} \cB\{ \3 \cE\} - } -\regex_const:Nn \c__tblr_remove_braces_regex - { - \c{begin} \cB\{ \cB\{ (.*?) \c{end} \cE\} - } -\tl_const:Nn \c__tblr_remove_braces_tl - { - \c{begin} \cB\{ \1 \c{end} - } -\cs_new_protected:Npn \__tblr_insert_braces:N #1 - { - \regex_replace_all:NVN \c__tblr_insert_braces_regex \c__tblr_insert_braces_tl #1 - \regex_replace_all:NVN \c__tblr_insert_braces_regex \c__tblr_insert_braces_tl #1 - } -\cs_new_protected:Npn \__tblr_remove_braces:N #1 - { - \regex_replace_all:NVN \c__tblr_remove_braces_regex \c__tblr_remove_braces_tl #1 - \regex_replace_all:NVN \c__tblr_remove_braces_regex \c__tblr_remove_braces_tl #1 - } - -\tl_new:N \l__tblr_body_tl -\tl_new:N \l__tblr_expand_tl -\seq_new:N \l__tblr_lines_seq - -%% Expand every occurrence of the specified macro once -%% #1: table content; #2: macro to be expanded -\cs_new_protected:Npn \__tblr_expand_table_body:nN #1 #2 - { - \tl_clear:N \l__tblr_body_tl - \cs_set_protected:Npn \__tblr_expand_table_body_aux:w ##1 #2 - { - \tl_put_right:Nn \l__tblr_body_tl {##1} - \peek_meaning:NTF \q_stop - { \use_none:n } - { \exp_last_unbraced:NV \__tblr_expand_table_body_aux:w #2 } - } - \__tblr_expand_table_body_aux:w #1 #2 \q_stop - } - -%% Split table content to cells and store them -%% #1: table content -\cs_new_protected:Npn \__tblr_split_table:n #1 - { - \tl_set:Nx \l__tblr_expand_tl { \__tblr_spec_item:nn { outer } { expand } } - \tl_set:Nx \l__tblr_expand_tl { \tl_head:N \l__tblr_expand_tl } - \tl_if_empty:NTF \l__tblr_expand_tl - { \tl_set:Nn \l__tblr_body_tl {#1} } - { \exp_args:NnV \__tblr_expand_table_body:nN {#1} \l__tblr_expand_tl } - \int_zero:N \c@rowcount - \int_zero:N \c@colcount - \__tblr_split_table_to_lines:NN \l__tblr_body_tl \l__tblr_lines_seq - \__tblr_split_lines_to_cells:N \l__tblr_lines_seq - } - -%% Split table content to a sequence of lines -%% #1: tl with table contents, #2: resulting sequence of lines -\cs_new_protected:Npn \__tblr_split_table_to_lines:NN #1 #2 - { - \__tblr_insert_braces:N #1 - \seq_set_split:NnV \l_tmpa_seq { \\ } #1 - \seq_clear:N #2 - \seq_map_inline:Nn \l_tmpa_seq - { - \tl_if_head_eq_meaning:nNTF {##1} * - { - \tl_set:Nn \l__tblr_b_tl { \SetRow { break = -1 } } - \tl_set:Nx \l__tblr_c_tl { \tl_tail:n {##1} } - \tl_trim_spaces:N \l__tblr_c_tl %% Ignore spaces between * and [dimen] - \tl_if_head_eq_meaning:VNT \l__tblr_c_tl [ - { - \tl_put_right:Nn \l__tblr_b_tl { \RowBefore@AddBelowSep } - } - \tl_put_right:NV \l__tblr_b_tl \l__tblr_c_tl - \seq_put_right:NV #2 \l__tblr_b_tl - } - { - \tl_if_head_eq_meaning:nNTF { ##1 } [ - { \seq_put_right:Nn #2 { \RowBefore@AddBelowSep ##1 } } - { \seq_put_right:Nn #2 { ##1 } } - } - } - \int_set:Nn \c@rowcount { \seq_count:N #2 } - } - -%% Treat \\[dimen] command -\NewTableCommand \RowBefore@AddBelowSep [1] [] - { - \IfValueT { #1 } - { - \__tblr_data_gadd_dimen_value:nene { row } - { \int_eval:n {\c@rownum - 1} } { belowsep } {#1} - } - } - -%% Split table lines to cells and store them -%% #1: sequence of lines -\cs_new_protected:Npn \__tblr_split_lines_to_cells:N #1 - { - \seq_map_indexed_function:NN #1 \__tblr_split_one_line:nn - \LogTblrTracing { text } - } - -%% Split one line into cells and store them -%% #1: row number, #2 the line text -\cs_new_protected:Npn \__tblr_split_one_line:nn #1 #2 - { - \seq_set_split:Nnn \l_tmpa_seq { & } { #2 } - \int_set:Nn \c@rownum {#1} - \int_zero:N \c@colnum - \seq_map_inline:Nn \l_tmpa_seq - { - \tl_set:Nn \l_tmpa_tl { ##1 } - \__tblr_remove_braces:N \l_tmpa_tl - \__tblr_trim_par_space_tokens:N \l_tmpa_tl - \int_incr:N \c@colnum - \__tblr_extract_table_commands:N \l_tmpa_tl - \__tblr_trim_par_space_tokens:N \l_tmpa_tl - \__tblr_spec_gput:neV { text } { [#1][\int_use:N \c@colnum] } \l_tmpa_tl - \__tblr_add_multicolumn_empty_cell: - } - %% Decrease row count by 1 if the last row has only one empty cell text - %% We need to do it here since the > or < column type may add text to cells - \bool_lazy_all:nTF - { - { \int_compare_p:nNn {#1} = {\c@rowcount} } - { \int_compare_p:nNn {\c@colnum} = {1} } - { \tl_if_empty_p:N \l_tmpa_tl } - } - { \int_decr:N \c@rowcount } - { - \__tblr_prop_gput:nnx - {row} { [#1] / cell-number } { \int_use:N \c@colnum } - \int_compare:nT { \c@colnum > \c@colcount } - { - \int_set_eq:NN \c@colcount \c@colnum - } - } - } - -\regex_const:Nn \c__tblr_trim_left_par_space_regex { ^ \c{par} ? \s * } -\regex_const:Nn \c__tblr_trim_right_space_par_regex { \s * \c{par} ? $ } - -\cs_new_protected:Npn \__tblr_trim_par_space_tokens:N #1 - { - \regex_replace_once:NnN \c__tblr_trim_left_par_space_regex {} #1 - \regex_replace_once:NnN \c__tblr_trim_right_space_par_regex {} #1 - } - -%% Add empty cells after the \multicolumn span cell -\cs_new_protected:Npn \__tblr_add_multicolumn_empty_cell: - { - \int_step_inline:nn { \l__multicolumn_cell_number_int - 1 } - { - \int_incr:N \c@colnum - \__tblr_spec_gput:nen { text } - { [\int_use:N \c@rownum][\int_use:N \c@colnum] } { } - } - } - -%%% -------------------------------------------------------- -%% \section{Extract Table Commands from Cell Text} -%%% -------------------------------------------------------- - -%% Extract table commands defined with \NewTableCommand from cell text - -\clist_gset:Nn \g__tblr_table_commands_unbrace_next_clist {\multirow, \multicolumn} -\bool_new:N \l__tblr_table_command_unbrace_next_bool -\int_new:N \l__multicolumn_cell_number_int -\tl_new:N \l__tblr_saved_table_commands_before_cell_text_tl -\tl_new:N \l__tblr_saved_cell_text_after_table_commands_tl - -\cs_new_protected:Npn \__tblr_extract_table_commands:N #1 - { - \tl_clear:N \l__tblr_saved_table_commands_before_cell_text_tl - \tl_clear:N \l__tblr_saved_cell_text_after_table_commands_tl - \int_set:Nn \l__multicolumn_cell_number_int {1} - \exp_last_unbraced:NV \__tblr_extract_table_commands_next:n #1 \q_stop - \tl_if_empty:NF \l__tblr_saved_table_commands_before_cell_text_tl - { - \__tblr_prop_gput:nxV { command } - {[\int_use:N \c@rownum][\int_use:N \c@colnum]} - \l__tblr_saved_table_commands_before_cell_text_tl - } - \tl_set_eq:NN #1 \l__tblr_saved_cell_text_after_table_commands_tl - } - -%% #1 maybe a single token or multiple tokens from a pair of braces -\cs_new_protected:Npn \__tblr_extract_table_commands_next:n #1 - { - \tl_if_single_token:nTF {#1} - { - \clist_if_in:NnTF \g__tblr_table_commands_clist { #1 } - { - \clist_if_in:NnTF \g__tblr_table_commands_unbrace_next_clist { #1 } - { \bool_set_true:N \l__tblr_table_command_unbrace_next_bool } - { \bool_set_false:N \l__tblr_table_command_unbrace_next_bool } - \token_if_eq_meaning:NNTF #1 \multicolumn - { \__tblr_extract_multicolumn_command:Nn #1 } - { \__tblr_extract_one_table_command:N #1 } - } - { - \token_if_eq_meaning:NNF #1 \q_stop - { \__tblr_save_real_cell_text:w #1 } - } - } - { \__tblr_save_real_cell_text:w {#1} } - } - -\cs_new_protected:Npn \__tblr_extract_multicolumn_command:Nn #1 #2 - { - \int_set:Nn \l__multicolumn_cell_number_int {#2} - \__tblr_extract_one_table_command:N #1 {#2} - } - -\cs_new_protected:Npn \__tblr_extract_one_table_command:N #1 - { - \int_set:Nn \l__tblr_a_int - { \cs:w g__tblr_table_cmd_ \cs_to_str:N #1 _arg_numb_tl \cs_end: } - \tl_put_right:Nn \l__tblr_saved_table_commands_before_cell_text_tl {#1} - \int_compare:nNnTF {\l__tblr_a_int} < {0} - { - \int_set:Nn \l__tblr_a_int { \int_abs:n {\l__tblr_a_int} - 1 } - \peek_charcode:NTF [ - { \__tblr_extract_table_command_arg_o:w } - { \__tblr_extract_table_command_arg_next: } - } - { \__tblr_extract_table_command_arg_next: } - } - -\cs_new_protected:Npn \__tblr_extract_table_command_arg_o:w [#1] - { - \tl_put_right:Nn \l__tblr_saved_table_commands_before_cell_text_tl { [#1] } - \__tblr_extract_table_command_arg_next: - } - -\cs_new_protected:Npn \__tblr_extract_table_command_arg_m:n #1 - { - \tl_put_right:Nn \l__tblr_saved_table_commands_before_cell_text_tl { {#1} } - \__tblr_extract_table_command_arg_next: - } - -\cs_new_protected:Npn \__tblr_extract_table_command_arg_next: - { - \int_compare:nNnTF {\l__tblr_a_int} > {0} - { - \int_decr:N \l__tblr_a_int - \__tblr_extract_table_command_arg_m:n - } - { - \bool_if:NTF \l__tblr_table_command_unbrace_next_bool - { \__tblr_last_unbraced:Nn \__tblr_extract_table_commands_next:n } - { \__tblr_extract_table_commands_next:n } - } - } - -\cs_new_protected:Npn \__tblr_last_unbraced:Nn #1 #2 { #1 #2 } - -%% The outermost set of braces of cell text #1 will be removed -\cs_new_protected:Npn \__tblr_save_real_cell_text:w #1 \q_stop - { - \tl_set:Nn \l__tblr_saved_cell_text_after_table_commands_tl {#1} - } - -%%% -------------------------------------------------------- -%% \section{Initialize Table Inner Specifications} -%%% -------------------------------------------------------- - -\prop_gset_from_keyval:Nn \g__tblr_initial_table_prop - { - stretch = 1, - rulesep = 2pt, - } - -\prop_gset_from_keyval:Nn \g__tblr_initial_rows_prop - { - abovesep = 2pt, - belowsep = 2pt, - @row-height = 0pt, - @row-head = 0pt, - @row-foot = 0pt, - @row-upper = 0pt, - @row-lower = 0pt, - } - -\prop_gset_from_keyval:Nn \g__tblr_initial_columns_prop - { - leftsep = 6pt, - rightsep = 6pt, - width = -1pt, % column width unset - coefficient = 0, % column coefficient unset - @col-width = 0pt, - } - -\prop_gset_from_keyval:Nn \g__tblr_initial_cells_prop - { - halign = l, - valign = t, - width = -1pt, % cell width unset - rowspan = 1, - colspan = 1, - omit = 0, - } - -\prop_gset_from_keyval:Nn \g__tblr_initial_hlines_prop - { - @hline-count = 0, - } - -\prop_gset_from_keyval:Nn \g__tblr_initial_vlines_prop - { - @vline-count = 0, - } - -\tl_new:N \l__tblr_inner_spec_measure_tl -\tl_new:N \l__tblr_inner_spec_verb_tl - -\cs_new_protected:Npn \__tblr_init_table_inner_spec: - { - \prop_map_inline:Nn \g__tblr_initial_table_prop - { - \__tblr_prop_gput:nxn { inner } { ##1 } {##2} - } - \int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl - { - \prop_map_inline:Nn \g__tblr_initial_rows_prop - { - \__tblr_data_gput:nVnn { row } \l__tblr_i_tl {##1} {##2} - } - \prop_map_inline:Nn \g__tblr_initial_hlines_prop - { - \__tblr_spec_gput:nen { hline } { [\l__tblr_i_tl] / ##1 } {##2} - } - \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl - { - \prop_map_inline:Nn \g__tblr_initial_cells_prop - { - \__tblr_data_gput:neeen { cell } - { \l__tblr_i_tl } { \l__tblr_j_tl } {##1} {##2} - } - } - } - \prop_map_inline:Nn \g__tblr_initial_hlines_prop - { - \__tblr_spec_gput:nen { hline } - { [\int_eval:n { \c@rowcount + 1}] / ##1 } {##2} - } - \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl - { - \prop_map_inline:Nn \g__tblr_initial_columns_prop - { - \__tblr_data_gput:nenn { column } { \l__tblr_j_tl } {##1} {##2} - } - \prop_map_inline:Nn \g__tblr_initial_vlines_prop - { - \__tblr_spec_gput:nen { vline } { [\l__tblr_j_tl] / ##1 } {##2} - } - } - \prop_map_inline:Nn \g__tblr_initial_vlines_prop - { - \__tblr_spec_gput:nen { vline } - { [\int_eval:n { \c@colcount + 1}] / ##1 } {##2} - } - \tl_clear:N \l__tblr_inner_spec_measure_tl - \tl_clear:N \l__tblr_inner_spec_verb_tl - \keys_set:nv { tblr } { l__tblr_default_ \l__tblr_env_name_tl _inner_tl } - } - -%%% -------------------------------------------------------- -%%> \section{Parse Table Inner Specifications} -%%% -------------------------------------------------------- - -\clist_new:N \g__tblr_table_known_keys_clist -\clist_gset:Nn \g__tblr_table_known_keys_clist - { - colspec, rowspec, width, hspan, vspan, stretch, verb, - column, row, cell, vline, hline, columns, rows, cells, vlines, hlines, - leftsep, rightsep, colsep, abovesep, belowsep, rowsep, rulesep, - rowhead, rowfoot, - } - -\keys_define:nn { tblr } - { - colspec .code:n = \__tblr_parse_colrow_spec:nn { column } {#1}, - rowspec .code:n = \__tblr_parse_colrow_spec:nn { row } {#1}, - width .code:n = \__tblr_keys_gput:nx { width } { \dim_eval:n {#1} }, - hspan .code:n = \__tblr_keys_gput:nn { hspan } {#1}, - vspan .code:n = \__tblr_keys_gput:nn { vspan } {#1}, - stretch .code:n = \__tblr_keys_gput:nn { stretch } {#1}, - verb .tl_set:N = \l__tblr_inner_spec_verb_tl, - verb .default:n = lite, - columns .code:n = \__tblr_set_every_column_aux:n {#1}, - rows .code:n = \__tblr_set_every_row_aux:n {#1}, - cells .code:n = \__tblr_set_every_cell_aux:n {#1}, - hlines .code:n = \__tblr_set_every_hline_aux:n {#1}, - vlines .code:n = \__tblr_set_every_vline_aux:n {#1}, - leftsep .code:n = \tblr_set_every_column:nn { } { leftsep = #1 }, - rightsep .code:n = \tblr_set_every_column:nn { } { rightsep = #1 }, - colsep .meta:n = { leftsep = #1, rightsep = #1 }, - abovesep .code:n = \tblr_set_every_row:nn { } { abovesep = #1 }, - belowsep .code:n = \tblr_set_every_row:nn { } { belowsep = #1 }, - rowsep .meta:n = { abovesep = #1, belowsep = #1 }, - rulesep .code:n = \__tblr_keys_gput:nn { rulesep } {#1}, - rowhead .code:n = \__tblr_keys_gput:nn { rowhead } {#1}, - rowfoot .code:n = \__tblr_keys_gput:nn { rowfoot } {#1}, - unknown .code:n = \__tblr_table_special_key:Vn \l_keys_key_str {#1}, - } - -\regex_const:Nn \c__tblr_split_key_name_regex { ^ ( [a-z] + ) ( . * ) } - -\cs_new_protected:Npn \__tblr_table_special_key:nn #1 #2 - { - \regex_extract_once:NnNT \c__tblr_split_key_name_regex {#1} \l_tmpa_seq - { - \tl_set:Nx \l__tblr_a_tl { \seq_item:Nn \l_tmpa_seq {2} } - \tl_set_rescan:Nnx \l__tblr_b_tl {} { \seq_item:Nn \l_tmpa_seq {3} } - \cs:w __tblr_set_ \l__tblr_a_tl _aux:Vn \cs_end: \l__tblr_b_tl {#2} - } - } -\cs_generate_variant:Nn \__tblr_table_special_key:nn { Vn } - -%% If the first key name is known, treat #1 is the table spec; -%% otherwise, treat #1 as colspec. - -\regex_const:Nn \c__tblr_first_key_name_regex { ^ \s * ( [A-Za-z\-] + ) } - -\cs_new_protected:Npn \__tblr_parse_table_spec:n #1 - { - \regex_extract_once:NnNTF \c__tblr_first_key_name_regex {#1} \l_tmpa_seq - { - \clist_if_in:NxTF \g__tblr_table_known_keys_clist - { \seq_item:Nn \l_tmpa_seq {2} } - { \keys_set:nn { tblr } {#1} } - { \__tblr_parse_colrow_spec:nn { column } {#1} } - } - { \__tblr_parse_colrow_spec:nn { column } {#1} } - } - -\cs_new_protected:Npn \__tblr_keys_gput:nn #1 #2 - { - \__tblr_prop_gput:nnn { inner } {#1} {#2} - } -\cs_generate_variant:Nn \__tblr_keys_gput:nn { nx } - -%%% -------------------------------------------------------- -%% \section{Initialize and Parse Table Outer Specifications} -%%% -------------------------------------------------------- - -%% #1: theme names; #2: template and style commands -\NewDocumentCommand \NewTblrTheme { m +m } - { - \tl_set:cn { g__tblr_theme_ #1 _code_tl } {#2} - \ignorespaces - } - -\cs_new_protected:Npn \__tblr_use_theme:n #1 - { - \ignorespaces - \tl_use:c { g__tblr_theme_ #1 _code_tl } - } - -\cs_new_protected:Npn \__tblr_init_table_outer_spec: - { - \keys_set:nv { tblr-outer } { l__tblr_default_ \l__tblr_env_name_tl _outer_tl } - } - -\cs_new_protected:Npn \__tblr_parse_table_option:n #1 - { - \keys_set:nn { tblr-outer } {#1} - } - -\keys_define:nn { tblr-outer } - { - long .code:n = \__tblr_outer_gput_spec:nn { long } { true }, - tall .code:n = \__tblr_outer_gput_spec:nn { tall } { true }, - halign .code:n = \__tblr_outer_gput_spec:nn { halign } {#1}, - valign .code:n = \__tblr_outer_gput_spec:nn { valign } {#1}, - l .meta:n = { halign = l }, - c .meta:n = { halign = c }, - r .meta:n = { halign = r }, - t .meta:n = { valign = t }, - m .meta:n = { valign = m }, - b .meta:n = { valign = b }, - expand .code:n = \__tblr_outer_gput_spec:nn { expand } {#1}, - headsep .code:n = \__tblr_outer_gput_spec:nn { headsep } {#1}, - footsep .code:n = \__tblr_outer_gput_spec:nn { footsep } {#1}, - presep .code:n = \__tblr_outer_gput_spec:nn { presep } {#1}, - postsep .code:n = \__tblr_outer_gput_spec:nn { postsep } {#1}, - theme .code:n = \__tblr_use_theme:n {#1}, - caption .code:n = \__tblr_outer_gput_spec:nn { caption } {#1}, - entry .code:n = \__tblr_outer_gput_spec:nn { entry } {#1}, - label .code:n = \__tblr_outer_gput_spec:nn { label } {#1}, - unknown .code:n = \__tblr_table_option_key:Vn \l_keys_key_str {#1}, - } - -\cs_new_protected:Npn \__tblr_outer_gput_spec:nn #1 #2 - { - \__tblr_spec_gput:nen { outer } {#1} {#2} - } - -\regex_const:Nn \c__tblr_option_key_name_regex { ^ [A-Za-z\-] + $ } - -\msg_new:nnn { tabularray } { unknown-outer-key } - { Unknown ~ outer ~ key ~ name ~ #1! } - -\cs_new_protected:Npn \__tblr_table_option_key:nn #1 #2 - { - \regex_match:NnTF \c__tblr_option_key_name_regex {#1} - { \msg_error:nnn { tabularray } { unknown-outer-key } {#1} } - { - \regex_extract_once:NnNT \c__tblr_split_key_name_regex {#1} \l_tmpa_seq - { - \tl_set:Nx \l__tblr_a_tl { \seq_item:Nn \l_tmpa_seq {2} } - \tl_set_rescan:Nnx \l__tblr_b_tl {} { \seq_item:Nn \l_tmpa_seq {3} } - \tl_set:Nx \l__tblr_c_tl { \tl_head:N \l__tblr_b_tl } - \use:c { __tblr_outer_gput_ \l__tblr_a_tl :Vn } \l__tblr_c_tl {#2} - } - } - } -\cs_generate_variant:Nn \__tblr_table_option_key:nn { Vn } - -\cs_new_protected:Npn \__tblr_outer_gput_note:nn #1 #2 - { - \__tblr_prop_gput:nnn { note } {#1} {#2} - } -\cs_generate_variant:Nn \__tblr_outer_gput_note:nn { Vn } - -\cs_new_protected:Npn \__tblr_outer_gput_remark:nn #1 #2 - { - \__tblr_prop_gput:nnn { remark } {#1} {#2} - } -\cs_generate_variant:Nn \__tblr_outer_gput_remark:nn { Vn } - -\cs_new_protected:Npn \__tblr_outer_gput_more:nn #1 #2 - { - \__tblr_prop_gput:nnn { more } {#1} {#2} - } -\cs_generate_variant:Nn \__tblr_outer_gput_more:nn { Vn } - -%%% -------------------------------------------------------- -%% \section{Typeset and Calculate Sizes} -%%% -------------------------------------------------------- - -%% Calculate the width and height for every cell and border - -\cs_new_protected:Npn \__tblr_calc_cell_and_line_sizes: - { - \__tblr_make_strut_box: - \__tblr_calculate_line_sizes: - \__tblr_calculate_cell_sizes: - \LogTblrTracing { cell, row, column, hline, vline } - \__tblr_compute_extendable_column_width: - \__tblr_adjust_sizes_for_span_cells: - } - -%% make strut box from stretch option of the table - -\box_new:N \l__tblr_strut_ht_box -\box_new:N \l__tblr_strut_dp_box - -\cs_new_protected:Npn \__tblr_make_strut_box: - { - \tl_set:Nx \l__tblr_s_tl { \__tblr_prop_item:ne { inner } { stretch } } - \hbox_set:Nn \l__tblr_strut_ht_box - { \vrule height \l__tblr_s_tl \box_ht:N \strutbox width ~ 0pt } - \hbox_set:Nn \l__tblr_strut_dp_box - { \vrule depth \l__tblr_s_tl \box_dp:N \strutbox width ~ 0pt } - } - -%% Calculate the thickness for every hline and vline -\cs_new_protected:Npn \__tblr_calculate_line_sizes: - { - %% We need these two counters in executing hline and vline commands - \int_zero:N \c@rownum - \int_zero:N \c@colnum - \int_step_inline:nn { \c@rowcount + 1 } - { - \int_incr:N \c@rownum - \int_zero:N \c@colnum - \int_step_inline:nn { \c@colcount + 1 } - { - \int_incr:N \c@colnum - \int_compare:nNnT { ##1 } < { \c@rowcount + 1 } - { - \__tblr_measure_and_update_vline_size:nn { ##1 } { ####1 } - } - \int_compare:nNnT { ####1 } < { \c@colcount + 1 } - { - \__tblr_measure_and_update_hline_size:nn { ##1 } { ####1 } - } - } - } - } - -%% Measure and update thickness of the vline -%% #1: row number, #2 column number -\cs_new_protected:Npn \__tblr_measure_and_update_vline_size:nn #1 #2 - { - \dim_zero:N \l__tblr_w_dim - \tl_set:Nx \l__tblr_n_tl - { \__tblr_spec_item:ne { vline } { [#2] / @vline-count } } - \int_compare:nNnT { \l__tblr_n_tl } > {0} - { - \tl_set:Nx \l__tblr_s_tl - { \__tblr_prop_item:ne { inner } { rulesep } } - \int_step_inline:nn { \l__tblr_n_tl } - { - \vbox_set_to_ht:Nnn \l__tblr_b_box {1pt} - { - \__tblr_get_vline_segment_child:nnnnn - {#1} {#2} {##1} {1pt} {1pt} - } - \tl_set:Nx \l__tblr_w_tl { \dim_eval:n { \box_wd:N \l__tblr_b_box } } - \__tblr_spec_gput_if_larger:nee { vline } - { [#2](##1) / @vline-width } { \l__tblr_w_tl } - \dim_add:Nn \l__tblr_w_dim { \l__tblr_w_tl } - \dim_add:Nn \l__tblr_w_dim { \l__tblr_s_tl } - } - \dim_add:Nn \l__tblr_w_dim { - \l__tblr_s_tl } - } - \__tblr_spec_gput_if_larger:nee { vline } - { [#2]/ @vline-width } { \dim_use:N \l__tblr_w_dim } - } - -%% Get text of a vline segment -%% #1: row number, #2: column number; #3: index number; #4: height; #5: depth -%% We put all code inside a group to avoid conflicts of local variables -\cs_new_protected:Npn \__tblr_get_vline_segment_child:nnnnn #1 #2 #3 #4 #5 - { - \group_begin: - \tl_set:Nx \l__tblr_w_tl - { \__tblr_spec_item:ne { vline } { [#1][#2](#3) / wd } } - \tl_if_empty:NF \l__tblr_w_tl { \dim_set:Nn \rulewidth { \l__tblr_w_tl } } - \tl_set:Nx \l__tblr_d_tl - { \__tblr_spec_item:ne { vline } { [#1][#2](#3) / @dash } } - \tl_set:Nx \l__tblr_a_tl { \tl_head:N \l__tblr_d_tl } - \tl_set:Nx \l__tblr_b_tl { \tl_tail:N \l__tblr_d_tl } - \exp_args:NV \tl_if_eq:NNTF \l__tblr_a_tl \@tblr@dash - { - \__tblr_get_vline_dash_style:N \l__tblr_b_tl - \xleaders \l__tblr_b_tl \vfil - } - { - %% When using text as vline, we need to omit abovepos and belowpos. - \unskip - \hbox_set:Nn \l__tblr_d_box { \l__tblr_b_tl } - \box_set_ht:Nn \l__tblr_d_box {#4} - \box_set_dp:Nn \l__tblr_d_box {#5} - \box_use:N \l__tblr_d_box - \vss - } - \group_end: - } -\cs_generate_variant:Nn \__tblr_get_vline_segment_child:nnnnn { nnnxx } - -%% Measure and update thickness of the hline -%% #1: row number, #2 column number -\cs_new_protected:Npn \__tblr_measure_and_update_hline_size:nn #1 #2 - { - \dim_zero:N \l__tblr_h_dim - \tl_set:Nx \l__tblr_n_tl - { \__tblr_spec_item:ne { hline } { [#1] / @hline-count } } - \int_compare:nNnT { \l__tblr_n_tl } > {0} - { - \tl_set:Nx \l__tblr_s_tl - { \__tblr_prop_item:ne { inner } { rulesep } } - \int_step_inline:nn { \l__tblr_n_tl } - { - \hbox_set_to_wd:Nnn \l__tblr_b_box {1pt} - { \__tblr_get_hline_segment_child:nnn {#1} {#2} {##1} } - \tl_set:Nx \l__tblr_h_tl - { - \dim_eval:n - { \box_ht:N \l__tblr_b_box + \box_dp:N \l__tblr_b_box } - } - \__tblr_spec_gput_if_larger:nee { hline } - { [#1](##1) / @hline-height } { \l__tblr_h_tl } - \dim_add:Nn \l__tblr_h_dim { \l__tblr_h_tl } - \dim_add:Nn \l__tblr_h_dim { \l__tblr_s_tl } - } - \dim_add:Nn \l__tblr_h_dim { - \l__tblr_s_tl } - } - \__tblr_spec_gput_if_larger:nee { hline } - { [#1] / @hline-height } { \dim_use:N \l__tblr_h_dim } - } - -%% Get text of a hline segment -%% #1: row number, #2: column number; #3: index number -\cs_new_protected:Npn \__tblr_get_hline_segment_child:nnn #1 #2 #3 - { - \group_begin: - \tl_set:Nx \l__tblr_w_tl - { \__tblr_spec_item:ne { hline } { [#1][#2](#3) / wd } } - \tl_if_empty:NF \l__tblr_w_tl { \dim_set:Nn \rulewidth { \l__tblr_w_tl } } - \tl_set:Nx \l__tblr_d_tl - { \__tblr_spec_item:ne { hline } { [#1][#2](#3) / @dash } } - \tl_set:Nx \l__tblr_a_tl { \tl_head:N \l__tblr_d_tl } - \tl_set:Nx \l__tblr_b_tl { \tl_tail:N \l__tblr_d_tl } - \exp_args:NV \tl_if_eq:NNTF \l__tblr_a_tl \@tblr@dash - { - \__tblr_get_hline_dash_style:N \l__tblr_b_tl - \xleaders \l__tblr_b_tl \hfil - } - { \l__tblr_b_tl \hfil } - \group_end: - } - -%% current cell alignments -\tl_new:N \g__tblr_cell_halign_tl -\tl_new:N \g__tblr_cell_valign_tl -\tl_new:N \g__tblr_cell_middle_tl - -\tl_const:Nn \c__tblr_valign_h_tl { h } -\tl_const:Nn \c__tblr_valign_m_tl { m } -\tl_const:Nn \c__tblr_valign_f_tl { f } -\tl_const:Nn \c__tblr_valign_t_tl { t } -\tl_const:Nn \c__tblr_valign_b_tl { b } - -\tl_const:Nn \c__tblr_middle_t_tl { t } -\tl_const:Nn \c__tblr_middle_m_tl { m } -\tl_const:Nn \c__tblr_middle_b_tl { b } - -%% #1: row number; #2: column number -\cs_new_protected:Npn \__tblr_get_cell_alignments:nn #1 #2 - { - \group_begin: - \tl_gset:Nx \g__tblr_cell_halign_tl - { \__tblr_data_item:neen { cell } {#1} {#2} { halign } } - \tl_set:Nx \l__tblr_v_tl - { \__tblr_data_item:neen { cell } {#1} {#2} { valign } } - \tl_case:NnF \l__tblr_v_tl - { - \c__tblr_valign_t_tl - { - \tl_gset:Nn \g__tblr_cell_valign_tl {m} - \tl_gset:Nn \g__tblr_cell_middle_tl {t} - } - \c__tblr_valign_m_tl - { - \tl_gset:Nn \g__tblr_cell_valign_tl {m} - \tl_gset:Nn \g__tblr_cell_middle_tl {m} - } - \c__tblr_valign_b_tl - { - \tl_gset:Nn \g__tblr_cell_valign_tl {m} - \tl_gset:Nn \g__tblr_cell_middle_tl {b} - } - } - { - \tl_gset_eq:NN \g__tblr_cell_valign_tl \l__tblr_v_tl - \tl_gclear:N \g__tblr_cell_middle_tl - } - \group_end: - } - -%% current cell dimensions -\dim_new:N \g__tblr_cell_wd_dim -\dim_new:N \g__tblr_cell_ht_dim -\dim_new:N \g__tblr_cell_head_dim -\dim_new:N \g__tblr_cell_foot_dim - -%% Calculate the width and height for every cell -\cs_new_protected:Npn \__tblr_calculate_cell_sizes: - { - %% You can use these two counters in cell text - \int_zero:N \c@rownum - \int_zero:N \c@colnum - \int_step_inline:nn { \c@rowcount } - { - \int_incr:N \c@rownum - \int_zero:N \c@colnum - \__tblr_update_rowsep_registers: - \tl_set:Nx \l__tblr_h_tl - { \__tblr_data_item:nen { row } { \int_use:N \c@rownum } { height } } - %% We didn't initialize row heights with -1pt - \dim_compare:nNnF { \l__tblr_h_tl } = { 0pt } - { - \__tblr_data_gput:nenV { row } { \int_use:N \c@rownum } - { @row-height } \l__tblr_h_tl - } - \int_step_inline:nn { \c@colcount } - { - \int_incr:N \c@colnum - \__tblr_update_colsep_registers: - \__tblr_measure_cell_update_sizes:nnNNNN - { \int_use:N \c@rownum } - { \int_use:N \c@colnum } - \g__tblr_cell_wd_dim - \g__tblr_cell_ht_dim - \g__tblr_cell_head_dim - \g__tblr_cell_foot_dim - } - } - \int_step_inline:nn { \c@colcount } - { - \tl_set:Nx \l__tblr_w_tl - { \__tblr_data_item:nen { column } {##1} { width } } - \dim_compare:nNnF { \l__tblr_w_tl } < { 0pt } - { - \__tblr_data_gput:nenV { column } {##1} { @col-width } \l__tblr_w_tl - } - } - } - -\cs_new_protected:Npn \__tblr_update_rowsep_registers: - { - \dim_set:Nn \abovesep - { \__tblr_data_item:nen { row } { \int_use:N \c@rownum } { abovesep } } - \dim_set:Nn \belowsep - { \__tblr_data_item:nen { row } { \int_use:N \c@rownum } { belowsep } } - } - -\cs_new_protected:Npn \__tblr_update_colsep_registers: - { - \dim_set:Nn \leftsep - { \__tblr_data_item:nen { column } { \int_use:N \c@colnum } { leftsep } } - \dim_set:Nn \rightsep - { \__tblr_data_item:nen { column } { \int_use:N \c@colnum } { rightsep } } - } - -%% Measure and update natural dimensions of the row/column/cell -%% #1: row number; #2 column number; #3: width dimension; -%% #4: total height dimension; #5: head dimension; #6: foot dimension -\cs_new_protected:Npn \__tblr_measure_cell_update_sizes:nnNNNN #1 #2 #3 #4 #5 #6 - { - \__tblr_get_cell_alignments:nn {#1} {#2} - \__tblr_save_counters:n { trial } - \hbox_set:Nn \l_tmpa_box { \__tblr_get_cell_text:nn {#1} {#2} } - \__tblr_restore_counters:n { trial } - \__tblr_update_cell_size:nnNNNN {#1} {#2} #3 #4 #5 #6 - \__tblr_update_row_size:nnNNN {#1} {#2} #4 #5 #6 - \__tblr_update_col_size:nN {#2} #3 - } - -%% #1: row number, #2: column number -\cs_new_protected:Npn \__tblr_get_cell_text:nn #1 #2 - { - \int_compare:nNnTF { \__tblr_data_item:neen { cell } {#1} {#2} { omit } } > {0} - { - \dim_gzero:N \g__tblr_cell_wd_dim - \dim_gzero:N \g__tblr_cell_ht_dim - \dim_gzero:N \g__tblr_cell_head_dim - \dim_gzero:N \g__tblr_cell_foot_dim - } - { \__tblr_get_cell_text_real:nn { #1 } { #2 } } - } - -\tl_new:N \l__tblr_cell_fg_tl -\tl_new:N \l__tblr_cell_cmd_tl -\tl_new:N \l__tblr_cell_mode_tl -\bool_new:N \l__tblr_cell_math_mode_bool -\tl_const:Nn \l__tblr_cell_math_style_tl { \relax } -\tl_const:Nn \l__tblr_cell_imath_style_tl { \textstyle } -\tl_const:Nn \l__tblr_cell_dmath_style_tl { \displaystyle } - -%% Get cell text, #1: row number, #2: column number -%% If the width of the cell is not set, split it with \\ and compute the width -%% Therefore we always get a vbox for any cell -\cs_new_protected:Npn \__tblr_get_cell_text_real:nn #1 #2 - { - \group_begin: - \tl_set:Nx \l__tblr_cell_cmd_tl - { \__tblr_data_item:neen { cell } {#1} {#2} { cmd } } - \tl_if_empty:NTF \l__tblr_cell_cmd_tl - { \tl_set:Nx \l__tblr_c_tl { \__tblr_spec_item:ne { text } {[#1][#2]} } } - { - \tl_set:Nx \l__tblr_c_tl { { \__tblr_spec_item:ne { text } {[#1][#2]} } } - \tl_put_left:NV \l__tblr_c_tl \l__tblr_cell_cmd_tl - } - \tl_set:Nx \l__tblr_cell_mode_tl - { \__tblr_data_item:neen { cell } {#1} {#2} { mode } } - \tl_if_empty:NT \l__tblr_cell_mode_tl - { - \bool_if:NTF \l__tblr_math_mode_bool - { \tl_set:Nn \l__tblr_cell_mode_tl { math } } - { \tl_set:Nn \l__tblr_cell_mode_tl { text } } - } - \tl_if_eq:NnTF \l__tblr_cell_mode_tl { text } - { \bool_set_false:N \l__tblr_cell_math_mode_bool } - { - \bool_set_true:N \l__tblr_cell_math_mode_bool - \tl_put_left:Nv \l__tblr_c_tl - { l__tblr_cell_ \l__tblr_cell_mode_tl _style_tl } - \tl_put_left:Nn \l__tblr_c_tl { $ } - \tl_put_right:Nn \l__tblr_c_tl { $ } - } - \tl_set:Nx \l__tblr_f_tl { \__tblr_data_item:neen { cell } {#1} {#2} { font } } - \tl_set:Nx \l__tblr_w_tl - { \__tblr_data_item:neen { cell } {#1} {#2} { width } } - \dim_compare:nNnT { \l__tblr_w_tl } < { 0pt } % cell width unset - { - \int_compare:nNnT - { \__tblr_data_item:neen { cell } {#1} {#2} { colspan } } < {2} - { - \tl_set:Nx \l__tblr_w_tl - { \__tblr_data_item:nen { column } {#2} { width } } - } - } - \dim_compare:nNnT { \l__tblr_w_tl } < { 0pt } % column width unset - { - \bool_if:NTF \l__tblr_cell_math_mode_bool - { - \hbox_set:Nn \l_tmpa_box { \l__tblr_c_tl } - \tl_set:Nx \l__tblr_w_tl { \box_wd:N \l_tmpa_box } - } - { - \__tblr_get_cell_size_with_box: - } - } - \tl_set:Nx \l__tblr_cell_fg_tl - { \__tblr_data_item:neen { cell } {#1} {#2} { foreground } } - \tl_put_left:NV \l__tblr_c_tl \l__tblr_f_tl - \__tblr_get_vcell_and_sizes:NN \l__tblr_c_tl \l__tblr_w_tl - \group_end: - } - -\cs_new_protected:Npn \__tblr_get_cell_size_with_box: - { - \__tblr_save_counters:n { cell } - \tl_if_eq:NnTF \l__tblr_inner_spec_measure_tl { vbox } - { \__tblr_get_cell_size_with_vbox: } - { \__tblr_get_cell_size_with_hbox: } - \__tblr_restore_counters:n { cell } - } - -%% Varwidth won't work as expected when \color command occurs in it, -%% and we can not fix this problem with \leavevmode command. -%% See https://tex.stackexchange.com/q/460489. -%% But we need to use \color command for fg option, -%% or users may use it in the middle of the cell text, -%% so we have redefine \color command and disable it before measuring cell. - -\NewDocumentCommand \__tblr_fake_color_command:w { o m } { } - -\cs_new_protected:Npn \__tblr_get_cell_size_with_vbox: - { - \hbox_set:Nn \l_tmpa_box - { - \cs_set_eq:NN \color \__tblr_fake_color_command:w - \begin{varwidth}{\paperwidth} - \l__tblr_f_tl - \__tblr_rescan_cell_tokens:N \l__tblr_c_tl - \end{varwidth} - } - \tl_set:Nx \l__tblr_w_tl { \box_wd:N \l_tmpa_box } - } - -\cs_new_protected:Npn \__tblr_get_cell_size_with_hbox: - { - \tl_set_eq:NN \l_tmpb_tl \l__tblr_c_tl - \__tblr_insert_braces:N \l_tmpb_tl - \seq_set_split:NnV \l_tmpa_seq { \\ } \l_tmpb_tl - \tl_set:Nn \l__tblr_w_tl { 0pt } - \seq_map_variable:NNn \l_tmpa_seq \l_tmpa_tl - { - \__tblr_remove_braces:N \l_tmpa_tl - \hbox_set:Nn \l_tmpa_box - { - \l__tblr_f_tl - \__tblr_rescan_cell_tokens:N \l_tmpa_tl - } - \tl_set:Nx \l__tblr_w_tl - { \dim_max:nn { \l__tblr_w_tl } { \box_wd:N \l_tmpa_box } } - } - } - -%% #1: cell text; #2: box width -\cs_new_protected:Npn \__tblr_get_vcell_and_sizes:NN #1 #2 - { - \group_begin: - \__tblr_save_counters:n { cell } - \vbox_set_top:Nn \l_tmpa_box { \__tblr_make_vcell_text:NN #1 #2 } - \__tblr_restore_counters:n { cell } - \vbox_set:Nn \l_tmpb_box { \__tblr_make_vcell_text:NN #1 #2 } - \dim_gset:Nn \g__tblr_cell_wd_dim { \box_wd:N \l_tmpb_box } - \dim_gset:Nn \g__tblr_cell_ht_dim - { \box_ht:N \l_tmpb_box + \box_dp:N \l_tmpb_box } - \dim_gset:Nn \g__tblr_cell_head_dim { \box_ht:N \l_tmpa_box } - \dim_gset:Nn \g__tblr_cell_foot_dim { \box_dp:N \l_tmpb_box } - \tl_case:Nn \g__tblr_cell_valign_tl - { - \c__tblr_valign_h_tl - { \box_use:N \l_tmpa_box } - \c__tblr_valign_m_tl - { - \tl_case:Nn \g__tblr_cell_middle_tl - { - \c__tblr_middle_t_tl - { \box_use:N \l_tmpa_box } - \c__tblr_middle_m_tl - { - \tl_set:Nx \l__tblr_b_tl - { - \dim_eval:n - { - ( \g__tblr_cell_ht_dim - \g__tblr_cell_head_dim - - \g__tblr_cell_foot_dim ) / 2 - } - } - \box_set_ht:Nn \l_tmpb_box - { \g__tblr_cell_head_dim + \l__tblr_b_tl } - \box_set_dp:Nn \l_tmpb_box - { \g__tblr_cell_foot_dim + \l__tblr_b_tl } - \box_use:N \l_tmpb_box - } - \c__tblr_middle_b_tl - { \box_use:N \l_tmpb_box } - } - } - \c__tblr_valign_f_tl - { \box_use:N \l_tmpb_box } - } - \group_end: - } - -%% #1: cell text; #2: box width -%% All halign commands are defined at the beginning of the file -\cs_new_protected:Npn \__tblr_make_vcell_text:NN #1 #2 - { - \dim_set:Nn \tex_hsize:D { #2 } - \@arrayparboxrestore - \cs:w __tblr_halign_command_ \g__tblr_cell_halign_tl : \cs_end: - \mode_leave_vertical: - \box_use:N \l__tblr_strut_ht_box - \tl_if_empty:NF \l__tblr_cell_fg_tl { \exp_args:NV \color \l__tblr_cell_fg_tl } - \bool_if:NTF \l__tblr_cell_math_mode_bool - { #1 } - { \__tblr_rescan_cell_tokens:N #1 } - \box_use:N \l__tblr_strut_dp_box - } - -%% When using verb option, there is an end-of-line character at the end. -%% This character causes extra horizontal space at the end when "measure=hbox", -%% or causes extra vertical space at the end with "measure=vbox". -%% Therefore we have to use an \empty to remove it. -%% See https://tex.stackexchange.com/q/213659 -\cs_new_protected:Npn \__tblr_rescan_cell_tokens:N #1 - { - \tl_if_empty:NTF \l__tblr_inner_spec_verb_tl - { #1 } - { - %% insert space characters after some control sequences first (issue #112) - \regex_replace_all:nnN { (\c{[A-Za-z]*}) ([A-Za-z]) } { \1 \ \2 } #1 - \regex_replace_all:nnN { . } { \c{string} \0 } #1 - \tl_set:Nx #1 { #1 \noexpand \empty } - \exp_args:NV \tex_scantokens:D #1 - } - } - -%% #1: total height dimension; #2: head dimension; #3: foot dimension; -%% #4: tl for resulting upper size; #5: tl for resulting lower size - -\tl_new:N \l__tblr_middle_body_tl - -\cs_new_protected:Npn \__tblr_get_middle_cell_upper_lower:NNNNN #1 #2 #3 #4 #5 - { - \tl_case:Nn \g__tblr_cell_middle_tl - { - \c__tblr_middle_t_tl - { - \tl_set:Nx #4 { \dim_use:N #2 } - \tl_set:Nx #5 { \dim_eval:n { #1 - #2 } } - } - \c__tblr_middle_m_tl - { - \tl_set:Nx \l__tblr_middle_body_tl { \dim_eval:n { #1 - #2 - #3 } } - \tl_set:Nx #4 { \dim_eval:n { #2 + \l__tblr_middle_body_tl / 2 } } - \tl_set:Nx #5 { \dim_eval:n { #3 + \l__tblr_middle_body_tl / 2 } } - } - \c__tblr_middle_b_tl - { - \tl_set:Nx #4 { \dim_eval:n { #1 - #3 } } - \tl_set:Nx #5 { \dim_use:N #3 } - } - } - } - -%% Update natural dimensions of the cell -%% #1: row number; #2 column number; #3: width dimension; -%% #4: total height dimension; #5: head dimension; #6: foot dimension -\cs_new_protected:Npn \__tblr_update_cell_size:nnNNNN #1 #2 #3 #4 #5 #6 - { - \group_begin: - \tl_set:Nx \l__tblr_c_tl - { \__tblr_data_item:neen { cell } {#1} {#2} { colspan } } - \int_compare:nNnT { \l__tblr_c_tl } > {1} - { - \__tblr_data_gput:neene { cell } {#1} {#2} { @cell-width } {\dim_use:N #3} - \dim_gzero:N #3 % don't affect column width - } - \tl_set:Nx \l__tblr_r_tl - { \__tblr_data_item:neen { cell } {#1} {#2} { rowspan } } - \int_compare:nNnT { \l__tblr_r_tl } > {1} - { - \tl_case:Nn \g__tblr_cell_valign_tl - { - \c__tblr_valign_h_tl - { - \tl_set:Nx \l__tblr_u_tl { \dim_use:N #5 } - \tl_set:Nx \l__tblr_v_tl { \dim_eval:n { #4 - #5 } } - %% Update the head size of the first span row here - \__tblr_data_gput_if_larger:nene - { row } {#1} { @row-head } { \dim_use:N #5 } - } - \c__tblr_valign_f_tl - { - \tl_set:Nx \l__tblr_u_tl { \dim_eval:n { #4 - #6 } } - \tl_set:Nx \l__tblr_v_tl { \dim_use:N #6 } - %% Update the foot size of the last span row here - \__tblr_data_gput_if_larger:nene - { row } - { \int_eval:n { #1 + \l__tblr_r_tl - 1 } } - { @row-foot } - { \dim_use:N #6 } - } - \c__tblr_valign_m_tl - { - \__tblr_get_middle_cell_upper_lower:NNNNN - #4 #5 #6 \l__tblr_u_tl \l__tblr_v_tl - } - } - \__tblr_data_gput:neenV { cell } {#1} {#2} { @cell-height } \l__tblr_u_tl - \__tblr_data_gput:neenV { cell } {#1} {#2} { @cell-depth } \l__tblr_v_tl - %% Don't affect row sizes - \dim_gzero:N #4 - \dim_gzero:N #5 - \dim_gzero:N #6 - } - \group_end: - } - - -%% Update size of the row. #1: row number; #2: column number; -%% #3: total height dimension; #4: head dimension; #5: foot dimension -\cs_new_protected:Npn \__tblr_update_row_size:nnNNN #1 #2 #3 #4 #5 - { - \group_begin: - %% Note that \l__tblr_h_tl may be empty - \tl_set:Nx \l__tblr_h_tl - { \__tblr_data_item:nen { row } {#1} { @row-height } } - \tl_if_eq:NNTF \g__tblr_cell_valign_tl \c__tblr_valign_m_tl - { - \tl_set:Nx \l__tblr_a_tl - { \__tblr_data_item:nen { row } {#1} { @row-upper } } - \tl_set:Nx \l__tblr_b_tl - { \__tblr_data_item:nen { row } {#1} { @row-lower } } - \__tblr_get_middle_cell_upper_lower:NNNNN - #3 #4 #5 \l__tblr_u_tl \l__tblr_v_tl - \dim_compare:nNnT { \l__tblr_u_tl } > { \l__tblr_a_tl } - { - \tl_set_eq:NN \l__tblr_a_tl \l__tblr_u_tl - \__tblr_data_gput:nenV { row } {#1} { @row-upper } \l__tblr_a_tl - } - \dim_compare:nNnT { \l__tblr_v_tl } > { \l__tblr_b_tl } - { - \tl_set_eq:NN \l__tblr_b_tl \l__tblr_v_tl - \__tblr_data_gput:nenV { row } {#1} { @row-lower } \l__tblr_b_tl - } - \dim_compare:nNnT - { \l__tblr_a_tl + \l__tblr_b_tl } > { \l__tblr_h_tl + 0pt } - { - \__tblr_data_gput:nene { row } {#1} { @row-height } - { \dim_eval:n { \l__tblr_a_tl + \l__tblr_b_tl } } - } - } - { - \tl_set:Nx \l__tblr_e_tl - { \__tblr_data_item:nen { row } {#1} { @row-head } } - \tl_set:Nx \l__tblr_f_tl - { \__tblr_data_item:nen { row } {#1} { @row-foot } } - \dim_compare:nNnT {#4} > {\l__tblr_e_tl} - { - \__tblr_data_gput:nene { row } {#1} { @row-head } { \dim_use:N #4 } - } - \dim_compare:nNnT {#5} > {\l__tblr_f_tl} - { - \__tblr_data_gput:nene { row } {#1} { @row-foot } { \dim_use:N #5 } - } - \tl_set:Nx \l__tblr_x_tl { \dim_max:nn {#4} { \l__tblr_e_tl } } - \tl_set:Nx \l__tblr_y_tl { \dim_max:nn {#5} { \l__tblr_f_tl } } - \dim_compare:nNnT - { #3 - #4 - #5 } > { \l__tblr_h_tl - \l__tblr_x_tl - \l__tblr_y_tl } - { - \__tblr_data_gput:nene { row } {#1} { @row-height } - { - \dim_eval:n - { - \l__tblr_x_tl - + \dim_use:N #3 - \dim_use:N #4 - \dim_use:N #5 - + \l__tblr_y_tl - } - } - } - } - \group_end: - } - - -%% Update size of the column. #1: column number; #2: width dimension - -\cs_new_protected:Npn \__tblr_update_col_size:nN #1 #2 - { - \tl_set:Nx \l_tmpb_tl - { \__tblr_data_item:nen { column } {#1} { @col-width } } - \bool_lazy_or:nnT - { \tl_if_empty_p:N \l_tmpb_tl } - { \dim_compare_p:nNn { \dim_use:N #2 } > { \l_tmpb_tl } } - { - \__tblr_data_gput:nene { column } {#1} { @col-width } { \dim_use:N #2 } - } - } - -%%% -------------------------------------------------------- -%% \section{Calculate and Adjust Extendable Columns} -%%% -------------------------------------------------------- - -%% Compute column widths when there are some extendable columns - -\dim_new:N \l__column_target_dim -\prop_new:N \l__column_coefficient_prop -\prop_new:N \l__column_natural_width_prop -\prop_new:N \l__column_computed_width_prop - -\msg_new:nnn { tabularray } { table-width-too-small } - { Table ~ width ~ is ~ too ~ small, ~ need ~ #1 ~ more! } - -\cs_new_protected:Npn \__tblr_compute_extendable_column_width: - { - \__tblr_collect_extendable_column_width: - \dim_compare:nNnTF { \l__column_target_dim } < { 0pt } - { - \msg_warning:nnx { tabularray } { table-width-too-small } - { \dim_abs:n { \l__column_target_dim } } - } - { - \prop_if_empty:NF \l__column_coefficient_prop - { \__tblr_adjust_extendable_column_width: } - } - } - -\cs_new_protected:Npn \__tblr_collect_extendable_column_width: - { - \tl_set:Nx \l_tmpa_tl { \__tblr_prop_item:nn { inner } { width } } - \tl_if_empty:NTF \l_tmpa_tl - { \dim_set_eq:NN \l__column_target_dim \linewidth } - { \dim_set:Nn \l__column_target_dim { \l_tmpa_tl } } - \prop_clear:N \l__column_coefficient_prop - \prop_clear:N \l__column_natural_width_prop - \prop_clear:N \l__column_computed_width_prop - \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl - { - \tl_set:Nx \l__tblr_a_tl - { \__tblr_data_item:nen { column } { \l__tblr_j_tl } { width } } - \tl_set:Nx \l__tblr_b_tl - { \__tblr_data_item:nen { column } { \l__tblr_j_tl } { coefficient } } - \tl_set:Nx \l__tblr_c_tl - { \__tblr_data_item:nen { column } { \l__tblr_j_tl } { @col-width } } - \dim_compare:nNnTF { \l__tblr_a_tl } < { 0pt } % column width unset - { - \dim_compare:nNnTF { \l__tblr_b_tl pt } = { 0pt } - { \dim_sub:Nn \l__column_target_dim { \l__tblr_c_tl } } - { - \prop_put:Nxx \l__column_coefficient_prop - { \l__tblr_j_tl } { \l__tblr_b_tl } - \prop_put:Nxn \l__column_computed_width_prop - { \l__tblr_j_tl } { 0pt } - \dim_compare:nNnF { \l__tblr_b_tl pt } > { 0pt } - { - \prop_put:Nxx \l__column_natural_width_prop - { \l__tblr_j_tl } { \l__tblr_c_tl } - } - } - } - { \dim_sub:Nn \l__column_target_dim { \l__tblr_a_tl } } - \tl_set:Nx \l__tblr_a_tl - { \__tblr_spec_item:ne { vline } { [\l__tblr_j_tl] / @vline-width } } - \tl_set:Nx \l__tblr_b_tl - { \__tblr_data_item:nen { column } { \l__tblr_j_tl } { leftsep } } - \tl_set:Nx \l__tblr_c_tl - { \__tblr_data_item:nen { column } { \l__tblr_j_tl } { rightsep } } - \dim_set:Nn \l__column_target_dim - { \l__column_target_dim - \l__tblr_a_tl - \l__tblr_b_tl - \l__tblr_c_tl } - } - \tl_set:Nx \l__tblr_a_tl - { - \__tblr_spec_item:ne { vline } - { [\int_eval:n {\c@colcount + 1}] / @vline-width } - } - \tl_if_empty:NF \l__tblr_a_tl - { \dim_sub:Nn \l__column_target_dim { \l__tblr_a_tl } } - \LogTblrTracing { target } - } - -%% If all columns have negative coefficients and small natural widths, -%% \l__column_coefficient_prop will be empty after one or more rounds. -%% We reset @row-height, etc for \linewidth graphics in X columns (issue #80) -\cs_new_protected:Npn \__tblr_adjust_extendable_column_width: - { - \bool_while_do:nn - { \dim_compare_p:nNn { \l__column_target_dim } > { \hfuzz } } - { - \prop_if_empty:NTF \l__column_coefficient_prop - { \__tblr_adjust_extendable_column_width_negative: } - { \__tblr_adjust_extendable_column_width_once: } - } - \prop_map_inline:Nn \l__column_computed_width_prop - { - \__tblr_data_gput:nnne { column } {##1} { width } {##2} - \__tblr_data_gput:nnnn { column } {##1} { @col-width } { 0pt } - } - \int_step_inline:nn { \c@rowcount } - { - \__tblr_data_gput:nnnn { row } {##1} { @row-height } { 0pt } - \__tblr_data_gput:nnnn { row } {##1} { @row-head } { 0pt } - \__tblr_data_gput:nnnn { row } {##1} { @row-foot } { 0pt } - \__tblr_data_gput:nnnn { row } {##1} { @row-upper } { 0pt } - \__tblr_data_gput:nnnn { row } {##1} { @row-lower } { 0pt } - } - \__tblr_calculate_cell_sizes: - } - -%% We use dimen register, since the coefficient may be a decimal number -\cs_new_protected:Npn \__tblr_adjust_extendable_column_width_once: - { - \dim_zero:N \l_tmpa_dim - \prop_map_inline:Nn \l__column_coefficient_prop - { - \dim_add:Nn \l_tmpa_dim { \dim_abs:n { ##2 pt } } - } - \tl_set:Nx \l__tblr_w_tl - { \dim_ratio:nn { \l__column_target_dim } { \l_tmpa_dim } } - \dim_zero:N \l__column_target_dim - \prop_map_inline:Nn \l__column_coefficient_prop - { - \tl_set:Nx \l__tblr_a_tl - { \dim_eval:n { \dim_abs:n { ##2 pt } * \l__tblr_w_tl } } - \dim_compare:nNnTF { ##2 pt } > { 0pt } - { - \__tblr_add_dimen_value:Nnn - \l__column_computed_width_prop { ##1 } { \l__tblr_a_tl } - } - { - \tl_set:Nx \l__tblr_b_tl - { \prop_item:Nn \l__column_natural_width_prop { ##1 } } - \tl_set:Nx \l__tblr_c_tl - { \prop_item:Nn \l__column_computed_width_prop { ##1 } } - \dim_compare:nNnTF { \l__tblr_a_tl + \l__tblr_c_tl } > { \l__tblr_b_tl } - { - \prop_put:Nnx \l__column_computed_width_prop - { ##1 } { \l__tblr_b_tl } - \dim_add:Nn \l__column_target_dim - { \l__tblr_a_tl + \l__tblr_c_tl - \l__tblr_b_tl } - \prop_remove:Nn \l__column_coefficient_prop { ##1 } - } - { - \__tblr_add_dimen_value:Nnn - \l__column_computed_width_prop { ##1 } { \l__tblr_a_tl } - } - } - } - \LogTblrTracing { target } - } - -\cs_new_protected:Npn \__tblr_adjust_extendable_column_width_negative: - { - \dim_zero:N \l_tmpa_dim - \prop_map_inline:Nn \l__column_natural_width_prop - { \dim_add:Nn \l_tmpa_dim { ##2 } } - \tl_set:Nx \l_tmpa_tl - { \dim_ratio:nn { \l__column_target_dim } { \l_tmpa_dim } } - \dim_zero:N \l__column_target_dim - \prop_map_inline:Nn \l__column_natural_width_prop - { - \tl_set:Nx \l_tmpb_tl { \dim_eval:n { ##2 * \l_tmpa_tl } } - \__tblr_add_dimen_value:Nnn - \l__column_computed_width_prop { ##1 } { \l_tmpb_tl } - } - \LogTblrTracing { target } - } - -%%% -------------------------------------------------------- -%% \section{Calculate and Adjust Multispan Cells} -%%% -------------------------------------------------------- - -%% Compute and adjust widths when there are some span cells. -%% By default, we will compute column widths from span widths; -%% but if we set table option "hspan = minimal", -%% we will compute span widths from column widths. - -\cs_new_protected:Npn \__tblr_adjust_sizes_for_span_cells: - { - \__tblr_prop_if_in:nnT { inner } { colspan } - { - \__tblr_collect_column_widths_skips: - \str_if_eq:xnTF - { \__tblr_prop_item:ne { inner } { hspan } } { minimal } - { - \__tblr_set_span_widths_from_column_widths: - } - { - \__tblr_collect_span_widths: - \__tblr_set_column_widths_from_span_widths: - } - \LogTblrTracing { column } - \__tblr_calculate_cell_sizes: - } - \__tblr_prop_if_in:nnT { inner } { rowspan } - { - \__tblr_collect_row_heights_skips: - \__tblr_collect_span_heights: - \__tblr_set_row_heights_from_span_heights: - \LogTblrTracing { row } - } - } - -\prop_new:N \l__tblr_col_item_skip_size_prop -\prop_new:N \l__tblr_col_span_size_prop -\prop_new:N \l__tblr_row_item_skip_size_prop -\prop_new:N \l__tblr_row_span_size_prop - -\cs_new_protected:Npn \__tblr_collect_column_widths_skips: - { - \prop_clear:N \l__tblr_col_item_skip_size_prop - \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl - { - \int_compare:nNnTF { \l__tblr_j_tl } > { 1 } - { - \prop_put:Nxx \l__tblr_col_item_skip_size_prop { skip[\l__tblr_j_tl] } - { - \dim_eval:n - { - \__tblr_data_item:nen { column } - { \int_eval:n { \l__tblr_j_tl - 1 } } { rightsep } - + - \__tblr_spec_item:ne { vline } - { [\l__tblr_j_tl] / @vline-width } - + - \__tblr_data_item:nen { column } { \l__tblr_j_tl } { leftsep } - } - } - } - { - \prop_put:Nxn \l__tblr_col_item_skip_size_prop { skip[\l__tblr_j_tl] } - { 0pt } - } - \prop_put:Nxx \l__tblr_col_item_skip_size_prop { item[\l__tblr_j_tl] } - { \__tblr_data_item:nen { column } { \l__tblr_j_tl } { @col-width } } - } - \__tblr_do_if_tracing:nn { cellspan } - { \prop_log:N \l__tblr_col_item_skip_size_prop } - } - -\cs_new_protected:Npn \__tblr_collect_row_heights_skips: - { - \prop_clear:N \l__tblr_row_item_skip_size_prop - \int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl - { - \int_compare:nNnTF { \l__tblr_i_tl } > { 1 } - { - \prop_put:Nxx \l__tblr_row_item_skip_size_prop { skip[\l__tblr_i_tl] } - { - \dim_eval:n - { - \__tblr_data_item:nen { row } - { \int_eval:n {\l__tblr_i_tl - 1} } { belowsep } - + - \__tblr_spec_item:ne { hline } - { [\l__tblr_i_tl] / @hline-height } - + - \__tblr_data_item:nen { row } { \l__tblr_i_tl } { abovesep } - } - } - } - { - \prop_put:Nxn \l__tblr_row_item_skip_size_prop { skip[\l__tblr_i_tl] } - { 0pt } - } - \__tblr_collect_one_row_height:NN \l__tblr_i_tl \l__tblr_h_tl - \prop_put:Nxx \l__tblr_row_item_skip_size_prop - { item[\l__tblr_i_tl] } { \l__tblr_h_tl } - } - \__tblr_do_if_tracing:nn { cellspan } - { \prop_log:N \l__tblr_row_item_skip_size_prop } - } - -%% #1: row number; #2: tl with result -\cs_new_protected:Npn \__tblr_collect_one_row_height:NN #1 #2 - { - \tl_set:Nx #2 { \__tblr_data_item:nen { row } {#1} { @row-height } } - } - -\cs_new_protected:Npn \__tblr_collect_span_widths: - { - \prop_clear:N \l__tblr_col_span_size_prop - \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl - { - \int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl - { - \tl_set:Nx \l__tblr_a_tl - { - \__tblr_data_item:neen { cell } - { \l__tblr_i_tl } { \l__tblr_j_tl } { colspan } - } - \int_compare:nNnT { \l__tblr_a_tl } > {1} - { - \__tblr_put_if_larger:Nxx \l__tblr_col_span_size_prop - { - ( \l__tblr_j_tl - - \int_eval:n {\l__tblr_j_tl + \l__tblr_a_tl - 1} ) - } - { - \__tblr_data_item:neen { cell } - { \l__tblr_i_tl } { \l__tblr_j_tl } { @cell-width } - } - } - } - } - \__tblr_do_if_tracing:nn { cellspan } - { \prop_log:N \l__tblr_col_span_size_prop } - } - -\prop_new:N \l__tblr_row_span_to_row_prop - -\cs_new_protected:Npn \__tblr_collect_span_heights: - { - \prop_clear:N \l__tblr_row_span_to_row_prop - \prop_clear:N \l__tblr_row_span_size_prop - \int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl - { - \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl - { - \tl_set:Nx \l__tblr_a_tl - { - \__tblr_data_item:neen { cell } - { \l__tblr_i_tl } { \l__tblr_j_tl } { rowspan } - } - \int_compare:nNnT { \l__tblr_a_tl } > {1} - { - \tl_set:Nx \l__tblr_v_tl - { - \__tblr_data_item:neen { cell } - { \l__tblr_i_tl } { \l__tblr_j_tl } { valign } - } - \tl_if_eq:NnT \l__tblr_v_tl { h } - { - \tl_set:Nx \l__tblr_h_tl - { - \__tblr_data_item:nen { row } - { \l__tblr_i_tl } { @row-head } - } - \__tblr_data_gput:neenV { cell } - { \l__tblr_i_tl } { \l__tblr_j_tl } { @cell-height } - \l__tblr_h_tl - } - \tl_if_eq:NnT \l__tblr_v_tl { f } - { - \tl_set:Nx \l__tblr_d_tl - { - \__tblr_data_item:nen - { row } - { \int_eval:n { \l__tblr_i_tl + \l__tblr_a_tl - 1 } } - { @row-foot } - } - \__tblr_data_gput:neenV { cell } - { \l__tblr_i_tl } { \l__tblr_j_tl } { @cell-depth } - \l__tblr_d_tl - } - \__tblr_put_if_larger:Nxx \l__tblr_row_span_size_prop - { - ( \l__tblr_i_tl - - \int_eval:n {\l__tblr_i_tl + \l__tblr_a_tl - 1} ) - } - { - \dim_eval:n - { - \__tblr_data_item:neen { cell } - { \l__tblr_i_tl } { \l__tblr_j_tl } { @cell-height } - + - \__tblr_data_item:neen { cell } - { \l__tblr_i_tl } { \l__tblr_j_tl } { @cell-depth } - } - } - \prop_put:Nxx \l__tblr_row_span_to_row_prop - { [\l__tblr_i_tl][\l__tblr_j_tl] } - { \int_eval:n {\l__tblr_i_tl + \l__tblr_a_tl - 1} } - } - } - } - \__tblr_do_if_tracing:nn { cellspan } - { - \prop_log:N \l__tblr_row_span_to_row_prop - \prop_log:N \l__tblr_row_span_size_prop - } - } - -%% Compute and set column widths from span widths -\cs_new_protected:Npn \__tblr_set_column_widths_from_span_widths: - { - \str_if_eq:xnTF - { \__tblr_prop_item:ne { inner } { hspan } } - { even } - { - \__tblr_distribute_span_sizes_even:xNN - { \int_use:N \c@colcount } - \l__tblr_col_item_skip_size_prop - \l__tblr_col_span_size_prop - } - { - \__tblr_distribute_span_sizes_default:xNN - { \int_use:N \c@colcount } - \l__tblr_col_item_skip_size_prop - \l__tblr_col_span_size_prop - } - \__tblr_set_all_column_widths: - } - -%% Compute and set row heights from span heights -\cs_new_protected:Npn \__tblr_set_row_heights_from_span_heights: - { - \str_if_eq:xnTF - { \__tblr_prop_item:ne { inner } { vspan } } - { even } - { - \__tblr_distribute_span_sizes_even:nNN - { \int_use:N \c@rowcount } - \l__tblr_row_item_skip_size_prop - \l__tblr_row_span_size_prop - } - { - \__tblr_distribute_span_sizes_default:xNN - { \int_use:N \c@rowcount } - \l__tblr_row_item_skip_size_prop - \l__tblr_row_span_size_prop - } - \__tblr_set_all_row_heights: - } - -%% See page 245 in Chapter 22 of TeXbook -%% #1: total number of items -%% #2: prop list with item sizes and skip sizes; #3: prop list with span sizes -\cs_new_protected:Npn \__tblr_distribute_span_sizes_default:nNN #1 #2 #3 - { - \int_step_variable:nNn { #1 } \l__tblr_j_tl - { - \dim_set:Nn \l__tblr_w_dim - { - \prop_item:Ne #2 { item[\l__tblr_j_tl] } - } - \int_step_variable:nNn { \l__tblr_j_tl - 1 } \l__tblr_i_tl - { - \tl_set:Nx \l__tblr_a_tl - { \prop_item:Ne #3 { (\l__tblr_i_tl-\l__tblr_j_tl) } } - \tl_if_empty:NF \l__tblr_a_tl - { - \int_step_variable:nnNn - { \l__tblr_i_tl } { \l__tblr_j_tl - 1 } \l__tblr_k_tl - { - \__tblr_do_if_tracing:nn { cellspan } - { - \tl_log:x - { \l__tblr_j_tl : \l__tblr_i_tl -> \l__tblr_k_tl } - } - \tl_set:Nx \l_tmpa_tl - { - \prop_item:Ne #2 { itemskip[\l__tblr_k_tl] } - } - \tl_set:Nx \l__tblr_a_tl - { \dim_eval:n { \l__tblr_a_tl - \l_tmpa_tl } } - } - \dim_compare:nNnT { \l__tblr_a_tl } > { \l__tblr_w_dim } - { - \dim_set:Nn \l__tblr_w_dim { \l__tblr_a_tl } - } - } - } - \prop_put:Nxx #2 - { item[\l__tblr_j_tl] } { \dim_use:N \l__tblr_w_dim } - \int_compare:nNnT { \l__tblr_j_tl } < { #1 } - { - \tl_set:Nx \l_tmpb_tl - { - \prop_item:Ne #2 - { skip[\int_eval:n { \l__tblr_j_tl + 1} ] } - } - \dim_add:Nn \l__tblr_w_dim { \l_tmpb_tl } - \prop_put:Nxx #2 - { itemskip[\l__tblr_j_tl] } { \dim_use:N \l__tblr_w_dim } - } - } - \__tblr_do_if_tracing:nn { cellspan } { \prop_log:N #2 } - } -\cs_generate_variant:Nn \__tblr_distribute_span_sizes_default:nNN { x } - -%% #1: total number of items -%% #2: prop list with item sizes and skip sizes; #3: prop list with span sizes -\cs_new_protected:Npn \__tblr_distribute_span_sizes_even:nNN #1 #2 #3 - { - \prop_clear:N \l_tmpa_prop - \prop_map_inline:Nn #3 - { - \__tblr_get_span_from_to:w ##1 - \dim_set:Nn \l_tmpa_dim {##2} - \dim_sub:Nn \l_tmpa_dim { \prop_item:Ne #2 { item[\l__tblr_a_tl] } } - \int_step_inline:nnn { \l__tblr_a_tl + 1 } { \l__tblr_b_tl } - { - \dim_sub:Nn \l_tmpa_dim - { - \prop_item:Ne #2 { skip[####1] } + \prop_item:Nn #2 { item[####1] } - } - } - \__tblr_do_if_tracing:nn { cellspan } - { - \tl_log:x { \l__tblr_a_tl -> \l__tblr_b_tl : ~ \dim_use:N \l_tmpa_dim } - } - \dim_compare:nNnT {\l_tmpa_dim} > {0pt} - { - \tl_set:Nx \l_tmpa_tl - { \dim_eval:n { \l_tmpa_dim / (\l__tblr_b_tl - \l__tblr_a_tl + 1) } } - \int_step_inline:nnn { \l__tblr_a_tl } { \l__tblr_b_tl } - { - \__tblr_put_if_larger:NnV \l_tmpa_prop {####1} \l_tmpa_tl - } - } - } - \__tblr_do_if_tracing:nn { cellspan } { \prop_log:N \l_tmpa_prop } - \prop_map_inline:Nn \l_tmpa_prop - { - \__tblr_add_dimen_value:Nnn #2 {item[##1]} {##2} - } - \__tblr_do_if_tracing:nn { cellspan } { \prop_log:N #2 } - } -\cs_generate_variant:Nn \__tblr_distribute_span_sizes_even:nNN { x } - -\cs_new_protected:Npn \__tblr_get_span_from_to:w (#1-#2) - { - \tl_set:Nn \l__tblr_a_tl {#1} - \tl_set:Nn \l__tblr_b_tl {#2} - } - -\cs_new_protected:Npn \__tblr_set_all_column_widths: - { - \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl - { - \__tblr_data_gput:nene { column } - { \l__tblr_j_tl } { width } - { \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[\l__tblr_j_tl] } } - } - } - -\cs_new_protected:Npn \__tblr_set_all_row_heights: - { - \int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl - { - \tl_set:Nx \l__tblr_h_tl - { - \__tblr_data_item:nen { row } { \l__tblr_i_tl } { @row-head } - } - \tl_set:Nx \l__tblr_d_tl - { - \__tblr_data_item:nen { row } { \l__tblr_i_tl } { @row-foot } - } - \tl_set:Nx \l__tblr_a_tl - { - \prop_item:Ne \l__tblr_row_item_skip_size_prop { item[\l__tblr_i_tl] } - } - \__tblr_collect_one_row_height:NN \l__tblr_i_tl \l__tblr_t_tl - \__tblr_data_gput:nene { row } - { \l__tblr_i_tl } { @row-height } { \l__tblr_a_tl } - } - } - -%% Compute and set span widths from column widths -\cs_new_protected:Npn \__tblr_set_span_widths_from_column_widths: - { - \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl - { - \int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl - { - \tl_set:Nx \l__tblr_a_tl - { - \__tblr_data_item:neen { cell } - { \l__tblr_i_tl } { \l__tblr_j_tl } { colspan } - } - \int_compare:nNnT { \l__tblr_a_tl } > {1} - { - \__tblr_calc_span_widths:xxN - { \l__tblr_j_tl } - { \int_eval:n { \l__tblr_j_tl + \l__tblr_a_tl - 1 } } - \l__tblr_w_dim - \__tblr_data_gput:neene { cell } - { \l__tblr_i_tl } { \l__tblr_j_tl } { width } - { \dim_use:N \l__tblr_w_dim } - } - } - } - } - -%% Cell is spanned from col #1 to col #2, #3 is the return dim -\cs_new_protected:Npn \__tblr_calc_span_widths:nnN #1 #2 #3 - { - \dim_set:Nn #3 { \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[#1] } } - \int_step_inline:nnn { #1 + 1 } { #2 } - { - \tl_set:Nx \l_tmpa_tl - { \prop_item:Ne \l__tblr_col_item_skip_size_prop { skip[##1] } } - \tl_set:Nx \l_tmpb_tl - { \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[##1] } } - \dim_add:Nn #3 { \dim_eval:n { \l_tmpa_tl + \l_tmpb_tl } } - } - } -\cs_generate_variant:Nn \__tblr_calc_span_widths:nnN { xxN } - -%%% -------------------------------------------------------- -%%> \section{Header and Footer Styles} -%%% -------------------------------------------------------- - -\prop_new:N \l__tblr_element_styles_prop - -\cs_new_protected:Npn \__tblr_style_put:nn #1 #2 - { - \prop_put:Nnn \l__tblr_element_styles_prop {#1} {#2} - } -\cs_generate_variant:Nn \__tblr_style_put:nn { nV, ne, en } - -\cs_new:Npn \__tblr_style_item:n #1 - { - \prop_item:Nn \l__tblr_element_styles_prop {#1} - } - -\cs_new_protected:Npn \__tblr_style_log: - { - \prop_log:N \l__tblr_element_styles_prop - } - -\tl_new:N \l__tblr_element_name_tl -\tl_new:N \l__tblr_element_styles_tl - -%% #1: list of element names; #2: element styles -\NewDocumentCommand \SetTblrStyle { m +m } - { - \tl_set:Nn \l__tblr_element_styles_tl {#2} - \keys_set:nn { tblr-element } {#1} - \ignorespaces - } - -\keys_define:nn { tblr-element } - { - head .meta:n = { firsthead, middlehead, lasthead }, - foot .meta:n = { firstfoot, middlefoot, lastfoot }, - unknown .code:n = \__tblr_set_element_styles:V \l_keys_key_str, - } - -\cs_new_protected:Npn \__tblr_set_element_styles:n #1 - { - \tl_set:Nn \l__tblr_element_name_tl {#1} - \keys_set:nV { tblr-style } \l__tblr_element_styles_tl - } -\cs_generate_variant:Nn \__tblr_set_element_styles:n { V } - -\keys_define:nn { tblr-style } - { - halign .code:n = \__tblr_element_gput_style:nn { halign } {#1}, - l .meta:n = { halign = l }, - c .meta:n = { halign = c }, - r .meta:n = { halign = r }, - fg .code:n = \__tblr_element_gput_style:nn { fg } {#1}, - font .code:n = \__tblr_element_gput_style:nn { font } {#1}, - hang .code:n = \__tblr_element_gput_style:nn { hang } {#1}, - indent .code:n = \__tblr_element_gput_style:nn { indent } {#1}, - unknown .code:n = \__tblr_element_unknown_key:Vn \l_keys_key_str {#1}, - } - -\cs_new_protected:Npn \__tblr_element_gput_style:nn #1 #2 - { - \__tblr_style_put:en { \l__tblr_element_name_tl / #1 } {#2} - } - -\cs_new_protected:Npn \__tblr_element_unknown_key:nn #1 #2 - { - \regex_match:NnTF \c__tblr_is_color_key_regex {#1} - { \__tblr_style_put:en { \l__tblr_element_name_tl / fg } {#1} } - { - %% unknown key name has been changed to string in \l_keys_key_str - \tl_set_rescan:Nnn \l__tblr_f_tl {} {#1} - \tl_if_head_eq_catcode:VNTF \l__tblr_f_tl \scan_stop: - { - \__tblr_style_put:en { \l__tblr_element_name_tl / font } \l__tblr_f_tl - } - { - \__tblr_style_put:en { \l__tblr_element_name_tl / #1 } {#2} - } - } - } -\cs_generate_variant:Nn \__tblr_element_unknown_key:nn { Vn } - -%%% -------------------------------------------------------- -%%> \section{Helper Functions for Templates} -%%% -------------------------------------------------------- - -\tl_new:N \l__tblr_template_name_tl -\tl_new:N \l__tblr_template_code_tl - -\keys_define:nn { tblr-def-template } - { - unknown .code:n = \__tblr_def_template:V \l_keys_key_str, - } - -%% #1: head/foot element; #2: template name; #3: template code -%% If the template name = default, we enable the template at once -%% Otherwise, we may enable the template by using \SetTblrTemplate command -\NewDocumentCommand \DefTblrTemplate { m m +m } - { - \tl_set:Nn \l__tblr_template_name_tl {#2} - \tl_set:Nn \l__tblr_template_code_tl {#3} - \keys_set:nn { tblr-def-template } {#1} - \ignorespaces - } - -\cs_new_protected:Npn \__tblr_def_template:n #1 - { - \tl_set_eq:cN { l__tblr_template_ #1 _ \l__tblr_template_name_tl _tl } - \l__tblr_template_code_tl - } -\cs_generate_variant:Nn \__tblr_def_template:n { V } - -\keys_define:nn { tblr-set-template } - { - unknown .code:n = \__tblr_set_template:V \l_keys_key_str, - } - -%% #1: head/foot element; #2: template name -\NewDocumentCommand \SetTblrTemplate { m m } - { - \tl_set:Nn \l__tblr_template_name_tl {#2} - \keys_set:nn { tblr-set-template } {#1} - \ignorespaces - } - -\cs_new_protected:Npn \__tblr_set_template:n #1 - { - \tl_set_eq:cc { l__tblr_template_ #1 _default_tl } - { l__tblr_template_ #1 _ \l__tblr_template_name_tl _tl } - } -\cs_generate_variant:Nn \__tblr_set_template:n { V } - -\NewExpandableDocumentCommand \GetTblrStyle { m m } - { - \__tblr_style_item:n { #1 / #2 } - } - -\NewDocumentCommand \UseTblrFont { m } - { - \GetTblrStyle {#1} { font } \selectfont - } - -\tl_new:N \l__tblr_use_color_tl - -\NewDocumentCommand \UseTblrColor { m } - { - \tl_set:Nx \l__tblr_use_color_tl { \GetTblrStyle {#1} { fg } } - \tl_if_empty:NF \l__tblr_use_color_tl { \color { \l__tblr_use_color_tl } } - } - -%% All halign commands are defined at the beginning of the file -\NewDocumentCommand \UseTblrAlign { m } - { - \use:c { __tblr_halign_command_ \GetTblrStyle {#1} { halign } : } - } - -\tl_new:N \l__tblr_use_hang_tl - -\NewDocumentCommand \UseTblrHang { m } - { - \tl_set:Nx \l__tblr_use_hang_tl { \GetTblrStyle {#1} { hang } } - \tl_if_empty:NF \l__tblr_use_hang_tl - { - \tl_put_left:Nn \l__tblr_use_hang_tl - { \hangafter = 1 \relax \hangindent = } - \tl_put_right:Nn \l__tblr_use_hang_tl { \relax } - \exp_args:NV \everypar \l__tblr_use_hang_tl - } - } - -\tl_new:N \l__tblr_use_indent_tl - -\NewDocumentCommand \UseTblrIndent { m } - { - \tl_set:Nx \l__tblr_use_indent_tl { \GetTblrStyle {#1} { indent } } - \tl_if_empty:NF \l__tblr_use_indent_tl - { \exp_args:NNV \setlength \parindent \l__tblr_use_indent_tl } - } - -\AtBeginDocument - { - \@ifpackageloaded{xcolor}{}{\RenewDocumentCommand \UseTblrColor {m} {}} - } - -%% #1: head/foot element; #2: template name -\NewExpandableDocumentCommand \ExpTblrTemplate { m m } - { - \tl_use:c { l__tblr_template_ #1 _ #2 _tl } - } - -%% #1: head/foot element; #2: template name -\NewDocumentCommand \UseTblrTemplate { m m } - { - \group_begin: - \UseTblrFont {#1} - \UseTblrColor {#1} - \tl_use:c { l__tblr_template_ #1 _ #2 _tl } - \group_end: - } - -\NewDocumentCommand \MapTblrNotes { +m } - { - \__tblr_prop_map_inline:nn { note } - { - \tl_set_rescan:Nnn \InsertTblrNoteTag {} {##1} - \tl_set:Nn \InsertTblrNoteText {##2} - #1 - } - } - -\NewDocumentCommand \MapTblrRemarks { +m } - { - \__tblr_prop_map_inline:nn { remark } - { - \tl_set_rescan:Nnn \InsertTblrRemarkTag {} {##1} - \tl_set:Nn \InsertTblrRemarkText {##2} - #1 - } - } - -\NewExpandableDocumentCommand \InsertTblrText { m } - { - \__tblr_spec_item:nn { outer } {#1} - } - -\NewExpandableDocumentCommand \InsertTblrMore { m } - { - \__tblr_prop_item:nn { more } {#1} - } - -%%% -------------------------------------------------------- -%%> \section{Table Continuation Templates} -%%% -------------------------------------------------------- - -\DefTblrTemplate { contfoot-text } { normal } { Continued ~ on ~ next ~ page } -\SetTblrTemplate { contfoot-text } { normal } - -\DefTblrTemplate { contfoot } { empty } { } -\DefTblrTemplate { contfoot } { plain } - { - \noindent - \raggedleft - \UseTblrTemplate { contfoot-text } { default } - \par - } -\DefTblrTemplate { contfoot } { normal } - { - %% need to set parindent after alignment - \raggedleft - \UseTblrAlign { contfoot } - \UseTblrIndent { contfoot } - \UseTblrHang { contfoot } - \leavevmode - \UseTblrTemplate { contfoot-text } { default } - \par - } -\SetTblrTemplate { contfoot } { normal } - -\DefTblrTemplate { conthead-text } { normal } { ( Continued ) } -\SetTblrTemplate { conthead-text } { normal } - -\DefTblrTemplate { conthead } { empty } { } -\DefTblrTemplate { conthead } { plain } - { - \noindent - \raggedright - \UseTblrTemplate { conthead-text } { default } - \par - } -\DefTblrTemplate { conthead } { normal } - { - %% need to set parindent after alignment - \raggedright - \UseTblrAlign { conthead } - \UseTblrIndent { conthead } - \UseTblrHang { conthead } - \leavevmode - \UseTblrTemplate { conthead-text } { default } - \par - } -\SetTblrTemplate { conthead } { normal } - -%%% -------------------------------------------------------- -%%> \section{Table Caption Templates} -%%% -------------------------------------------------------- - -\tl_new:N \l__tblr_caption_short_tl - -\DefTblrTemplate { caption-lot } { empty } { } -\DefTblrTemplate { caption-lot } { normal } - { - \tl_set:Nx \l__tblr_caption_short_tl { \InsertTblrText { entry } } - \tl_if_empty:NT \l__tblr_caption_short_tl - { \tl_set:Nx \l__tblr_caption_short_tl { \InsertTblrText { caption } } } - \addcontentsline { lot } { table } - { \protect\numberline { \thetable } { \l__tblr_caption_short_tl } } - } -\SetTblrTemplate { caption-lot } { normal } - -%% We need to use \hspace and \enskip, but not ~ or \space, -%% since we want a correct hangindent caption paragraph. - -\DefTblrTemplate { caption-tag } { empty } { } -\DefTblrTemplate { caption-tag } { normal } { \tablename\hspace{0.25em}\thetable } -\SetTblrTemplate { caption-tag } { normal } - -\DefTblrTemplate { caption-sep } { empty } { } -\DefTblrTemplate { caption-sep } { normal } { : \enskip } -\SetTblrTemplate { caption-sep } { normal } - -\DefTblrTemplate { caption-text } { empty } { } -\DefTblrTemplate { caption-text } { normal } { \InsertTblrText { caption } } -\SetTblrTemplate { caption-text } { normal } - -\box_new:N \l__tblr_caption_box -\box_new:N \l__tblr_caption_left_box - -\DefTblrTemplate { caption } { empty } { } -\DefTblrTemplate { caption } { plain } - { - \hbox_set:Nn \l__tblr_caption_box - { - \UseTblrTemplate { caption-tag } { default } - \UseTblrTemplate { caption-sep } { default } - \UseTblrTemplate { caption-text } { default } - } - \dim_compare:nNnTF { \box_wd:N \l__tblr_caption_box } > { \hsize } - { - \noindent - \hbox_unpack:N \l__tblr_caption_box - \par - } - { - \centering - \makebox [\hsize] [c] { \box_use:N \l__tblr_caption_box } - \par - } - } -\DefTblrTemplate { caption } { normal } - { - \hbox_set:Nn \l__tblr_caption_box - { - \UseTblrTemplate { caption-tag } { default } - \UseTblrTemplate { caption-sep } { default } - \UseTblrTemplate { caption-text } { default } - } - \dim_compare:nNnTF { \box_wd:N \l__tblr_caption_box } > { \hsize } - { - \UseTblrAlign { caption } - \UseTblrIndent { caption } - \hbox_set:Nn \l__tblr_caption_left_box - { - \UseTblrTemplate { caption-tag } { default } - \UseTblrTemplate { caption-sep } { default } - } - \hangindent = \box_wd:N \l__tblr_caption_left_box - \hangafter = 1 - \UseTblrHang { caption } - \leavevmode - \hbox_unpack:N \l__tblr_caption_box - \par - } - { - \centering - \makebox [\hsize] [c] { \box_use:N \l__tblr_caption_box } - \par - } - } -\DefTblrTemplate { caption } { simple } - { - \UseTblrAlign { caption } - \UseTblrIndent { caption } - \UseTblrHang { caption } - \leavevmode - \UseTblrTemplate { caption-tag } { default } - \UseTblrTemplate { caption-sep } { default } - \UseTblrTemplate { caption-text } { default } - \par - } -\SetTblrTemplate { caption } { normal } - -\DefTblrTemplate { capcont } { empty } { } -\DefTblrTemplate { capcont } { plain } - { - \hbox_set:Nn \l__tblr_caption_box - { - \UseTblrTemplate { caption-tag } { default } - \UseTblrTemplate { caption-sep } { default } - \UseTblrTemplate { caption-text } { default } - \space - \UseTblrTemplate { conthead-text } { default } - } - \dim_compare:nNnTF { \box_wd:N \l__tblr_caption_box } > { \hsize } - { - \noindent - \hbox_unpack:N \l__tblr_caption_box - \par - } - { - \centering - \makebox [\hsize] [c] { \box_use:N \l__tblr_caption_box } - \par - } - } -\DefTblrTemplate { capcont } { normal } - { - \hbox_set:Nn \l__tblr_caption_box - { - \UseTblrTemplate { caption-tag } { default } - \UseTblrTemplate { caption-sep } { default } - \UseTblrTemplate { caption-text } { default } - \space - \UseTblrTemplate { conthead-text } { default } - } - \dim_compare:nNnTF { \box_wd:N \l__tblr_caption_box } > { \hsize } - { - \UseTblrAlign { capcont } - \UseTblrIndent { capcont } - \hbox_set:Nn \l__tblr_caption_left_box - { - \UseTblrTemplate { caption-tag } { default } - \UseTblrTemplate { caption-sep } { default } - } - \hangindent = \box_wd:N \l__tblr_caption_left_box - \hangafter = 1 - \UseTblrHang { capcont } - \leavevmode - \hbox_unpack:N \l__tblr_caption_box - \par - } - { - \centering - \makebox [\hsize] [c] { \box_use:N \l__tblr_caption_box } - \par - } - } -\DefTblrTemplate { capcont } { simple } - { - \UseTblrAlign { caption } - \UseTblrIndent { caption } - \UseTblrHang { caption } - \leavevmode - \UseTblrTemplate { caption-tag } { default } - \UseTblrTemplate { caption-sep } { default } - \UseTblrTemplate { caption-text } { default } - \space - \UseTblrTemplate { conthead-text } { default } - \par - } -\SetTblrTemplate { capcont} { normal } - -%%% -------------------------------------------------------- -%%> \section{Table Notes Templates} -%%% -------------------------------------------------------- - -%% By default the targets generated by \hypertarget are too low -%% Therefore we need to use \Hy@raisedlink command to fix this problem -%% See https://tex.stackexchange.com/questions/17057 -%% We also use \use:c in case the private command \Hy@raisedlink is removed -\cs_new_protected:Npn \__tblr_hyper_target:n #1 - { - \cs_if_exist:NT \hypertarget - { - \use:c { Hy@raisedlink } - { - \hypertarget - { tblr / \int_use:N \g__tblr_table_count_int / \tl_to_str:n {#1} } - { } - } - } - } -\cs_generate_variant:Nn \__tblr_hyper_target:n { V } - -\cs_new_protected:Npn \__tblr_hyper_link:nn #1 #2 - { - \cs_if_exist:NTF \hyperlink - { - \hyperlink - { tblr / \int_use:N \g__tblr_table_count_int / \tl_to_str:n {#1} } - { #2 } - } - { #2 } - } - -\DefTblrTemplate { note-border } { empty } - { - \hypersetup { pdfborder = { 0 ~ 0 ~ 0 } } - } -\DefTblrTemplate { note-border } { normal } - { - \hypersetup { pdfborder = { 0 ~ 0 ~ 1 } } - } -\SetTblrTemplate { note-border } { empty } - -\NewDocumentCommand \TblrNote { m } - { - \cs_if_exist:NT \hypersetup { \ExpTblrTemplate { note-border }{ default } } - \__tblr_hyper_link:nn {#1} - { \textsuperscript { \sffamily \UseTblrFont { note-tag } #1 } } - } - -\DefTblrTemplate { note-tag } { empty } { } -\DefTblrTemplate { note-tag } { normal } - { - \textsuperscript { \sffamily \UseTblrFont { note-tag } \InsertTblrNoteTag } - } -\SetTblrTemplate { note-tag } { normal } - -\DefTblrTemplate { note-target } { normal } - { - \__tblr_hyper_target:V \InsertTblrNoteTag - } -\SetTblrTemplate { note-target } { normal } - -\DefTblrTemplate { note-sep } { empty } { } -\DefTblrTemplate { note-sep } { normal } { \space } -\SetTblrTemplate { note-sep } { normal } - -\DefTblrTemplate { note-text } { empty } { } -\DefTblrTemplate { note-text } { normal } { \InsertTblrNoteText } -\SetTblrTemplate { note-text } { normal } - -\DefTblrTemplate { note } { empty } { } -\DefTblrTemplate { note } { plain } - { - \MapTblrNotes - { - \noindent - \UseTblrTemplate { note-tag } { default } - \UseTblrTemplate { note-target } { default } - \UseTblrTemplate { note-sep } { default } - \UseTblrTemplate { note-text } { default } - \par - } - } -\DefTblrTemplate { note } { normal } - { - \UseTblrAlign { note } - \UseTblrIndent { note } - \MapTblrNotes - { - \hangindent = 0.7em - \hangafter = 1 - \UseTblrHang { note } - \leavevmode - \hbox_to_wd:nn { \the\hangindent } - { - \UseTblrTemplate { note-tag } { default } - \UseTblrTemplate { note-target } { default } - \hfil - } - \UseTblrTemplate { note-text } { default } - \par - } - } -\DefTblrTemplate { note } { inline } - { - \UseTblrAlign { note } - \UseTblrIndent { note } - \UseTblrHang { note } - \leavevmode - \MapTblrNotes - { - \UseTblrTemplate { note-tag } { default } - \UseTblrTemplate { note-target } { default } - \UseTblrTemplate { note-sep } { default } - \UseTblrTemplate { note-text } { default } - \quad - } - \par - } -\SetTblrTemplate { note } { normal } - -%%% -------------------------------------------------------- -%%> \section{Table Remarks Templates} -%%% -------------------------------------------------------- - -\DefTblrTemplate { remark-tag } { empty } { } -\DefTblrTemplate { remark-tag } { normal } - { - \itshape \UseTblrFont { remark-tag } \InsertTblrRemarkTag - } -\SetTblrTemplate { remark-tag } { normal } - -\DefTblrTemplate { remark-sep } { empty } { } -\DefTblrTemplate { remark-sep } { normal } { : \space } -\SetTblrTemplate { remark-sep } { normal } - -\DefTblrTemplate { remark-text } { empty } { } -\DefTblrTemplate { remark-text } { normal } { \InsertTblrRemarkText } -\SetTblrTemplate { remark-text } { normal } - -\DefTblrTemplate { remark } { empty } { } -\DefTblrTemplate { remark } { plain } - { - \MapTblrRemarks - { - \noindent - \UseTblrTemplate { remark-tag } { default } - \UseTblrTemplate { remark-sep } { default } - \UseTblrTemplate { remark-text } { default } - \par - } - } -\DefTblrTemplate { remark } { normal } - { - \UseTblrAlign { remark } - \UseTblrIndent { remark } - \MapTblrRemarks - { - \hangindent = 0.7em - \hangafter = 1 - \UseTblrHang { remark } - \leavevmode - \UseTblrTemplate { remark-tag } { default } - \UseTblrTemplate { remark-sep } { default } - \UseTblrTemplate { remark-text } { default } - \par - } - } -\DefTblrTemplate { remark } { inline } - { - \UseTblrAlign { remark } - \UseTblrIndent { remark } - \UseTblrHang { remark } - \leavevmode - \MapTblrRemarks - { - \UseTblrTemplate { remark-tag } { default } - \UseTblrTemplate { remark-sep } { default } - \UseTblrTemplate { remark-text } { default } - \quad - } - \par - } -\SetTblrTemplate { remark } { normal } - -%%% -------------------------------------------------------- -%%> \section{Header and Footer Templates} -%%% -------------------------------------------------------- - -\tl_new:N \g__tblr_template_firsthead_default_tl -\tl_new:N \g__tblr_template_middlehead_default_tl -\tl_new:N \g__tblr_template_lasthead_default_tl -\tl_new:N \g__tblr_template_firstfoot_default_tl -\tl_new:N \g__tblr_template_middlefoot_default_tl -\tl_new:N \g__tblr_template_lastfoot_default_tl - -\keys_define:nn { tblr-def-template } - { - head .meta:n = { firsthead, middlehead, lasthead }, - foot .meta:n = { firstfoot, middlefoot, lastfoot }, - } - -\keys_define:nn { tblr-set-template } - { - head .meta:n = { firsthead, middlehead, lasthead }, - foot .meta:n = { firstfoot, middlefoot, lastfoot }, - } - -\DefTblrTemplate { head } { empty } { } -\DefTblrTemplate { foot } { empty } { } - -\DefTblrTemplate { firsthead } { normal } - { - \UseTblrTemplate { caption } { default } - } - -\DefTblrTemplate { middlehead, lasthead } { normal } - { - \UseTblrTemplate { capcont } { default } - } - -\DefTblrTemplate { firstfoot, middlefoot } { normal } - { - \UseTblrTemplate { contfoot } { default } - } - -\DefTblrTemplate { lastfoot } { normal } - { - \UseTblrTemplate { note } { default } - \UseTblrTemplate { remark } { default } - } - -\SetTblrTemplate { head } { normal } -\SetTblrTemplate { foot } { normal } - -%%% -------------------------------------------------------- -%%> \section{Build the Whole Table} -%%% -------------------------------------------------------- - -\cs_new:Npn \__tblr_box_height:N #1 - { - \dim_eval:n { \box_ht:N #1 + \box_dp:N #1 } - } - -\cs_new_protected:Npn \__tblr_build_head_foot: - { - \__tblr_build_row_head_foot: - \__tblr_build_table_head_foot: - } - -\tl_new:N \l__tblr_row_head_tl -\tl_new:N \l__tblr_row_foot_tl -\box_new:N \l__tblr_row_head_box -\box_new:N \l__tblr_row_foot_box -\dim_new:N \l__tblr_row_head_foot_dim - -\cs_new_protected:Npn \__tblr_build_row_head_foot: - { - %% \l__tblr_row_head_tl and \l__tblr_row_foot_tl may be empty - \tl_set:Nx \l__tblr_row_head_tl { \__tblr_prop_item:ne { inner } { rowhead } } - \int_compare:nNnTF { \l__tblr_row_head_tl + 0 } > { 0 } - { \__tblr_build_one_table:nn {1} { \l__tblr_row_head_tl } } - { \__tblr_build_one_hline:n {1} } - \box_set_eq:NN \l__tblr_row_head_box \l__tblr_table_box - \tl_set:Nx \l__tblr_row_foot_tl { \__tblr_prop_item:ne { inner } { rowfoot } } - \int_compare:nNnTF { \l__tblr_row_foot_tl + 0 } > { 0 } - { - \__tblr_build_one_table:nn - { \c@rowcount - \l__tblr_row_foot_tl + 1 } { \c@rowcount } - } - { \__tblr_build_one_hline:n { \int_eval:n { \c@rowcount + 1 } } } - \box_set_eq:NN \l__tblr_row_foot_box \l__tblr_table_box - \dim_set:Nn \l__tblr_row_head_foot_dim - { - \__tblr_box_height:N \l__tblr_row_head_box - + \__tblr_box_height:N \l__tblr_row_foot_box - } - } - -\dim_new:N \tablewidth - -\cs_new_protected:Npn \__tblr_get_table_width: - { - \dim_zero:N \tablewidth - \int_step_inline:nn { \c@colcount } - { - \dim_add:Nn \tablewidth - { - \__tblr_spec_item:nn { vline } { [##1] / @vline-width } - + - \__tblr_data_item:nnn { column } {##1} { leftsep } - + - \__tblr_data_item:nnn { column } {##1} { @col-width } - + - \__tblr_data_item:nnn { column } {##1} { rightsep } - } - } - \dim_add:Nn \tablewidth - { - \__tblr_spec_item:ne { vline } - { [\int_eval:n { \c@colcount + 1 }] / @vline-width } - } - } - -\box_new:N \l__tblr_table_firsthead_box -\box_new:N \l__tblr_table_middlehead_box -\box_new:N \l__tblr_table_lasthead_box -\box_new:N \l__tblr_table_firstfoot_box -\box_new:N \l__tblr_table_middlefoot_box -\box_new:N \l__tblr_table_lastfoot_box - -\cs_new_protected:Npn \__tblr_build_table_head_foot: - { - \__tblr_get_table_width: - \__tblr_build_table_head_aux:Nn \l__tblr_table_firsthead_box - { - \__tblr_build_table_label_entry: - \UseTblrTemplate { firsthead } { default } - } - \__tblr_build_table_head_aux:Nn - \l__tblr_table_middlehead_box { \UseTblrTemplate { middlehead } { default } } - \__tblr_build_table_head_aux:Nn - \l__tblr_table_lasthead_box { \UseTblrTemplate { lasthead } { default } } - \__tblr_build_table_foot_aux:Nn - \l__tblr_table_firstfoot_box { \UseTblrTemplate { firstfoot } { default } } - \__tblr_build_table_foot_aux:Nn - \l__tblr_table_middlefoot_box { \UseTblrTemplate { middlefoot } { default } } - \__tblr_build_table_foot_aux:Nn - \l__tblr_table_lastfoot_box { \UseTblrTemplate { lastfoot } { default } } - } - -\cs_new_protected:Npn \__tblr_build_tall_table_head_foot: - { - \__tblr_get_table_width: - \__tblr_build_table_head_aux:Nn \l__tblr_table_firsthead_box - { - \__tblr_build_table_label_entry: - \UseTblrTemplate { firsthead } { default } - } - \__tblr_build_table_foot_aux:Nn - \l__tblr_table_lastfoot_box { \UseTblrTemplate { lastfoot } { default } } - } - -\cs_new_protected:Npn \__tblr_build_table_label_entry: - { - \tl_set:Nx \l_tmpa_tl { \InsertTblrText { label } } - \tl_if_eq:NnTF \l_tmpa_tl { none } - { - \SetTblrTemplate { caption-tag }{ empty } - \SetTblrTemplate { caption-sep }{ empty } - } - { - \refstepcounter { table } - \tl_if_empty:NF \l_tmpa_tl { \exp_args:NV \label \l_tmpa_tl } - } - \tl_set:Nx \l_tmpb_tl { \InsertTblrText { entry } } - \tl_if_eq:NnF \l_tmpb_tl { none } - { \UseTblrTemplate { caption-lot } { default } } - } - -\cs_new_protected:Npn \__tblr_build_table_head_aux:Nn #1 #2 - { - \vbox_set:Nn #1 - { - \hsize = \tablewidth - \parindent = 0pt \relax - \vbox:n {#2} - \skip_vertical:n { \__tblr_spec_item:nn { outer } { headsep } } - } - } - -\cs_new_protected:Npn \__tblr_build_table_foot_aux:Nn #1 #2 - { - \vbox_set:Nn #1 - { - \hsize = \tablewidth - \skip_vertical:n { \__tblr_spec_item:nn { outer } { footsep } } - \parindent = 0pt \relax - \vbox:n {#2} - } - } - -\cs_new_protected:Npn \__tblr_build_whole: - { - \tl_if_eq:enTF { \__tblr_spec_item:nn { outer } { long } } { true } - { \__tblr_build_long_table:e { \__tblr_spec_item:nn { outer } { halign } } } - { - \tl_if_eq:enTF { \__tblr_spec_item:nn { outer } { tall } } { true } - { - \__tblr_build_tall_table:e - { \__tblr_spec_item:nn { outer } { valign } } - } - { - \__tblr_build_short_table:e - { \__tblr_spec_item:nn { outer } { valign } } - } - } - } - -\dim_new:N \l__tblr_remain_height_dim -\int_new:N \l__tblr_long_from_int -\int_new:N \l__tblr_long_to_int -\int_new:N \l__tblr_curr_i_int -\int_new:N \l__tblr_prev_i_int -\int_new:N \l__tblr_table_page_int -\bool_new:N \l__tblr_page_break_curr_bool -\bool_new:N \l__tblr_page_break_prev_bool - -%% #1: table alignment -%% For long table, we need to leave hmode first to get correct \pagetotal -%% Also remove topskip and presep if we are at the beginning of the page -\cs_new_protected:Npn \__tblr_build_long_table:n #1 - { - \LogTblrTracing { page } - \par - \LogTblrTracing { page } - \dim_compare:nNnTF { \pagegoal } = { \maxdimen } - { \hbox{}\kern-\topskip\nobreak } - { \skip_vertical:n { \__tblr_spec_item:nn { outer } { presep } } } - \LogTblrTracing { page } - \nointerlineskip - \mode_leave_vertical: % enter horizontal mode to update \pagetotal - \LogTblrTracing { page } - \hrule height ~ 0pt - \nobreak % prevent page break after \hrule (see issue #42) - \LogTblrTracing { page } - \int_set:Nn \l__tblr_table_page_int {1} - \__tblr_build_head_foot: - \dim_set:Nn \l__tblr_remain_height_dim - { \pagegoal - \pagetotal - \l__tblr_row_head_foot_dim } - \int_set:Nn \l__tblr_long_from_int { \l__tblr_row_head_tl + 1 } - \int_set:Nn \l__tblr_long_to_int { \c@rowcount - ( \l__tblr_row_foot_tl + 0 ) } - \int_set:Nn \l__tblr_curr_i_int { \l__tblr_long_from_int - 1 } - \int_do_while:nNnn { \l__tblr_curr_i_int } < { \l__tblr_long_to_int } - { - \int_set_eq:NN \l__tblr_prev_i_int \l__tblr_curr_i_int - \__tblr_get_next_table_rows:NNNN - \l__tblr_long_to_int \l__tblr_curr_i_int - \l_tmpa_dim \l__tblr_page_break_curr_bool - \__tblr_check_table_page_break:NNN - \l__tblr_remain_height_dim \l_tmpa_dim \l__tblr_page_break_prev_bool - \__tblr_do_if_tracing:nn { page } { \int_log:N \l__tblr_curr_i_int } - \bool_if:NTF \l__tblr_page_break_prev_bool - { - \int_compare:nNnTF - { \l__tblr_long_from_int } > { \l__tblr_prev_i_int } - { - % See issue #42: if longtblr starts at the bottom of a page, - % \pagetotal maybe exceed \pagegoal after adding presep, - % or after adding rowhead or rowfoot of the table. - % In these cases, we will not typeset table in this page, - % but rather do some negative \vskip and execute \newpage. - \skip_vertical:n { \pagegoal - \pagetotal } - } - { - \__tblr_build_page_table:nnx {#1} - { \int_use:N \l__tblr_long_from_int } - { \int_use:N \l__tblr_prev_i_int } - \int_incr:N \l__tblr_table_page_int - \int_set:Nn \l__tblr_long_from_int { \l__tblr_prev_i_int + 1 } - } - \newpage - \hbox{}\kern-\topskip\nobreak - \noindent - \LogTblrTracing { page } - \dim_set:Nn \l__tblr_remain_height_dim - { \pagegoal - \pagetotal - \l__tblr_row_head_foot_dim - \l_tmpa_dim } - } - { - \bool_if:NTF \l__tblr_page_break_curr_bool - { - \__tblr_build_page_table:nnx {#1} - { \int_use:N \l__tblr_long_from_int } - { \int_use:N \l__tblr_curr_i_int } - \int_incr:N \l__tblr_table_page_int - \newpage - \hbox{}\kern-\topskip\nobreak - \noindent - \LogTblrTracing { page } - \dim_set:Nn \l__tblr_remain_height_dim - { \pagegoal - \pagetotal - \l__tblr_row_head_foot_dim } - \int_set:Nn \l__tblr_long_from_int { \l__tblr_curr_i_int + 1 } - } - { \dim_add:Nn \l__tblr_remain_height_dim { -\l_tmpa_dim } } - } - } - \int_compare:nNnTF { \l__tblr_table_page_int } = {1} - { - \box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_firsthead_box - \box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_lastfoot_box - } - { - \box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_lasthead_box - \box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_lastfoot_box - } - \__tblr_build_page_table:nnn {#1} - { \int_use:N \l__tblr_long_from_int } { \int_use:N \l__tblr_long_to_int } - \skip_vertical:n { \__tblr_spec_item:nn { outer } { postsep } } - % In the past we used "\hrule height ~ 0pt" to get strict postsep, - % but the postsep was not discarded when page breaks, see issue #39. - % Therefore we use \nointerlineskip here. - \nointerlineskip - } -\cs_generate_variant:Nn \__tblr_build_long_table:n { e } - -%% #1: int with index of the last row; #2: int with index of current row; -%% #3: row dimension; #4: break page or not. -\cs_new_protected:Npn \__tblr_get_next_table_rows:NNNN #1 #2 #3 #4 - { - \bool_set_true:N \l_tmpa_bool - \dim_zero:N #3 - \bool_set_false:N #4 - \bool_while_do:Nn \l_tmpa_bool - { - \int_incr:N #2 - \dim_add:Nn #3 - { - \__tblr_data_item:nen { row } { \int_use:N #2 } { abovesep } - + - \__tblr_data_item:nen { row } { \int_use:N #2 } { @row-height } - + - \__tblr_data_item:nen { row } { \int_use:N #2 } { belowsep } - + - \__tblr_spec_item:ne { hline } - { [ \int_eval:n { #2 + 1 } ] / @hline-height } - } - \int_compare:nNnTF {#2} < {#1} - { - \tl_set:Nx \l__tblr_b_tl - { \__tblr_data_item:nen { row } { \int_eval:n { #2 + 1 } } { break } } - \int_compare:nNnTF { \l__tblr_b_tl } < { 0 } - { \bool_set_true:N \l_tmpa_bool } - { - \bool_set_false:N \l_tmpa_bool - \int_compare:nNnT { \l__tblr_b_tl } > { 0 } { \bool_set_true:N #4 } - } - } - { \bool_set_false:N \l_tmpa_bool } - } - } - -\box_new:N \l__tblr_table_head_box -\box_new:N \l__tblr_table_foot_box -\dim_new:N \l__tblr_table_head_foot_dim -\dim_new:N \l__tblr_table_head_body_foot_dim - -%% #1: remain dimension; #2: row dimension; #3: break page or not -\cs_new_protected:Npn \__tblr_check_table_page_break:NNN #1 #2 #3 - { - \int_compare:nNnTF { \l__tblr_table_page_int } = {1} - { - \dim_set:Nn \l__tblr_table_head_body_foot_dim - { - \__tblr_box_height:N \l__tblr_table_firsthead_box - + #2 + \__tblr_box_height:N \l__tblr_table_firstfoot_box - } - \box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_firsthead_box - \dim_compare:nNnTF - { \l__tblr_table_head_body_foot_dim } > {#1} - { - \bool_set_true:N #3 - \box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_firstfoot_box - } - { \bool_set_false:N #3 } - } - { - \dim_set:Nn \l__tblr_table_head_body_foot_dim - { - \__tblr_box_height:N \l__tblr_table_middlehead_box - + #2 + \__tblr_box_height:N \l__tblr_table_middlefoot_box - } - \box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_middlehead_box - \dim_compare:nNnTF - { \l__tblr_table_head_body_foot_dim } > {#1} - { - \bool_set_true:N #3 - \box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_middlefoot_box - } - { \bool_set_false:N #3 } - } - } - -\box_new:N \l__tblr_table_box - -%% #1: table alignment; #2: row from; #3: row to -\cs_new_protected:Npn \__tblr_build_page_table:nnn #1 #2 #3 - { - \bool_set_false:N \l__tblr_build_first_hline_bool - \bool_set_false:N \l__tblr_build_last_hline_bool - \__tblr_build_one_table:nn {#2} {#3} - \vbox_set:Nn \l__tblr_table_box - { - \box_use:N \l__tblr_table_head_box - \__tblr_cover_two_vboxes:NN \l__tblr_row_head_box \l__tblr_table_box - \box_use:N \l__tblr_row_foot_box - \hrule height ~ 0pt - \box_use:N \l__tblr_table_foot_box - } - \__tblr_halign_whole:Nn \l__tblr_table_box #1 - } -\cs_generate_variant:Nn \__tblr_build_page_table:nnn { nnx } - -%% To solve the problem of missing hlines of long tables in some PDF readers, -%% We need to draw body rows before head rows (see issue #88). -\cs_new_protected:Npn \__tblr_cover_two_vboxes:NN #1 #2 - { - \dim_set:Nn \l_tmpa_dim { \box_ht:N #1 + \box_dp:N #1 } - \dim_set:Nn \l_tmpb_dim { \box_ht:N #2 + \box_dp:N #2 } - \skip_vertical:N \l_tmpa_dim - \hrule height ~ 0pt - \box_use:N #2 - \skip_vertical:n { - \l_tmpa_dim - \l_tmpb_dim } - \hrule height ~ 0pt - \box_use:N #1 - \skip_vertical:N \l_tmpb_dim - \hrule height ~ 0pt - } - -\cs_new_protected:Npn \__tblr_halign_whole:Nn #1 #2 - { - \noindent - \hbox_to_wd:nn { \linewidth } - { - \tl_if_eq:nnF {#2} {l} { \hfil } - \box_use:N #1 - \tl_if_eq:nnF {#2} {r} { \hfil } - } - } - -%% #1: table alignment -%% For tall table, we need to leave vmode first. -%% Since there may be \centering in table environment, -%% We use \raggedright to reset alignement for table head/foot. -\cs_new_protected:Npn \__tblr_build_tall_table:n #1 - { - \mode_leave_vertical: - \raggedright - \__tblr_build_tall_table_head_foot: - \__tblr_build_one_table:nn {1} {\c@rowcount} - \vbox_set:Nn \l__tblr_table_box - { - \box_use:N \l__tblr_table_firsthead_box - \hrule height ~ 0pt - \box_use:N \l__tblr_table_box - \hrule height ~ 0pt - \box_use:N \l__tblr_table_lastfoot_box - } - \__tblr_valign_whole:Nn \l__tblr_table_box #1 - } -\cs_generate_variant:Nn \__tblr_build_tall_table:n { e } - -%% #1: table alignment -%% For short table, we need to leave vmode first -\cs_new_protected:Npn \__tblr_build_short_table:n #1 - { - \mode_leave_vertical: - \__tblr_build_one_table:nn {1} {\c@rowcount} - \__tblr_valign_whole:Nn \l__tblr_table_box #1 - } -\cs_generate_variant:Nn \__tblr_build_short_table:n { e } - -\bool_new:N \l__tblr_build_first_hline_bool -\bool_new:N \l__tblr_build_last_hline_bool -\bool_set_true:N \l__tblr_build_first_hline_bool -\bool_set_true:N \l__tblr_build_last_hline_bool -\box_new:N \l__tblr_table_hlines_box -\box_new:N \l__tblr_hline_box -\box_new:N \l__tblr_row_box - -%% #1: row from; #2: row to -%% To fix disappeared hlines with colorful tables in Adobe Reader (see #76), -%% we collect all hlines and draw them at the end of the table. -\cs_new_protected:Npn \__tblr_build_one_table:nn #1 #2 - { - \box_clear:N \l__tblr_table_hlines_box - \vbox_set:Nn \l__tblr_table_box - { - \int_step_variable:nnNn {#1} {#2} \l__tblr_i_tl - { - \bool_lazy_or:nnT - { \int_compare_p:nNn { \l__tblr_i_tl } > {#1} } - { \bool_if_p:N \l__tblr_build_first_hline_bool } - { \__tblr_put_one_hline:n { \__tblr_build_hline:V \l__tblr_i_tl } } - \hrule height ~ 0pt % remove lineskip between hlines and rows - \__tblr_put_one_row:n { \__tblr_build_row:N \l__tblr_i_tl } - \hrule height ~ 0pt - } - \bool_if:NT \l__tblr_build_last_hline_bool - { - \__tblr_put_one_hline:n - { \__tblr_build_hline:n { \int_eval:n {#2 + 1} } } - } - \skip_vertical:n - { - - \box_ht:N \l__tblr_table_hlines_box - - \box_dp:N \l__tblr_table_hlines_box - } - \box_use:N \l__tblr_table_hlines_box - } - \bool_set_true:N \l__tblr_build_first_hline_bool - \bool_set_true:N \l__tblr_build_last_hline_bool - } - -\cs_new_protected:Npn \__tblr_put_one_hline:n #1 - { - \hbox_set:Nn \l__tblr_hline_box {#1} - \skip_vertical:n { \box_ht:N \l__tblr_hline_box + \box_dp:N \l__tblr_hline_box } - \vbox_set:Nn \l__tblr_table_hlines_box - { - \vbox_unpack:N \l__tblr_table_hlines_box - \box_use:N \l__tblr_hline_box - } - } - -\cs_new_protected:Npn \__tblr_put_one_row:n #1 - { - \hbox_set:Nn \l__tblr_row_box {#1} - \vbox_set:Nn \l__tblr_table_hlines_box - { - \vbox_unpack:N \l__tblr_table_hlines_box - \skip_vertical:n - { \box_ht:N \l__tblr_row_box + \box_dp:N \l__tblr_row_box } - } - \box_use:N \l__tblr_row_box - } - -%% #1: hline number -\cs_new_protected:Npn \__tblr_build_one_hline:n #1 - { - \vbox_set:Nn \l__tblr_table_box { \hbox:n { \__tblr_build_hline:n { #1 } } } - } - -\tl_new:N \__tblr_vbox_align_tl -\tl_const:Nn \__tblr_vbox_t_tl {t} -\tl_const:Nn \__tblr_vbox_m_tl {m} -\tl_const:Nn \__tblr_vbox_c_tl {c} -\tl_const:Nn \__tblr_vbox_b_tl {b} - -\cs_new_protected:Npn \__tblr_valign_whole:Nn #1 #2 - { - \group_begin: - \tl_set:Nn \__tblr_vbox_align_tl {#2} - \dim_set:Nn \l__tblr_t_dim { \box_ht:N #1 + \box_dp:N #1 } - \tl_case:NnF \__tblr_vbox_align_tl - { - \__tblr_vbox_m_tl - { \__tblr_valign_whole_middle:N #1 } - \__tblr_vbox_c_tl - { \__tblr_valign_whole_middle:N #1 } - \__tblr_vbox_t_tl - { \__tblr_valign_whole_top:N #1 } - \__tblr_vbox_b_tl - { \__tblr_valign_whole_bottom:N #1 } - } - { \__tblr_valign_whole_middle:N #1 } - \group_end: - } - -\cs_new_protected:Npn \__tblr_valign_whole_middle:N #1 - { - \hbox:n { $ \m@th \tex_vcenter:D { \vbox_unpack_drop:N #1 } $ } - } - -\cs_new_protected:Npn \__tblr_valign_whole_top:N #1 - { - \tl_set:Nx \l__tblr_a_tl - { \__tblr_spec_item:ne { hline } { [1] / @hline-height } } - %% Note that \l__tblr_b_tl may be empty - \tl_set:Nx \l__tblr_b_tl - { \__tblr_prop_item:ne { inner } { baseline } } - \bool_lazy_or:nnTF - { \dim_compare_p:nNn { \l__tblr_a_tl } = { 0pt } } - { \int_compare_p:nNn { \l__tblr_b_tl + 0 } = { 1 } } - { - \dim_set:Nn \l__tblr_h_dim - { - \__tblr_data_item:nnn { row } {1} { abovesep } - + - ( \__tblr_data_item:nnn { row } {1} { @row-height } - + - \__tblr_data_item:nnn { row } {1} { @row-upper } - - - \__tblr_data_item:nnn { row } {1} { @row-lower } - ) / 2 - } - \dim_set:Nn \l__tblr_d_dim { \l__tblr_t_dim - \l__tblr_h_dim } - } - { - \dim_set:Nn \l__tblr_h_dim { 0pt } - \dim_set_eq:NN \l__tblr_d_dim \l__tblr_t_dim - } - \box_set_ht:Nn #1 { \l__tblr_h_dim } - \box_set_dp:Nn #1 { \l__tblr_d_dim } - \box_use_drop:N #1 - } - -\cs_new_protected:Npn \__tblr_valign_whole_bottom:N #1 - { - \tl_set:Nx \l__tblr_a_tl - { - \__tblr_spec_item:ne { hline } - { [\int_eval:n {\c@rowcount + 1}] / @hline-height } - } - %% Note that \l__tblr_b_tl may be empty - \tl_set:Nx \l__tblr_b_tl - { \__tblr_prop_item:ne { inner } { baseline } } - \bool_lazy_or:nnTF - { \dim_compare_p:nNn { \l__tblr_a_tl } = { 0pt } } - { \int_compare_p:nNn { \l__tblr_b_tl + 0 } = { \c@rowcount } } - { - \dim_set:Nn \l__tblr_d_dim - { - ( \__tblr_data_item:nen { row } - { \int_use:N \c@rowcount } { @row-height } - - - \__tblr_data_item:nen { row } - { \int_use:N \c@rowcount } { @row-upper } - + - \__tblr_data_item:nen { row } - { \int_use:N \c@rowcount } { @row-lower } - ) / 2 - + - \__tblr_data_item:nnn { row } {1} { belowsep } - } - \dim_set:Nn \l__tblr_h_dim { \l__tblr_t_dim - \l__tblr_d_dim } - } - { - \dim_set:Nn \l__tblr_d_dim { 0pt } - \dim_set_eq:NN \l__tblr_h_dim \l__tblr_t_dim - } - \box_set_ht:Nn #1 { \l__tblr_h_dim } - \box_set_dp:Nn #1 { \l__tblr_d_dim } - \box_use_drop:N #1 - } - -%%% -------------------------------------------------------- -%%> \section{Build Table Components} -%%% -------------------------------------------------------- - -\dim_new:N \l__tblr_col_o_wd_dim -\dim_new:N \l__tblr_col_b_wd_dim - -%% Build hline. #1: row number -\cs_new_protected:Npn \__tblr_build_hline:n #1 - { - \int_step_inline:nn { \c@colcount } - { \__tblr_build_hline_segment:nn { #1 } { ##1 } } - } -\cs_generate_variant:Nn \__tblr_build_hline:n { x, V } - -%% #1: row number, #2: column number -\cs_new_protected:Npn \__tblr_build_hline_segment:nn #1 #2 - { - \tl_set:Nx \l__tblr_n_tl - { \__tblr_spec_item:ne { hline } { [#1] / @hline-count } } - \tl_set:Nx \l__tblr_o_tl - { \__tblr_spec_item:ne { hline } { [#1][#2] / omit } } - \__tblr_get_col_outer_width_border_width:nNN {#2} - \l__tblr_col_o_wd_dim \l__tblr_col_b_wd_dim - \tl_if_empty:NTF \l__tblr_o_tl - { - \int_compare:nNnT { \l__tblr_n_tl } > {0} - { \__tblr_build_hline_segment_real:nn {#1} {#2} } - } - { \__tblr_build_hline_segment_omit:nn {#1} {#2} } - } - -%% #1: row number, #2: column number -\cs_new_protected:Npn \__tblr_build_hline_segment_omit:nn #1 #2 - { - \skip_horizontal:n { \l__tblr_col_o_wd_dim - \l__tblr_col_b_wd_dim } - } - -%% #1: row number, #2: column number -\cs_new_protected:Npn \__tblr_build_hline_segment_real:nn #1 #2 - { - \tl_set:Nx \l__tblr_s_tl - { \__tblr_prop_item:ne { inner } { rulesep } } - \vbox_set:Nn \l__tblr_c_box - { - %% add an empty hbox to support vbox width - \tex_hbox:D to \l__tblr_col_o_wd_dim {} - \int_step_inline:nn { \l__tblr_n_tl } - { - \tl_set:Nx \l__tblr_h_tl - { \__tblr_spec_item:ne { hline } { [#1](##1) / @hline-height } } - \hrule height ~ 0pt % remove lineskip - \hbox_set_to_wd:Nnn \l__tblr_b_box { \l__tblr_col_o_wd_dim } - { - \__tblr_get_hline_left_right_skips:nnn {#1} {#2} {##1} - \skip_horizontal:N \l__tblr_hline_leftskip_dim - \tl_set:Nx \l__tblr_f_tl - { \__tblr_spec_item:ne { hline } { [#1][#2](##1) / fg } } - \tl_if_empty:NF \l__tblr_f_tl { \color{\l__tblr_f_tl} } - \__tblr_get_hline_segment_child:nnn {#1} {#2} {##1} - \skip_horizontal:N \l__tblr_hline_rightskip_dim - } - \box_set_ht:Nn \l__tblr_b_box { \l__tblr_h_tl } - \box_set_dp:Nn \l__tblr_b_box { 0pt } - \box_use:N \l__tblr_b_box - \skip_vertical:n { \l__tblr_s_tl } - } - \skip_vertical:n { - \l__tblr_s_tl } - } - \box_use:N \l__tblr_c_box - \skip_horizontal:n { - \l__tblr_col_b_wd_dim } - } - -%% Read from table specifications and calculate the widths of row and border -%% column outer width = content width + colsep width + border width -%% #1: the column number, #2: outer width, #3: border width -\cs_new_protected:Npn \__tblr_get_col_outer_width_border_width:nNN #1 #2 #3 - { - \dim_set:Nn #3 - { \__tblr_spec_item:ne { vline } { [\int_eval:n {#1 + 1}] / @vline-width } } - \dim_set:Nn #2 - { - \__tblr_spec_item:ne { vline } { [#1] / @vline-width } - + - \__tblr_data_item:nen { column } {#1} { leftsep } - + - \__tblr_data_item:nen { column } {#1} { @col-width } - + - \__tblr_data_item:nen { column } {#1} { rightsep } - + - #3 - } - } - -\dim_new:N \l__tblr_hline_leftskip_dim -\dim_new:N \l__tblr_hline_rightskip_dim - -%% Calculate left and right skips from leftpos and rightpos specifications -%% #1: row number; #2: column number; #3: hline index; -\cs_new_protected:Npn \__tblr_get_hline_left_right_skips:nnn #1 #2 #3 - { - \tl_set:Nx \l__tblr_hline_leftpos_tl - { \__tblr_spec_item:ne { hline } { [#1][#2](#3) / leftpos } } - \tl_if_empty:NT \l__tblr_hline_leftpos_tl - { \tl_set:Nn \l__tblr_hline_leftpos_tl {1} } % default position - \tl_set:Nx \l__tblr_hline_rightpos_tl - { \__tblr_spec_item:ne { hline } { [#1][#2](#3) / rightpos } } - \tl_if_empty:NT \l__tblr_hline_rightpos_tl - { \tl_set:Nn \l__tblr_hline_rightpos_tl {1} } % default position - \fp_compare:nNnT { \l__tblr_hline_leftpos_tl } < {1} - { - \dim_set:Nn \l_tmpa_dim - { \__tblr_spec_item:ne { vline } { [#2] / @vline-width } } - \dim_set:Nn \l_tmpb_dim - { \__tblr_data_item:nen { column } {#2} { leftsep } } - \fp_compare:nNnTF { \l__tblr_hline_leftpos_tl } < {0} - { - \dim_set:Nn \l__tblr_hline_leftskip_dim - { \l_tmpa_dim - \l__tblr_hline_leftpos_tl \l_tmpb_dim } - } - { - \dim_set:Nn \l__tblr_hline_leftskip_dim - { \l_tmpa_dim - \l__tblr_hline_leftpos_tl \l_tmpa_dim } - } - } - \fp_compare:nNnT { \l__tblr_hline_rightpos_tl } < {1} - { - \dim_set:Nn \l_tmpa_dim - { - \__tblr_spec_item:ne { vline } - { [\int_eval:n { #2 + 1 }] / @vline-width } - } - \dim_set:Nn \l_tmpb_dim - { \__tblr_data_item:nen { column } {#2} { rightsep } } - \fp_compare:nNnTF { \l__tblr_hline_rightpos_tl } < {0} - { - \dim_set:Nn \l__tblr_hline_rightskip_dim - { \l_tmpa_dim - \l__tblr_hline_rightpos_tl \l_tmpb_dim } - } - { - \dim_set:Nn \l__tblr_hline_rightskip_dim - { \l_tmpa_dim - \l__tblr_hline_rightpos_tl \l_tmpa_dim } - } - } - } - -\dim_new:N \l__tblr_row_ht_dim -\dim_new:N \l__tblr_row_dp_dim -\dim_new:N \l__tblr_row_abovesep_dim -\dim_new:N \l__tblr_row_belowsep_dim -\box_new:N \l__tblr_row_vlines_box -\box_new:N \l__tblr_vline_box -\box_new:N \l__tblr_cell_box - -%% Build current row, #1: row number -%% To fix disappeared vlines with colorful tables in Adobe Reader (see #76), -%% we collect all vlines and draw them at the end of the row. -\cs_new_protected:Npn \__tblr_build_row:N #1 - { - \int_set:Nn \c@rownum {#1} - \__tblr_update_rowsep_registers: - \__tblr_get_row_inner_height_depth:VNNNN #1 - \l__tblr_row_ht_dim \l__tblr_row_dp_dim - \l__tblr_row_abovesep_dim \l__tblr_row_belowsep_dim - \vrule width ~ 0pt ~ height ~ \l__tblr_row_ht_dim ~ depth ~ \l__tblr_row_dp_dim - \hbox_set:Nn \l__tblr_row_vlines_box - { - \vrule width ~ 0pt ~ height ~ \l__tblr_row_ht_dim - ~ depth ~ \l__tblr_row_dp_dim - } - \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl - { - \__tblr_put_one_vline:n - { \__tblr_build_vline_segment:nn {#1} { \l__tblr_j_tl } } - \__tblr_put_one_cell:n { \__tblr_build_cell:NN #1 \l__tblr_j_tl } - } - \__tblr_put_one_vline:n - { \__tblr_build_vline_segment:nn {#1} { \int_eval:n {\c@colcount + 1} } } - \skip_horizontal:n { - \box_wd:N \l__tblr_row_vlines_box } - \box_use:N \l__tblr_row_vlines_box - } - -%% Read from table specifications and calculate inner height/depth of the row -%% inner height = abovesep + above vspace + row upper -%% inner depth = row lower + below vspace + belowsep -%% #1: the row number; #2: resulting inner height; #3: resulting inner depth; -%% #4: restulting abovesep; #5: restulting belowsep. - -\dim_new:N \l__row_upper_dim -\dim_new:N \l__row_lower_dim -\dim_new:N \l__row_vpace_dim - -\cs_new_protected:Npn \__tblr_get_row_inner_height_depth:nNNNN #1 #2 #3 #4 #5 - { - \dim_set:Nn #4 - { \__tblr_data_item:nen { row } {#1} { abovesep } } - \dim_set:Nn #5 - { \__tblr_data_item:nen { row } {#1} { belowsep } } - \dim_set:Nn \l__row_upper_dim - { \__tblr_data_item:nen { row } {#1} { @row-upper } } - \dim_set:Nn \l__row_lower_dim - { \__tblr_data_item:nen { row } {#1} { @row-lower } } - \dim_set:Nn \l__row_vpace_dim - { - ( \__tblr_data_item:nen { row } {#1} { @row-height } - - \l__row_upper_dim - \l__row_lower_dim ) / 2 - } - \dim_set:Nn #2 { #4 + \l__row_vpace_dim + \l__row_upper_dim } - \dim_set:Nn #3 { \l__row_lower_dim + \l__row_vpace_dim + #5 } - } -\cs_generate_variant:Nn \__tblr_get_row_inner_height_depth:nNNNN { V } - -\cs_new_protected:Npn \__tblr_put_one_vline:n #1 - { - \hbox_set:Nn \l__tblr_vline_box {#1} - \skip_horizontal:n { \box_wd:N \l__tblr_vline_box } - \hbox_set:Nn \l__tblr_row_vlines_box - { - \hbox_unpack:N \l__tblr_row_vlines_box - \box_use:N \l__tblr_vline_box - } - } - -\cs_new_protected:Npn \__tblr_put_one_cell:n #1 - { - \hbox_set:Nn \l__tblr_cell_box {#1} - \hbox_set:Nn \l__tblr_row_vlines_box - { - \hbox_unpack:N \l__tblr_row_vlines_box - \skip_horizontal:n { \box_wd:N \l__tblr_cell_box } - } - \box_use:N \l__tblr_cell_box - } - -%% #1: row number, #2: column number -\cs_new_protected:Npn \__tblr_build_vline_segment:nn #1 #2 - { - \tl_set:Nx \l__tblr_n_tl - { \__tblr_spec_item:ne { vline } { [#2] / @vline-count } } - \tl_set:Nx \l__tblr_o_tl - { \__tblr_spec_item:ne { vline } { [#1][#2] / omit } } - \tl_if_empty:NTF \l__tblr_o_tl - { - \int_compare:nNnT { \l__tblr_n_tl } > {0} - { \__tblr_build_vline_segment_real:nn {#1} {#2} } - } - { \__tblr_build_vline_segment_omit:nn {#1} {#2} } - } - -%% #1: row number, #2: column number -\cs_new_protected:Npn \__tblr_build_vline_segment_omit:nn #1 #2 - { - \tl_set:Nx \l__tblr_w_tl - { \__tblr_spec_item:ne { vline } { [#2] / @vline-width } } - \skip_horizontal:N \l__tblr_w_tl - } - -%% #1: row number, #2: column number -%% We make every vline segment intersect with first hline below -%% to remove gaps in vlines around multirow cells -\cs_new_protected:Npn \__tblr_build_vline_segment_real:nn #1 #2 - { - \tl_set:Nx \l__tblr_s_tl - { \__tblr_prop_item:ne { inner } { rulesep } } - \hbox_set:Nn \l__tblr_a_box - { - \int_step_inline:nn { \l__tblr_n_tl } - { - \tl_set:Nx \l__tblr_w_tl - { \__tblr_spec_item:ne { vline } { [#2](##1) / @vline-width } } - \vbox_set_to_ht:Nnn \l__tblr_b_box - { \dim_eval:n { \l__tblr_row_ht_dim + \l__tblr_row_dp_dim } } - { - \tl_set:Nx \l__tblr_f_tl - { \__tblr_spec_item:ne { vline } { [#1][#2](##1) / fg } } - \tl_if_empty:NF \l__tblr_f_tl { \color{\l__tblr_f_tl} } - \__tblr_get_vline_above_below_skips:nnn {#1} {#2} {##1} - \skip_vertical:N \l__tblr_vline_aboveskip_dim - \__tblr_get_vline_segment_child:nnnxx {#1} {#2} {##1} - { \dim_eval:n { \l__tblr_row_ht_dim } } - { \dim_eval:n { \l__tblr_row_dp_dim } } - \skip_vertical:N \l__tblr_vline_belowskip_dim - } - \box_set_wd:Nn \l__tblr_b_box { \l__tblr_w_tl } - \box_use:N \l__tblr_b_box - \skip_horizontal:n { \l__tblr_s_tl } - } - \skip_horizontal:n { - \l__tblr_s_tl } - } - \vbox_set:Nn \l__tblr_c_box { \box_use:N \l__tblr_a_box } - \box_set_ht:Nn \l__tblr_c_box { \dim_use:N \l__tblr_row_ht_dim } - \box_set_dp:Nn \l__tblr_c_box { \dim_use:N \l__tblr_row_dp_dim } - \box_use:N \l__tblr_c_box - } - -\dim_new:N \l__tblr_vline_aboveskip_dim -\dim_new:N \l__tblr_vline_belowskip_dim - -%% Calculate above and below skips from abovepos and belowpos specifications -%% #1: row number; #2: column number; #3: vline index; -\cs_new_protected:Npn \__tblr_get_vline_above_below_skips:nnn #1 #2 #3 - { - \tl_set:Nx \l__tblr_vline_abovepos_tl - { \__tblr_spec_item:ne { vline } { [#1][#2](#3) / abovepos } } - \tl_if_empty:NT \l__tblr_vline_abovepos_tl - { - \tl_set:Nn \l__tblr_vline_abovepos_tl {0} % default position - } - \tl_set:Nx \l__tblr_vline_belowpos_tl - { \__tblr_spec_item:ne { vline } { [#1][#2](#3) / belowpos } } - \tl_if_empty:NT \l__tblr_vline_belowpos_tl - { - \tl_set:Nn \l__tblr_vline_belowpos_tl {0} % default position - } - \fp_compare:nNnF { \l__tblr_vline_abovepos_tl } = {0} - { - \dim_set:Nn \l_tmpa_dim - { \__tblr_spec_item:ne { hline } { [#1] / @hline-height } } - \fp_compare:nNnTF { \l__tblr_vline_abovepos_tl } < {0} - { - \dim_set:Nn \l__tblr_vline_aboveskip_dim - { - \l__tblr_vline_abovepos_tl \l__tblr_row_abovesep_dim } - } - { - \dim_set:Nn \l__tblr_vline_aboveskip_dim - { - \l__tblr_vline_abovepos_tl \l_tmpa_dim } - } - } - %% To join two vline segment above and below a cline, - %% we choose to extend every vline downwards a little (#55). - \fp_compare:nNnTF { \l__tblr_vline_belowpos_tl } = {0} - { - \dim_set:Nn \l__tblr_vline_belowskip_dim - { - - \__tblr_spec_item:ne { hline } - { [\int_eval:n { #1 + 1 }](1) / @hline-height } - + 0pt - } - } - { - \dim_set:Nn \l_tmpa_dim - { - \__tblr_spec_item:ne { hline } - { [\int_eval:n { #1 + 1 }] / @hline-height } - } - \fp_compare:nNnTF { \l__tblr_vline_belowpos_tl } < {0} - { - \dim_set:Nn \l__tblr_vline_belowskip_dim - { - \l__tblr_vline_belowpos_tl \l__tblr_row_belowsep_dim } - } - { - \dim_set:Nn \l__tblr_vline_belowskip_dim - { - \l__tblr_vline_belowpos_tl \l_tmpa_dim } - } - } - } - -\tl_new:N \l__tblr_cell_rowspan_tl -\tl_new:N \l__tblr_cell_colspan_tl -\dim_new:N \l__tblr_cell_wd_dim -\dim_new:N \l__tblr_cell_ht_dim - -\cs_new_protected:Npn \__tblr_build_cell:NN #1 #2 - { - \int_set:Nn \c@colnum {#2} - \__tblr_update_colsep_registers: - \group_begin: - \tl_set:Nx \l__tblr_w_tl - { \__tblr_data_item:nen { column } {#2} { @col-width } } - \tl_set:Nx \l__tblr_h_tl - { \__tblr_data_item:nen { row } {#1} { @row-height } } - \tl_set:Nx \l__tblr_x_tl - { \__tblr_data_item:nen { column } {#2} { leftsep} } - \tl_set:Nx \l__tblr_y_tl - { \__tblr_data_item:nen { column } {#2} { rightsep } } - \tl_set:Nx \l__tblr_cell_colspan_tl - { \__tblr_data_item:neen { cell } {#1} {#2} { colspan } } - \int_compare:nNnTF { \l__tblr_cell_colspan_tl } < {2} - { \dim_set:Nn \l__tblr_cell_wd_dim { \l__tblr_w_tl } } - { - \__tblr_get_span_horizontal_sizes:NNNNN #1 #2 - \l__tblr_o_dim \l__tblr_cell_wd_dim \l__tblr_q_dim - } - \tl_set:Nx \l__tblr_cell_rowspan_tl - { \__tblr_data_item:neen { cell } {#1} {#2} { rowspan } } - \int_compare:nNnTF { \l__tblr_cell_rowspan_tl } < {2} - { \dim_set:Nn \l__tblr_cell_ht_dim { \l__tblr_h_tl } } - { - \__tblr_get_span_vertical_sizes:NNNNN #1 #2 - \l__tblr_r_dim \l__tblr_cell_ht_dim \l__tblr_t_dim - } - \__tblr_get_cell_alignments:nn {#1} {#2} - \__tblr_build_cell_background:NN #1 #2 - \__tblr_build_cell_content:NN #1 #2 - \group_end: - } - -\cs_new_protected:Npn \__tblr_build_cell_content:NN #1 #2 - { - \hbox_set_to_wd:Nnn \l__tblr_a_box { \l__tblr_cell_wd_dim } - { - \tl_if_eq:NnTF \g__tblr_cell_halign_tl {j} - { \__tblr_get_cell_text:nn {#1} {#2} } - { - \tl_if_eq:NnF \g__tblr_cell_halign_tl {l} { \hfil } - \__tblr_get_cell_text:nn {#1} {#2} - \tl_if_eq:NnF \g__tblr_cell_halign_tl {r} { \hfil } - } - } - \vbox_set_to_ht:Nnn \l__tblr_b_box { \l__tblr_cell_ht_dim } - { - \tl_case:Nn \g__tblr_cell_valign_tl - { - \c__tblr_valign_m_tl - { - \vfil - \int_compare:nNnT { \l__tblr_cell_rowspan_tl } < {2} - { - \box_set_ht:Nn \l__tblr_a_box - { \__tblr_data_item:nen { row } {#1} { @row-upper } } - \box_set_dp:Nn \l__tblr_a_box - { \__tblr_data_item:nen { row } {#1} { @row-lower } } - } - \box_use:N \l__tblr_a_box - \vfil - } - \c__tblr_valign_h_tl - { - \box_set_ht:Nn \l__tblr_a_box - { \__tblr_data_item:nen { row } {#1} { @row-head } } - \box_use:N \l__tblr_a_box - \vfil - } - \c__tblr_valign_f_tl - { - \vfil - \int_compare:nNnTF { \l__tblr_cell_rowspan_tl } < {2} - { - \box_set_dp:Nn \l__tblr_a_box - { \__tblr_data_item:nen { row } {#1} { @row-foot } } - } - { - \box_set_dp:Nn \l__tblr_a_box - { - \__tblr_data_item:nen - { row } - { \int_eval:n { #1 + \l__tblr_cell_rowspan_tl - 1 } } - { @row-foot } - } - } - \box_use:N \l__tblr_a_box - } - } - \hrule height ~ 0pt %% zero depth - } - \vbox_set_to_ht:Nnn \l__tblr_c_box - { \l__tblr_row_ht_dim - \l__tblr_row_abovesep_dim } - { - \box_use:N \l__tblr_b_box - \vss - } - \skip_horizontal:n { \l__tblr_x_tl } - \box_use:N \l__tblr_c_box - \skip_horizontal:n { \l__tblr_y_tl - \l__tblr_cell_wd_dim + \l__tblr_w_tl } - } - -\cs_new_protected:Npn \__tblr_build_cell_background:NN #1 #2 - { - \int_compare:nNnT { \__tblr_data_item:neen { cell } {#1} {#2} { omit } } = {0} - { - \group_begin: - \tl_set:Nx \l__tblr_b_tl - { \__tblr_data_item:neen { cell } {#1} {#2} { background } } - \tl_if_empty:NF \l__tblr_b_tl - { - \__tblr_get_cell_background_width:NNN #1 #2 \l_tmpa_dim - \__tblr_get_cell_background_depth:NNN #1 #2 \l_tmpb_dim - \__tblr_build_cell_background:nnnn - { \dim_use:N \l_tmpa_dim } - { \l__tblr_row_ht_dim } - { \dim_use:N \l_tmpb_dim } - { \l__tblr_b_tl } - } - \group_end: - } - } - -%% #1: row number; #2: column number; #3 resulting dimension -\cs_new_protected:Npn \__tblr_get_cell_background_width:NNN #1 #2 #3 - { - \int_compare:nNnTF { \l__tblr_cell_colspan_tl } < {2} - { \dim_set:Nn #3 { \l__tblr_x_tl + \l__tblr_w_tl + \l__tblr_y_tl } } - { - \dim_set:Nn #3 { \l__tblr_o_dim + \l__tblr_cell_wd_dim + \l__tblr_q_dim } - } - } - -%% #1: row number; #2: column number; #3 resulting dimension -\cs_new_protected:Npn \__tblr_get_cell_background_depth:NNN #1 #2 #3 - { - \int_compare:nNnTF { \l__tblr_cell_rowspan_tl } < {2} - { \dim_set_eq:NN #3 \l__tblr_row_dp_dim } - { - \dim_set:Nn #3 - { - \l__tblr_r_dim + \l__tblr_cell_ht_dim - + \l__tblr_t_dim - \l__tblr_row_ht_dim - } - } - } - -%% #1: width, #2: height, #3: depth, #4: color -\cs_new_protected:Npn \__tblr_build_cell_background:nnnn #1 #2 #3 #4 - { - \hbox_set:Nn \l__tblr_a_box - { - \color {#4} - \vrule width ~ #1 ~ height ~ #2 ~ depth ~ #3 - } - \box_set_dp:Nn \l__tblr_a_box { 0pt } - \box_use:N \l__tblr_a_box - \skip_horizontal:n { - #1 } - } - -%% #1: row number; #2: column number; #3: dimen register for rowsep above. -%% #4: dimen register for total height; #5: dimen register for rowsep below. -%% We can use \l__tblr_row_item_skip_size_prop which was made before -%% But when vspan=even, there are no itemskip in the prop list. -%% Therefore we need to calculate them from the sizes of items and skips -\cs_new_protected:Npn \__tblr_get_span_vertical_sizes:NNNNN #1 #2 #3 #4 #5 - { - \dim_set:Nn #3 - { \__tblr_data_item:nen { row } {#1} { abovesep } } - \dim_zero:N #4 - \dim_add:Nn #4 - { \prop_item:Ne \l__tblr_row_item_skip_size_prop { item[#1] } } - \int_step_inline:nnn { #1 + 1 } { #1 + \l__tblr_cell_rowspan_tl - 1 } - { - \dim_add:Nn #4 - { - \prop_item:Ne \l__tblr_row_item_skip_size_prop { skip[##1] } - + - \prop_item:Ne \l__tblr_row_item_skip_size_prop { item[##1] } - } - } - \dim_set:Nn #5 - { - \__tblr_data_item:nen { row } - { \int_eval:n { #1 + \l__tblr_cell_rowspan_tl - 1 } } { belowsep } - } - %\tl_log:x { cell[#1][#2] ~:~ \dim_use:N #3, \dim_use:N #4, \dim_use:N #5 } - } - -%% #1: row number; #2: column number; #3: dimen register for colsep left. -%% #4: dimen register for total width; #5: dimen register for colsep right. -%% We can use \l__tblr_col_item_skip_size_prop which was made before -%% But when hspan=even or hspan=minimal, there are no itemskip in the prop list. -%% Therefore we need to calculate them from the sizes of items and skips -\cs_new_protected:Npn \__tblr_get_span_horizontal_sizes:NNNNN #1 #2 #3 #4 #5 - { - \dim_set:Nn #3 - { \__tblr_data_item:nen { column } {#2} { leftsep } } - \dim_zero:N #4 - \dim_add:Nn #4 - { \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[#2] } } - \int_step_inline:nnn { #2 + 1 } { #2 + \l__tblr_cell_colspan_tl - 1 } - { - \dim_add:Nn #4 - { - \prop_item:Ne \l__tblr_col_item_skip_size_prop { skip[##1] } - + - \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[##1] } - } - } - \dim_set:Nn #5 - { - \__tblr_data_item:nen { column } - { \int_eval:n {#2 + \l__tblr_cell_colspan_tl - 1} } { rightsep } - } - %\tl_log:x { cell[#1][#2] ~:~ \dim_use:N #3, \dim_use:N #4, \dim_use:N #5 } - } - -%%% -------------------------------------------------------- -%% \section{Tracing Tabularray} -%%% -------------------------------------------------------- - -\NewDocumentCommand \SetTabularrayTracing { m } - { - \keys_set:nn { tblr-set-tracing } {#1} - } -\cs_new_eq:NN \SetTblrTracing \SetTabularrayTracing - -\bool_new:N \g__tblr_tracing_text_bool -\bool_new:N \g__tblr_tracing_command_bool -\bool_new:N \g__tblr_tracing_option_bool -\bool_new:N \g__tblr_tracing_theme_bool -\bool_new:N \g__tblr_tracing_outer_bool -\bool_new:N \g__tblr_tracing_inner_bool -\bool_new:N \g__tblr_tracing_column_bool -\bool_new:N \g__tblr_tracing_row_bool -\bool_new:N \g__tblr_tracing_cell_bool -\bool_new:N \g__tblr_tracing_vline_bool -\bool_new:N \g__tblr_tracing_hline_bool -\bool_new:N \g__tblr_tracing_colspec_bool -\bool_new:N \g__tblr_tracing_rowspec_bool -\bool_new:N \g__tblr_tracing_target_bool -\bool_new:N \g__tblr_tracing_cellspan_bool -\bool_new:N \g__tblr_tracing_intarray_bool -\bool_new:N \g__tblr_tracing_page_bool -\bool_new:N \g__tblr_tracing_step_bool - -\bool_gset_true:N \g__tblr_tracing_step_bool - -\keys_define:nn { tblr-set-tracing } - { - +text .code:n = \bool_gset_true:N \g__tblr_tracing_text_bool, - -text .code:n = \bool_gset_false:N \g__tblr_tracing_text_bool, - +command .code:n = \bool_gset_true:N \g__tblr_tracing_command_bool, - -command .code:n = \bool_gset_false:N \g__tblr_tracing_command_bool, - +option .code:n = \bool_gset_true:N \g__tblr_tracing_option_bool, - -option .code:n = \bool_gset_false:N \g__tblr_tracing_option_bool, - +theme .code:n = \bool_gset_true:N \g__tblr_tracing_theme_bool, - -theme .code:n = \bool_gset_false:N \g__tblr_tracing_theme_bool, - +outer .code:n = \bool_gset_true:N \g__tblr_tracing_outer_bool, - -outer .code:n = \bool_gset_false:N \g__tblr_tracing_outer_bool, - +inner .code:n = \bool_gset_true:N \g__tblr_tracing_inner_bool, - -inner .code:n = \bool_gset_false:N \g__tblr_tracing_inner_bool, - +column .code:n = \bool_gset_true:N \g__tblr_tracing_column_bool, - -column .code:n = \bool_gset_false:N \g__tblr_tracing_column_bool, - +row .code:n = \bool_gset_true:N \g__tblr_tracing_row_bool, - -row .code:n = \bool_gset_false:N \g__tblr_tracing_row_bool, - +cell .code:n = \bool_gset_true:N \g__tblr_tracing_cell_bool, - -cell .code:n = \bool_gset_false:N \g__tblr_tracing_cell_bool, - +vline .code:n = \bool_gset_true:N \g__tblr_tracing_vline_bool, - -vline .code:n = \bool_gset_false:N \g__tblr_tracing_vline_bool, - +hline .code:n = \bool_gset_true:N \g__tblr_tracing_hline_bool, - -hline .code:n = \bool_gset_false:N \g__tblr_tracing_hline_bool, - +colspec .code:n = \bool_gset_true:N \g__tblr_tracing_colspec_bool, - -colspec .code:n = \bool_gset_false:N \g__tblr_tracing_colspec_bool, - +rowspec .code:n = \bool_gset_true:N \g__tblr_tracing_rowspec_bool, - -rowspec .code:n = \bool_gset_false:N \g__tblr_tracing_rowspec_bool, - +target .code:n = \bool_gset_true:N \g__tblr_tracing_target_bool, - -target .code:n = \bool_gset_false:N \g__tblr_tracing_target_bool, - +cellspan .code:n = \bool_gset_true:N \g__tblr_tracing_cellspan_bool, - -cellspan .code:n = \bool_gset_false:N \g__tblr_tracing_cellspan_bool, - +intarray .code:n = \bool_gset_true:N \g__tblr_tracing_intarray_bool, - -intarray .code:n = \bool_gset_false:N \g__tblr_tracing_intarray_bool, - +page .code:n = \bool_gset_true:N \g__tblr_tracing_page_bool, - -page .code:n = \bool_gset_false:N \g__tblr_tracing_page_bool, - +step .code:n = \bool_gset_true:N \g__tblr_tracing_step_bool, - -step .code:n = \bool_gset_false:N \g__tblr_tracing_step_bool, - all .code:n = \__tblr_enable_all_tracings:, - none .code:n = \__tblr_disable_all_tracings:, - } - -\cs_new_protected_nopar:Npn \__tblr_enable_all_tracings: - { - \bool_gset_true:N \g__tblr_tracing_text_bool - \bool_gset_true:N \g__tblr_tracing_command_bool - \bool_gset_true:N \g__tblr_tracing_option_bool - \bool_gset_true:N \g__tblr_tracing_theme_bool - \bool_gset_true:N \g__tblr_tracing_outer_bool - \bool_gset_true:N \g__tblr_tracing_inner_bool - \bool_gset_true:N \g__tblr_tracing_column_bool - \bool_gset_true:N \g__tblr_tracing_row_bool - \bool_gset_true:N \g__tblr_tracing_cell_bool - \bool_gset_true:N \g__tblr_tracing_vline_bool - \bool_gset_true:N \g__tblr_tracing_hline_bool - \bool_gset_true:N \g__tblr_tracing_colspec_bool - \bool_gset_true:N \g__tblr_tracing_rowspec_bool - \bool_gset_true:N \g__tblr_tracing_target_bool - \bool_gset_true:N \g__tblr_tracing_cellspan_bool - \bool_gset_true:N \g__tblr_tracing_intarray_bool - \bool_gset_true:N \g__tblr_tracing_page_bool - \bool_gset_true:N \g__tblr_tracing_step_bool - } - -\cs_new_protected_nopar:Npn \__tblr_disable_all_tracings: - { - \bool_gset_false:N \g__tblr_tracing_text_bool - \bool_gset_false:N \g__tblr_tracing_command_bool - \bool_gset_false:N \g__tblr_tracing_option_bool - \bool_gset_false:N \g__tblr_tracing_theme_bool - \bool_gset_false:N \g__tblr_tracing_outer_bool - \bool_gset_false:N \g__tblr_tracing_inner_bool - \bool_gset_false:N \g__tblr_tracing_column_bool - \bool_gset_false:N \g__tblr_tracing_row_bool - \bool_gset_false:N \g__tblr_tracing_cell_bool - \bool_gset_false:N \g__tblr_tracing_vline_bool - \bool_gset_false:N \g__tblr_tracing_hline_bool - \bool_gset_false:N \g__tblr_tracing_colspec_bool - \bool_gset_false:N \g__tblr_tracing_rowspec_bool - \bool_gset_false:N \g__tblr_tracing_target_bool - \bool_gset_false:N \g__tblr_tracing_cellspan_bool - \bool_gset_false:N \g__tblr_tracing_intarray_bool - \bool_gset_false:N \g__tblr_tracing_page_bool - \bool_gset_false:N \g__tblr_tracing_step_bool - } - -\NewDocumentCommand \LogTabularrayTracing { m } - { - \keys_set:nn { tblr-log-tracing } {#1} - } -\cs_new_eq:NN \LogTblrTracing \LogTabularrayTracing - -\keys_define:nn { tblr-log-tracing } - { - step .code:n = \__tblr_log_tracing_step:n {#1}, - unknown .code:n = \__tblr_log_tracing:N \l_keys_key_str - } - -\cs_new_protected:Npn \__tblr_log_tracing:N #1 - { - \bool_if:cT { g__tblr_tracing_ #1 _bool } - { \cs:w __tblr_log_tracing _ #1 : \cs_end: } - } - -\cs_new_protected:Npn \__tblr_log_tracing_text: - { - \__tblr_spec_log:n { text } - } - -\cs_new_protected:Npn \__tblr_log_tracing_command: - { - \__tblr_prop_log:n { command } - } - -\cs_new_protected:Npn \__tblr_log_tracing_option: - { - \__tblr_prop_log:n { note } - \__tblr_prop_log:n { remark } - \__tblr_prop_log:n { more } - } - -\cs_new_protected:Npn \__tblr_log_tracing_theme: - { - \__tblr_style_log: - } - -\cs_new_protected:Npn \__tblr_log_tracing_outer: - { - \__tblr_spec_log:n { outer } - } - -\cs_new_protected:Npn \__tblr_log_tracing_inner: - { - \__tblr_prop_log:n { inner } - } - -\cs_new_protected:Npn \__tblr_log_tracing_column: - { - \__tblr_data_log:n { column } - } - -\cs_new_protected:Npn \__tblr_log_tracing_row: - { - \__tblr_data_log:n { row } - } - -\cs_new_protected:Npn \__tblr_log_tracing_cell: - { - \__tblr_data_log:n { cell } - } - -\cs_new_protected:Npn \__tblr_log_tracing_vline: - { - \__tblr_spec_log:n { vline } - } - -\cs_new_protected:Npn \__tblr_log_tracing_hline: - { - \__tblr_spec_log:n { hline } - } - -\cs_new_protected:Npn \__tblr_log_tracing_colspec: - { - \tl_if_eq:NnT \g__tblr_column_or_row_tl { column } - { \tl_log:N \g__tblr_expanded_colrow_spec_tl } - } - -\cs_new_protected:Npn \__tblr_log_tracing_rowspec: - { - \tl_if_eq:NnT \g__tblr_column_or_row_tl { row } - { \tl_log:N \g__tblr_expanded_colrow_spec_tl } - } - -\cs_new_protected:Npn \__tblr_log_tracing_target: - { - \dim_log:N \l__column_target_dim - \prop_log:N \l__column_coefficient_prop - \prop_log:N \l__column_natural_width_prop - \prop_log:N \l__column_computed_width_prop - } - -\cs_new_protected:Npn \__tblr_log_tracing_cellspan: - { - \prop_log:N \l__tblr_col_item_skip_size_prop - \prop_log:N \l__tblr_col_span_size_prop - \prop_log:N \l__tblr_row_item_skip_size_prop - \prop_log:N \l__tblr_row_span_size_prop - \prop_log:N \l__tblr_row_span_to_row_prop - } - -\cs_new_protected:Npn \__tblr_log_tracing_page: - { - \dim_log:N \pagegoal - \dim_log:N \pagetotal - } - -\cs_new_protected:Npn \__tblr_log_tracing_step:n #1 - { - \bool_if:NT \g__tblr_tracing_step_bool { \tl_log:x {Step :~ #1} } - } - -\cs_new_protected:Npn \__tblr_do_if_tracing:nn #1 #2 - { - \bool_if:cT { g__tblr_tracing_ #1 _bool } {#2} - } - -%%% -------------------------------------------------------- -%% \section{Tabularray Libraries} -%%% -------------------------------------------------------- - -%% \NewTblrLibrary and \UseTblrLibrary commands - -\NewDocumentCommand \NewTblrLibrary { m m } - { - \cs_new_protected:cpn { __tblr_use_lib_ #1: } {#2} - } - -\NewDocumentCommand \UseTblrLibrary { m } - { - \clist_map_inline:nn {#1} { \use:c { __tblr_use_lib_ ##1: } } - } - -%% Library amsmath and environments +array, +matrix, +cases, ... - -\NewTblrLibrary { amsmath } - { - \RequirePackage { amsmath, environ } - \NewTblrEnviron { +array } - \SetTblrInner[+array]{colsep = 5pt} - \NewEnviron { +matrix } [1] [] { - \begin{+array}[expand = \BODY]{ - column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt}, - cells = {c}, ##1 - } - \BODY - \end{+array} - } - \NewEnviron { +bmatrix } [1] [] { - \left[\begin{+array}[expand = \BODY]{ - column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt}, - cells = {c}, ##1 - } - \BODY - \end{+array}\right] - \ignorespacesafterend - } - \NewEnviron { +Bmatrix } [1] [] { - \left\lbrace\begin{+array}[expand = \BODY]{ - column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt}, - cells = {c}, ##1 - } - \BODY - \end{+array}\right\rbrace - } - \NewEnviron { +pmatrix } [1] [] { - \left(\begin{+array}[expand = \BODY]{ - column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt}, - cells = {c}, ##1 - } - \BODY - \end{+array}\right) - } - \NewEnviron { +vmatrix } [1] [] { - \left\lvert\begin{+array}[expand = \BODY]{ - column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt}, - cells = {c}, ##1 - } - \BODY - \end{+array}\right\rvert - } - \NewEnviron { +Vmatrix } [1] [] { - \left\lVert\begin{+array}[expand = \BODY]{ - column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt}, - cells = {c}, ##1 - } - \BODY - \end{+array}\right\rVert - } - \NewEnviron { +cases } [1] [] { - \left\lbrace\begin{+array}[expand = \BODY]{ - column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt}, - colspec = {ll}, stretch = 1.2, ##1 - } - \BODY - \end{+array}\right. - } - } - -%% Library booktabs and commands \toprule, \midrule, \bottomrule - -\NewTblrLibrary { booktabs } - { - % We only use dimensions \aboverulesep and \belowrulesep in booktabs package - \RequirePackage { booktabs } - \newcommand \tblr@booktabs@hline [1] [] { \hline [##1] } - \newcommand \tblr@booktabs@oldhline [1] [] { - \hline [abovespace = \aboverulesep, belowspace = \belowrulesep, ##1] - } - \newcommand \tblr@booktabs@cline [2] [] { \cline [##1] {##2} } - \newcommand \tblr@booktabs@oldcline [2] [] { - \cline [abovespace = \aboverulesep, belowspace = \belowrulesep, ##1] {##2} - } - \newcommand \tblr@booktabs@cline@more [2] [] { \SetHline [+] {##2} {##1} } - \newcommand \tblr@booktabs@oldcline@more [2] [] { - \SetHline [+] {##2} { - abovespace = \aboverulesep, belowspace = \belowrulesep, ##1 - } - } - \NewTableCommand \toprule [1] [] { - \tblr@booktabs@hline [wd=\heavyrulewidth, ##1] - } - \NewTableCommand \midrule [1] [] { - \tblr@booktabs@hline [wd=\lightrulewidth, ##1] - } - \NewTableCommand \bottomrule [1] [] { - \tblr@booktabs@hline [wd=\heavyrulewidth, ##1] - } - \NewTableCommand \cmidrule [2] [] { - \tblr@booktabs@cline [wd=\cmidrulewidth, endpos, ##1] {##2} - } - \NewTableCommand \cmidrulemore [2] [] { - \tblr@booktabs@cline@more [wd=\cmidrulewidth, endpos, ##1] {##2} - } - \newcommand \tblr@booktabs@change@more [1] { \cmidrulemore } - \NewTableCommand \morecmidrules { - \peek_meaning:NTF \cmidrule { \tblr@booktabs@change@more } { \relax } - } - \NewTblrEnviron { booktabs } - \SetTblrInner [ booktabs ] { rowsep = 0pt } - \RequirePackage { etoolbox } - \AtBeginEnvironment { booktabs } - { - \let \tblr@booktabs@hline = \tblr@booktabs@oldhline - \let \tblr@booktabs@cline = \tblr@booktabs@oldcline - \let \tblr@booktabs@cline@more = \tblr@booktabs@oldcline@more - } - \NewTableCommand \specialrule [3] - { \hline [##1, abovespace = ##2, belowspace = ##3] } - \NewTableCommand \addrowspace [1] [\defaultaddspace] - { \SetVspace { abovespace+ = (##1) / 2, belowspace+ = (##1) / 2 } } - \NewTableCommand \addlinespace [1] [\defaultaddspace] - { \SetVspace { abovespace+ = (##1) / 2, belowspace+ = (##1) / 2 } } - } - -%% Library counter for resetting all counters - -\tl_new:N \__tblr_saved_trial_counters_tl -\tl_new:N \__tblr_saved_cell_counters_tl - -\cs_new_protected:Npn \__tblr_save_counters:n #1 { } -\cs_new_protected:Npn \__tblr_restore_counters:n #1 { } - -%% We use code from tabularx package for resetting all LaTeX counters, -%% where internal macro \cl@@ckpt looks like the following: -%% \@elt{page} \@elt{equation} \@elt{enumi} \@elt{enumii} \@elt{enumiii} ... - -\NewTblrLibrary { counter } - { - \cs_set_protected:Npn \__tblr_save_counters:n ##1 - { - \def \@elt ####1 { \global\value{####1} = \the\value{####1} \relax } - \tl_set:cx { __tblr_saved_ ##1 _counters_tl } { \cl@@ckpt } - \let \@elt = \relax - } - \cs_set_protected:Npn \__tblr_restore_counters:n ##1 - { - \tl_use:c { __tblr_saved_ ##1 _counters_tl } - } - } - -%% Library diagbox and command \diagbox - -\NewTblrLibrary { diagbox } - { - \RequirePackage{ diagbox } - \cs_set_eq:NN \__tblr_lib_saved_diagbox:w \diagbox - \NewContentCommand \diagbox [3] [] - { - \__tblr_lib_diagbox_fix:n - { - \__tblr_lib_saved_diagbox:w - [ leftsep=\leftsep, rightsep=\rightsep, ##1 ] - { \__tblr_lib_diagbox_math_or_text:n {##2} } - { \__tblr_lib_diagbox_math_or_text:n {##3} } - } - } - \NewContentCommand \diagboxthree [4] [] - { - \__tblr_lib_diagbox_fix:n - { - \__tblr_lib_saved_diagbox:w - [ leftsep=\leftsep, rightsep=\rightsep, ##1 ] - { \__tblr_lib_diagbox_math_or_text:n {##2} } - { \__tblr_lib_diagbox_math_or_text:n {##3} } - { \__tblr_lib_diagbox_math_or_text:n {##4} } - } - } - } - -\cs_new_protected:Npn \__tblr_lib_diagbox_math_or_text:n #1 - { - \bool_if:NTF \l__tblr_cell_math_mode_bool {$#1$} {#1} - } - -\box_new:N \l__tblr_diag_box - -\cs_new_protected:Npn \__tblr_lib_diagbox_fix:n #1 - { - \hbox_set:Nn \l__tblr_diag_box {#1} - \box_set_ht:Nn \l__tblr_diag_box { \box_ht:N \l__tblr_diag_box - \abovesep } - \box_set_dp:Nn \l__tblr_diag_box { \box_dp:N \l__tblr_diag_box - \belowsep } - \box_use:N \l__tblr_diag_box - } - -%% Library siunitx and S columns - -\NewTblrLibrary { siunitx } - { - \RequirePackage { siunitx } - \NewColumnType { S } [1] [] { Q[si = {##1}, c] } - \NewColumnType { s } [1] [] { Q[si = {##1}, c, cmd = \TblrUnit] } - \__tblr_data_new_key:nnn { cell } { si } { str } - \keys_define:nn { tblr-column } - { - si .code:n = \__tblr_siunitx_setcolumn:n {##1} - } - \cs_new_protected:Npn \__tblr_siunitx_setcolumn:n ##1 - { - \__tblr_column_gput_cell:nn { si } {##1} - \__tblr_column_gput_cell:nn { cmd } { \TblrNum } - } - \NewDocumentCommand \TblrNum { m } - { - \__tblr_siunitx_process:Nn \tablenum {##1} - } - \NewDocumentCommand \TblrUnit { m } - { - \__tblr_siunitx_process:Nn \si {##1} - } - \cs_new_protected:Npn \__tblr_siunitx_process:Nn ##1 ##2 - { - \tl_if_head_is_group:nTF {##2} - { ##2 } - { - \group_begin: - \tl_set:Nx \l_tmpa_tl - { - \__tblr_data_item:neen { cell } - { \int_use:N \c@rownum } { \int_use:N \c@colnum } { si } - } - \exp_args:NV \sisetup \l_tmpa_tl - ##1 {##2} - \group_end: - } - } - } - -%% Library varwidth and measure option - -\NewTblrLibrary { varwidth } - { - \RequirePackage { varwidth } - \clist_gput_left:Nn \g__tblr_table_known_keys_clist { measure } - \keys_define:nn { tblr } { measure .tl_set:N = \l__tblr_inner_spec_measure_tl } - } -