这三个命令在文档中说的是可以用在处理键的代码中,在其它地方使用显然是未定义行为。包括那些 undocumented 命令,都由使用者自己负责。
这三个命令在文档中说的是可以用在处理键的代码中,在其它地方使用显然是未定义行为。包括那些 undocumented 命令,都由使用者自己负责。
首先,context 没有你给的那些命令行参数。
其次,TeXLive 2025 的 ConTeXt 默认用的是 LuaMetaTeX,它不带 kpathsea 库,所有的第三方模块都必须手动安装(包括 tikz、pgfplots 等),否则就会找不到相关文件,用 LuaTeX 的版本才行。因为我没有 TeX Studio,不知道你是如何成功编译的。不过你可以查看输出的 PDF 文件,看看究竟是哪个版本。
最后,LaTeX Workshop 需要找到主文件(即 root file,见 https://github.com/James-Yu/LaTeX-Workshop/wiki/Compile#the-root-file),主要是找到 \documentclass
这个命令,这在 ConTeXt 中是没有的。
只要解决上面这三个问题就行了。
修改 setting.json
:
{
"latex-workshop.latex.tools": [
{
"name": "context-luatex",
"command": "context",
"args": [
"--synctex",
"--nonstopmode",
"--luatex",
"%DOC%"
],
"env": {}
},
],
"latex-workshop.latex.recipes": [
{
"name": "context (luatex)",
"tools": [
"context-luatex"
]
},
]
}
然后用 magic comment 设置主文件(注意第一行):
% !TEX root = main.tex
%命令行编译: context --luatex main
\usemodule[tikz]
\startTEXpage[offset=2pt]
\def\mygrid#1{
\fill [gray!60] (0,0) rectangle (#1,#1);
\draw [white,thick] (0,0) grid (#1,#1);
\foreach \x in {1,...,#1}
{
\node at (0,\x) [left] {$\x$};
\node at (\x,0) [below] {$\x$};
}
\node at (0,0) [below left] {$0$};
}
\starttikzpicture[every node/.append style={scale=.5}]
\mygrid{3}
\stoptikzpicture
\CONTEXT{} -- \LUATEX
\stopTEXpage
然后点击 context (luatex)
即可。
可能是 xetex 的驱动文件有问题。asymptote 支持输出为 PDF,用 PDF 文件就好了。
case 1 是可以正常输出的,需要指定 \usepackage[encoding=gbk]{zhlipsum}
。
%%% 文件编码为 GBK!
\documentclass[GBK]{ctexart}
\usepackage{lipsum}
\usepackage[encoding=gbk]{zhlipsum}
\begin{document}
现代社会以海德格尔的一句“一切实践传统都已经瓦解完了”为嚆矢。滥觞于家庭与社会传统的期望正失去它们的借鉴意义。
但面对看似无垠的未来天空,我想循卡尔维诺“树上的男爵”的生活好过过早地振翮。我们怀揣热忱的灵魂天然被赋予对超越性的追求,不屑于古旧坐标的约束,钟情于在别处的芬芳。
\lipsum[1]
\zhlipsum[1]
\end{document}
case 2、3、4 都是同一个问题,TeX 不能正确解码 GBK 编码或 UTF8 编码的 bytes 为 Unicode Scalar Value。
可分别观察如下 python 代码的结果:
>>> b'\xd2\xbb'.decode('utf8')
'һ' ### 看看 case 3 的错误日志
>>> b'\xd2\xbb'.decode('gbk')
'一'
>>> '\ufffd\ufffd'.encode('utf8')
b'\xef\xbf\xbd\xef\xbf\xbd'
>>> '\ufffd\ufffd'.encode('utf8').decode('gbk')
'锟斤拷'
同一段 bytes 以不同的方式解码得到的是不同的 Unicode Scalar Value。如果一段 bytes 可以以 GBK 解码但不能以 UTF8 解码,就会得到错误,反之亦然。如果可以以两种方式解码,那看到的 Unicode Scalar Value 也大概率不是一样的,ASCII 除外。
TeX 看到的总是 bytes,人看到的是 Unicode Scalar Value,如果字体里没有某些 Unicode Scalar Value 的字形,就不能在 PDF 中显示。
对于 case 2,由于 zhlipsum
分别制作了 gbk 和 utf8 两个文件用来保存假文,所以,在这些文件中,文件的编码和 bytes 是匹配的,并且在 case 2 中,总是使用 utf8 这个文件,TeX 也总以 utf8 解码,所以不论 main 文件编码为何,TeX 总能读出假文正确的 Unicode Scalar Value。而 main 文件由于文件编码和解码方式不同,TeX 不能正确读取(解码)。
现在如果有 GBK 编码的 TeX 文件,最好的办法应该是统一转为 UTF8 编码,然后使用 CTeX-kit 默认的编码方式。
实际上是中间的行号比前两行和最后一行更靠近右侧一点。这应该是 algorithm2e
的 bug。
在导言区重定义 \algocf@Vline
\algocf@Vsline
即可。
\documentclass{ctexart}
\usepackage{amsmath,amssymb}
\usepackage[linesnumbered,lined,ruled,noend]{algorithm2e}
\SetArgSty{textrm}
\SetAlgorithmName{算法}{算法}{算法目录}
\makeatletter
\@ifpackagelater{algorithm2e}{2017/07/19}{}{% current version 2017/07/18
%%%%%%%%% block with a vertical line end by a little horizontal line
\renewcommand{\algocf@Vline}[1]{% no vskip in between boxes but a strut to separate them,
\strut\par\nointerlineskip% then interblock space stay the same whatever is inside it
\algocf@push{\skiprule}% move to the right before the vertical rule
\hbox{\kern-.4pt\vrule% %% <- add \kern
\vtop{\algocf@push{\skiptext}%move the right after the rule
\vtop{\algocf@addskiptotal #1}\Hlne}}\vskip\skiphlne% inside the block
\algocf@pop{\skiprule}%\algocf@subskiptotal% restore indentation
\nointerlineskip}% no vskip after
%
%%%%%%%%% block with a vertical line
\renewcommand{\algocf@Vsline}[1]{% no vskip in between boxes but a strut to separate them,
\strut\par\nointerlineskip% then interblock space stay the same whatever is inside it
\algocf@bblockcode%
\algocf@push{\skiprule}% move to the right before the vertical rule
\hbox{\kern-.4pt\vrule% the vertical rule %% <- add \kern
\vtop{\algocf@push{\skiptext}%move the right after the rule
\vtop{\algocf@addskiptotal #1}}}% inside the block
\algocf@pop{\skiprule}% restore indentation
\algocf@eblockcode%
}
}
\makeatother
\begin{document}
\begin{algorithm}
\small
\KwIn{数据图$G=(V_G, E_G)$, 整数参数$K$, 以及查询顶点$v_q$ }
\KwOut{对应的包含$v_q$的$K$-truss社区集合}
visited= $\varnothing$, $l = 0$ \label{code:truss-search:init}
\For{$v_q$的每一个邻居$u$}
{
\If{边$(v_q,u)$的{\rm truss}不小于$k$且并未访问过}
{
visited = visited$\cup \{(v_q, u)\}$\;
$l {++}$\;
$C_l=\varnothing, Q=\varnothing$ \;
$Q$.push$(v_q, u)$\;
\While{$Q \neq \varnothing$}
{
$(x,y) = Q.$pop()\;
$C_l.$push$((x,y))$\;
\For{$z\in N(x)\cap N(y)$}
{
\If{$(x,z)$和$(y,z)$的{\rm truss}值均不小于$K$}
{
\If{$(x,z)$未访问过}
{
$Q.$push$((x,z))$\;
visited = visited $\cup \{(x,z)\}$
}
\If{$(y,z)$未访问过}
{
$Q$.push$((y,z))$\;
visited = visited $\cup \{(y,z)\}$
}
}
}
}
}
}
Return \{$C_1$, $\cdots$, $C_l$\}
\caption{$K$-truss社区搜索在线查询算法}
\label{alg:truss:search:online}
\end{algorithm}
\end{document}
TeXLive 查找 opentype 字体文件的路径是可以配置的。在 Windows 系统中默认只有 c:\WINDOWS\fonts
和 TeXLive 自带的那些 opentype 字体。
LuaTeX 使用 luaotfload 查找 opentype 字体,而它使用 kpathsea 查找字体文件,直接编辑 kpsewhich.exe texmf.cnf
输出的那个文件,加上
% TrueType outline fonts.
TTFONTS = $TEXMFDOTDIR;$TEXMF/fonts/{truetype,opentype}//;$OSFONTDIR//;C:/your/fonts/dir//
% OpenType outline fonts.
OPENTYPEFONTS = $TEXMFDOTDIR;$TEXMF/fonts/{opentype,truetype}//;$OSFONTDIR//;C:/your/fonts/dir//
每项用英文分号分隔,前面三项如果不知道是什么含义就不要修改。这是跨平台的。
XeTeX 在 Windows 和 Linux 平台使用 fontfonfig,(除非你使用 xetex-specimen)。
在 Linux 平台,根据 fontconfig 文档的说明改动即可。
在 Windows 平台,编辑 kpsewhich.exe --var-value XE_FONTCONFIG_PATH
输出的那个文件夹下的 conf.d/51-local.conf
,改为
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<dir>D:/your/fonts/dir1</dir>
<dir>D:/your/fonts/dir2</dir>
... 其它东西,不要改动
</fontconfig>
如果要修改,建议同时修改这两处。
修改完成后,再依次执行 texhash
和 fc-cache -fv
。
1.这是因为扩展 H 区直到 2022 年 9 月的 Unicode 15 才引入,xeCJK
还没有更新到这个版本。
自己设置一下就好了。
\documentclass{ctexbook}
\xeCJKsetup{AutoFallBack=true}
\xeCJKDeclareCharClass{CJK}{"2EBF0->"2EE5F, "31350->"323AF} % Ext-I, Ext-H
\setCJKmainfont{SimSun}
\setCJKfallbackfamilyfont{\CJKrmdefault}{
{[AutoFakeBold,AutoFakeSlant]{SimSun-ExtB}},
{[AutoFakeBold,AutoFakeSlant]{SimSun-ExtG}},
}
\begin{document}
你好,world!
“𠳹”、“𤠠”、“𬬺”、“𱠧”、“𤝽”。
\end{document}
xeCJK
还支持为不同的字符区间设置不同的 CJK 字体,见 \xeCJKDeclareSubCJKBlock
的说明。
2.比较完善的策略是使用大而全的字库,或者为不同的字符区间设置不同的字体,然而这总是有时效的,因为 Unicode 没有收录“所有汉字”,每个版本都有可能添加新的 CJK 字符。
这类问题总是可以通过把必要的信息写入到辅助文件中解决。
\documentclass{article}
\usepackage[many]{tcolorbox}
\newcounter{problem}
\newcounter{solution}
\makeatletter
\protected\def\solutionwriteaux{\immediate\write\@auxout{%
\global\string\@namedef
{solution@count@of-\number\value{problem}}{\number\value{solution}}}}
\def\solutionmaxcount{\@ifundefined{solution@count@of-\number\value{problem}}
{1}{\@nameuse{solution@count@of-\number\value{problem}}}}
\def\thesolutionornone#1{\ifnum\number\solutionmaxcount>\@ne #1\thesolution\fi} % #1: sep
\makeatletter
\newcommand*{\Problem}[1]{%
\setcounter{solution}{0}
\refstepcounter{problem}%
\begin{tcolorbox}[enhanced,title={\bfseries Problem~\theproblem},colframe=magenta!80!white,colback=magenta!20!white]
#1
\end{tcolorbox}
}
\newcommand*{\Solution}[1]{%
\refstepcounter{solution}%
\solutionwriteaux % <- 这里写入辅助文件
\begin{tcolorbox}[enhanced,
title={\bfseries Solution~\theproblem \thesolutionornone{-}}, % <- 检查是否多于一个
colframe=cyan!80!white,colback=cyan!20!white]
#1
\end{tcolorbox}
}
\begin{document}
\Problem{This is the problem statement.}
\Solution{This is the first solution of the problem}
xi
\Problem{This is another problem but two solution multiple line.}
\Solution{This is the second solution.}
\Solution{This is the second solution.}
\Problem{This is another problem balabalabala}
\Solution{This is the only solution}
\Problem{This is another problem balabalabala}
\end{document}
这同时需要 PDF 文件具有某些特殊标记(即 “Tagged”),以及特定的阅读器的支持才能实现。
在 LaTeX 端,由 tagpdf
宏包提供支持,可参考它的文档了解用法,不过它目前还处于实验性的阶段,而且对 XeTeX 的支持不太好。近些年的 LaTeX 大版本更新都提到了 “LaTeX Tagged PDF” 这个项目,就是用来干这个事情的。
经过我的测试,目前(在 Windows 平台)只有 Adobe Acrobat DC(Adobe 的其它阅读器也可能支持)、Drawboard PDF(据我所知,它使用 PDFKit 库,所以,任何使用这个库的阅读器应该也支持,没有测试)支持这个功能,包括 SumatraPDF、福昕 PDF 阅读器等在内的都不支持。可以用某个阅读器打开前面提到的 tagpdf.pdf 这个文件,然后随意复制一段文字用来测试是否支持这个功能。
默认情况下,LaTeX 的目录由 l@<title>
输出,<title>
就是 chapter
section
这些,其中 part
chapter
section
都定义了自己的 l@..
,而 subsection
及其子标题都使用 \@dottedtocline
,区别是设置不同的参数。查看 mcmthesis 2024/01/22 v6.3.3
源码发现,它并没有修改这一行为。
因此只需在导言区加上
\makeatletter
\@namedef{@level1@space}{10pt} % section
\@namedef{@level2@space}{10pt} % subsection
\@namedef{@level3@space}{0pt} % subsubsection
\long\def\sectionvspace#1{\addvspace{\@nameuse{@level1@space}}}
\patchcmd\l@section{\addvspace}{\sectionvspace}{}{\ERR} % section
\long\def\dottedvspace#1#2#{\nointerlineskip \vskip-\parskip \vskip\@nameuse{@level#1@space}\relax}
\patchcmd\@dottedtocline{\vskip}{\dottedvspace{#1}}{}{\ERR} % subsection
\makeatother
浮动体的位置直到 output routine 时才会确定,(浮动的)浮动环境只是把它的内容保存到盒子里,此时,LaTeX 默认的实现是不会保存当前设置的各种间距的,这些间距直到 output routine 时才会使用,因此,局部设置地设置这些间距一般都无效。既然说了是 LaTeX 的默认实现,那自然可以自定义,不过,麻烦、工作量大、与其它宏包兼容性不好(比如涉及到 output routine 的 longtable
multicol
paracol
lineno
,还有和浮动体有关的宏包 caption
float
placeins
newfloat
,等等),而且 LaTeX 也没有提供方便的方法修改 output routine 以及排布浮动体的算法。
很多时候并不需要让内容浮动,只需要一个 center
环境、一个和浮动体共享计数器的命令(直接 \let\c@myfigure\c@figure
,就能够让 myfigure
和 figure
共享计数器了,不过这样并不共享格式),以及 caption
宏包的 type
键。
同样是在这个链接的评论里提到,
为了使得 robust cmd 达到应有的效果,必须使用这几个 \protected@
开头的命令,而 protected 宏则没有这个要求。
因为 \label@optarg
在第一次展开 \thepage
时用的是 \edef
,而不是 \protected@edef
,只有后者才能保护 \protect
宏。问题就在于此。
由于 LaTeX 内核用 begindocument
钩子 patch 了 cleveref
的几个命令,\label@optarg
恰好在其中,所以自己 patch 也必须使用这个钩子才行。可查看 latex2e-first-aid-for-external-files.pdf 这个文件了解 patch 了哪些命令。
默认情况下,每页底部的文字都是对齐的,但不可能恰好每页文字的长度都一样,所以那些可以伸缩的空白就会根据需要而伸长或缩短。
你的这种情况可以设置章节标题前后的间距为固定长度,而不是弹性长度,或者不设置每页底部文字对齐。
前者可以通过 ctex
文档类或 titlesec
等提供的接口修改,后者只需在 \begin{document}
之前加上 \raggedbottom
。
不是没起作用,而是 env/../before
和 env/../after
钩子的内容是在当前组中执行的,这里的 \bfseries
对整篇文档都生效,而不是只对 quote
环境生效。环境开始时会添加 \begingroup
,before
钩子在这个 \begingroup
之前执行,begin
钩子在这个 \begingroup
之后执行。因此 env/../begin
和 env/../end
钩子才是和环境的内容在同一个组。这些在文档 lthooks-doc 的 3.1.1 节有描述。
报错里看到 \test..
展开为了 inner sep=2
不代表 \node
读取键时看到了 \test..
展开后的结果,读取键时可能展开,也可能不展开,完全取决于实现。比如 \keys_set:nn
就不会展开键,\keys_set:ne
就会先展开第二个参数,再读取键。实际使用时不应当依赖于这一行为,如果没有特殊说明,总是应当认为既可能展开,又可能不展开,这样才能减少出错的概率。
问 关于l3keys是否对于\l_keys_key_str的作用域有更新的问题?