雾月
雾月
这家伙很懒,什么也没写!

注册于 6年前

回答
268
文章
2
关注者
26

不用 \include 编译,你可以在 log 最后几行看到这样的内容:

(\end occurred when \ifx on line 42 was incomplete)
Output written on main.pdf (1 page).

用了 \include 只是将这个问题过早地暴露出来而已。

实际是 ntheoremhyperref,thref 这两个选项导致的问题。ntheorem不会自动加载 hyperref(即使启用 hyperref 选项也是如此)。需要自己在 ntheorem 之后加载 hyperref

\usepackage[amsmath,thmmarks,amsthm,hyperref,thref]{ntheorem}
\usepackage{hyperref}

这样应该就能正常编译了。


ntheorem 最近更新已经是15年前。这期间 LaTeX 里涉及到引用的相关代码已经发生了很大改变,主要是 LaTeX 内核里 \newlabel 内部的参数由原来的 2 个变成了 5 个,保证了与 hyperref 一致。ntheorem 却没有,如果只使用 hyperref 选项而不加载 hyperref 宏包,它写入的 label 是用的 2 个参数,但却是按 5 个参数来用的,参数不足,TeX 只能吞掉后面的 tokens 了。

现在如果硬要用 ntheorem,还要正确的交叉引用,最好是不用它自己的实现,而用 zref-clever 宏包:

\usepackage[amsmath,thmmarks,amsthm]{ntheorem}
\usepackage{hyperref}
\usepackage{biblatex}
\addbibresource{thesis.bib}
\newtheorem{theorem}{定理}[section]

\usepackage{zref-clever}
\let\thref\zcref
\zcsetup{noname}
\zcRefTypeSetup{theorem}{refbounds={,定理,,}}

编译结果应该是一致的。这在 TeXLive 2023 以及之后应该都是能正确编译的。更早一点的版本,就要使用 cleveref 宏包,不过,它最近更新也是 8 年前了,与现在的 LaTeX 内核也有不兼容的地方。

可以使用 \cftsetindents{⟨entry⟩}{⟨indent⟩}{⟨numwidth⟩}entry 就是 section 这些,indent 就是第一行的缩进,numwidth 就是标题数字的宽度,也是第一行之后的缩进。

% ctex 五号字的是 10.5bp,一共三个字,ctex 还会在数字后面加上半个字宽的间距
\cftsetindents{section}{0pt}{\dimeval{10.5bp*3+10.5bp/2}}

这样的结果是
image.png
比较短的数字后有额外的间距。ctex 做了补丁,它把数字的宽度设置为其自然宽度(加上半个字宽)和 numwidth 中的较大值,如果没有这个补丁,数字的宽度就是 numwidth

如果要保持自然宽度,需要重定义

\usepackage{calc}
\makeatletter
\protected\def\CTEX@toc@width@n#1{\setlength\@tempdima{\widthof{#1}+\f@size\p@/2}}
\makeatother

image.png

完整代码:

\documentclass[UTF8,punct=banjiao,fontset=fandol]{ctexart}
%% 载入各种宏包 -----------------------------
\usepackage{tocloft,zhlipsum,geometry}
%% 自定义命令 -------------------------------
\newcommand{\setsecpage}[2]{
  \setcounter{section}{#1}
  \setcounter{page}{#2}}
%% ctex 相关设定 ----------------------------
\ctexset{
  section/number={\zhdigits{\arabic{section}}},
  section/format={\bfseries}}
%% geometry 相关设定 ------------------------
\geometry{a6paper, hmargin=5mm, vmargin=1cm, headsep=2.5mm, footskip=7.5mm, marginparwidth=5mm, marginparsep=0pt, showframe}%
%% 页眉页脚相关设定 --------------------------
\makeatletter
\renewcommand{\@oddhead}{}
\renewcommand{\@evenhead}{}
\renewcommand{\@oddfoot}{\hfill\thepage}
\renewcommand{\@evenfoot}{\thepage\hfill}
\makeatother
%% 目录相关设定 ------------------------------
%% 目录标题名 : 
\renewcommand{\contentsname}{\bfseries 目\quad 录}
\renewcommand\cfttoctitlefont{\null\hfill}
\renewcommand\cftaftertoctitle{\hfill\null}
%% 目录页码 : 
\renewcommand{\cftsecpagefont}{}
\renewcommand{\cftsecafterpnum}{}
%% 目录引导点 : 
\renewcommand\cftdot{$\cdot$}
\renewcommand{\cftdotsep}{0}
\renewcommand{\cftsecleader}{\cftdotfill{\cftdotsep}}
%% 目录条目 : 
\renewcommand{\cftsecfont}{}

\cftsetindents{section}{0pt}{\dimeval{10.5bp*3+10.5bp/2}}
\usepackage{calc}
\makeatletter
\protected\def\CTEX@toc@width@n#1{\setlength\@tempdima{\widthof{#1}+\f@size\p@/2}}
\makeatother
\begin{document}

\tableofcontents

\setsecpage{3}{5}
\section{“挨”在“挨着坐”和“挨到天亮”中的读音}
\zhlipsum[1-2]

\setsecpage{17}{35}
\section{“屏”在“屏除杂念”中的读音}
\zhlipsum[1-2]

\setsecpage{101}{78}
\section{“空地”“空缺”中的“空”读四声 kòng,不读一声kōng}
\zhlipsum[1-2]

\setsecpage{128}{158}
\section{“宁缺勿滥”“宁死不屈”中的“宁”读四声nìng,不读二声níng}
\zhlipsum[1-2]

\setsecpage{188}{259}
\section{“肖像”“生肖”中的“肖”读四声 xiào,不读一声xiāo}
\zhlipsum[1-2]

\end{document}

我没有测试以上代码在 ctex 前几天发的新版中是否仍然生效,但旧版可行。

\exp_args:Ne \test:n { \text_expand:n { XXX: ~\a } }

image.png

\exp_args:No 只会把第一个“词元”(token)展开一次,\a 不是第一个词元,所以不会展开。

\, 是 Robust 命令(用 \DeclareRobustCommand 定义的,也就是文档说的 LaTeX-protected),必须使用特定的手段才能保护,在 e 参数里会被直接展开,所以 \exp_args:Ne 不行。

\text_expand:n 会比 e 参数慢很多,一般是临时重定义 \protect,让 Robust 命令生效:

\makeatletter
\let\@@protect\protect
\let\protect\noexpand
\afterassignment\restore@protect
\edef \l_tmpa_tl { XXX: ~\a } % 可以改成 \tl_set:Ne
\exp_args:No \test:n { \l_tmpa_tl }
\makeatother

  1. 计算宽度要用 interrupt 环境,直接在绘图环境里是不行的。
  2. blur shadow 里创建了新的绘图环境,盲猜是因为这个把原本的 bottom 图层清空了,解决办法同 1,把标题样式放到单独的绘图环境,先让它画完这部分,就不会被后面影响了。
  3. 分别在 extra unbroken/first/middle/last 里使用 /tcb/interior code 重写 interior,让 first 末尾的颜色等于 middle 开始的颜色,依此类推,但 middle 部分最好不使用渐变,因为 tcb 好像没有直接判断是否是 unbroken 还是 first-middle-last 还是 first-last,需要 hack。

我实现了 1,2。对于 3,middle 不使用渐变的情况下应该不难。

\documentclass[12pt]{ctexbook}
\usepackage{lipsum}
\usepackage[margin=2cm]{geometry}
\RequirePackage{cncolours,newtx}
\RequirePackage{etoolbox} % 判断函数
\RequirePackage{tikz,calc} %%页面样式设计核心包 %提供\pgfonlayer命令
\usetikzlibrary{cd,calc,shadows,shadows.blur,hobby,intersections, decorations.markings, decorations.pathreplacing,spy,arrows,shapes,fadings,trees,mindmap,patterns,shapes.arrows,shapes.symbols,tikzmark,shapes.geometric,graphs, quotes, angles,decorations.pathmorphing,through,shadings,backgrounds,positioning,fit,arrows.meta,shapes.misc,decorations.shapes}
\pgfdeclarelayer{background} %背景%底层
\pgfdeclarelayer{foreground} %上层
\pgfdeclarelayer{top} %顶部
\pgfdeclarelayer{bottom} %底部
\pgfsetlayers{bottom,background,main,foreground,top}
\RequirePackage[most]{tcolorbox}
\tcbuselibrary{breakable, skins,theorems,minted}

\makeatletter
\tcbset{my@basic@tcbthm/.style={detach title,}}
\newcommand{\@my@newtcbtheorem@n}[1]{\ERROR}
\newcommand{\@my@newtcbtheorem@nn}[2]{%
  \@ifundefined{#1}{\@my@newtcbtheorem{#1}{#2}}{\@my@renewtcbtheorem{#1}{#2}}}
\newcommand{\@my@newtcbtheorem}[2]{%
  \edef\my@curr@thmenvname{#1}% 它保存当前定理环境的名称
  \mytcbtheoremset{#2}%
  \NewTColorBox{#1}{ O{} O{} o }
  {my@basic@tcbthm, my@#1@tcbthmstyle, title={##2}, IfNoValueF={##3}{label={##3}}, ##1}}
\newcommand{\@my@renewtcbtheorem}[2]{\edef\my@curr@thmenvname{#1}\mytcbtheoremset{#2}}

% 键值设置
\pgfkeys{/mytcbtheorem/.is family}
\newcommand{\mytcbtheoremset}{\pgfqkeys{/mytcbtheorem}}
\mytcbtheoremset{
  name/.code=\@namedef{\my@curr@thmenvname @name}{#1}, %无效
  counter/.code=\@namedef{my@\my@curr@thmenvname @counter}{#1}\newcounter{#1}[chapter],
  % 计数器遇到subsection就会自动归零 % https://zhuanlan.zhihu.com/p/57454848#circle=on
  the counter/.code=\@namedef{the\@nameuse{my@\my@curr@thmenvname @counter}}{#1},
  autoref name/.code=\@namedef{\@nameuse{my@\my@curr@thmenvname @counter}autorefname}{#1},
  style/.code=\tcbset{my@\my@curr@thmenvname @tcbthmstyle/.style={#1}},
  thmcolor/.code=\@namedef{\my@curr@thmenvname @thmcolor}{#1}, %无效
  lemcolor/.code=\@namedef{\my@curr@thmenvname @lemcolor}{#1}, %无效
}
% 存储键值 (LaTeX3)
\ExplSyntaxOn
\cs_new_protected:Npn \mynewtheorem
   { \keyval_parse:NNn \@my@newtheorem@n \@my@newtheorem@nn }
\cs_new_protected:Npn \mynewtcbtheorem
{ \keyval_parse:NNn \@my@newtcbtheorem@n \@my@newtcbtheorem@nn }
\ExplSyntaxOff

% /* ------------------ Second theorem style overlay settings ----------------- */
%%定义标题文字长度%%
\newlength{\thmtcbtextlen}
%%设置临界长度%%
\newlength{\thmcriticstarlen}
\setlength{\thmcriticstarlen}{.6\linewidth}
%
\def\my@thm@a#1#2{%
  \begin{scope}
    \path[
      fill=#2,
      drop shadow={shadow blur steps=10,shadow xshift=-1pt, shadow yshift=-1pt,shadow blur radius=1.5pt,shadow opacity=35}
    ]
    node
    [
      append after command={
        ([xshift=-1.5*\rad]thmname.north west) to[out=0,in=180,looseness=1] ([xshift=2.5*\rad]thmname.south west) --([xshift=-\rad]thmname.south east) to[out=0,in=180,looseness=1] ([xshift=3*\rad]thmname.north east) --cycle},
      text=white,font=\bfseries,align=center,inner ysep=1.5mm,minimum height=0.6cm,right
    ]
    (thmname) at
    ([xshift=\rad,yshift=-.7*\rad]frame.north west)
    {\hspace*{10pt}#1.\ \ifdefvoid{\tcbtitletext}{}{(\itshape\tcbtitletext)}};

    %%============== 两边的阴影/折叠部分 ==============%%
    \my@thm@a@layer{#1}{#2}
  \end{scope}%
}
\def\my@thm@a@layer#1#2{%
  \begin{pgfonlayer}{bottom}
      % 左侧翅膀样式一
      % \shade[left color=#2!20, right color=#2!80!black]
      % ([xshift=-1.5*\rad]thmname.north west)
      % to[out=180, in=0] ++(-2*\rad, -\rad)
      % -| +(5*\rad,\rad)
      % -- cycle;
      % /* -------------------------------------------------------------------------- */
      % 左侧翅膀样式二:镜像翻转为向上折叠效果
      \shade[left color=#2!20, right color=#2!80!black]
      ([shift={(-.5*\rad,-\rad)}]thmname.north west)
      to[out=180, in=0] ++(-2*\rad, \rad) % 将 -\rad 改为 \rad,使其向上延伸
      -| +(5*\rad, -\rad)                 % 将 \rad 改为 -\rad,使其向下回到主体水平线
      -- cycle;
      % 右侧翅膀:完全镜像处理
      % \shade[right color=#2!20, left color=#2!80!black]
      % ([xshift=3*\rad]thmname.north east) % 注意这里起点需对应你核心代码中的 3*\rad
      % to[out=0, in=180] ++(2*\rad, -\rad) % 镜像:out 180->0, in 0->180, x -2->2
      % -| +(-5*\rad,\rad)                % 镜像:x 5->-5
      % -- cycle;
      % ===== 右翅膀按条件切换 =====
      %判断标题文字长度与临界长度的关系
      \ifdim\thmtcbtextlen>\thmcriticstarlen
        %-------- 右侧小翅膀:上下翻转版本 --------
        \shade[right color=#2!20, left color=#2!80!black]
            ([xshift=2*\rad,yshift=-1*\rad]thmname.north east)
            to[out=0, in=180] ++(2*\rad, \rad)
            -| +(-5*\rad,-\rad)
            -- cycle;
      \else
        % -------- 右侧小翅膀:原版本 --------
        \shade[right color=#2!20, left color=#2!80!black]
            ([xshift=3*\rad]thmname.north east)
            to[out=0, in=180] ++(2*\rad, -\rad)
            -| +(-5*\rad,\rad)
            -- cycle;
      \fi
  \end{pgfonlayer}
}
\def\my@thm@b#1#2{%
  \begin{scope} % <--- 添加 scope 隔离环境
    \path[fill=#2,
    % drop shadow={opacity=0.3,shadow xshift=.3pt}
    blur shadow={shadow blur steps=10,shadow xshift=-1pt, shadow yshift=-1pt,shadow blur radius=1.5pt,shadow opacity=35}
    ]
    ([xshift=-2*\rad,yshift=-5pt]frame.south east) coordinate (SE)  to[out=0,in=180] +(4*\rad,5pt+\theight) --([shift={(-\tlen+4*\rad,5pt+\theight)}]SE) to[out=180,in=0] +(-4*\rad,-5pt-\theight) --cycle;
    \begin{pgfonlayer}{bottom}
        % 左侧翅膀:镜像翻转为向上折叠效果
        \shade[left color=#2!20, right color=#2!80!black]
        ([shift={(-1.35*\tlen+\Rad,-5pt)}]frame.south east)
        to[out=180, in=0] ++(-2*\rad, \rad) % 将 -\rad 改为 \rad,使其向上延伸
        -| +(5*\rad, -\rad)                 % 将 \rad 改为 -\rad,使其向下回到主体水平线
        -- cycle;
    \end{pgfonlayer}
  \end{scope}%
}
\newcommand{\my@lemma@overlay@unbroken}[2]{
   %%============== First ==============%%
  \def\rad{7pt}%
  %%% 注意这里!
  \begin{pgfinterruptpicture}
    \settowidth{\thmtcbtextlen}{\hspace*{10pt}#1.\ \ifdefvoid{\tcbtitletext}{}{(\itshape\tcbtitletext)}}
    % \global\thmtcbtextlen\thmtcbtextlen % \my@thm@a放到interrupt环境外面就需要global
    \begin{tikzpicture}
      % 这里可能需要调整细节!
      \path[use as bounding box]([xshift=\rad]frame.north west) rectangle (frame.south east);
      \my@thm@a{#1}{#2}%
    \end{tikzpicture}
  \end{pgfinterruptpicture}
  % \my@thm@a{#1}{#2}% 把它放到单独的tikz环境里,如上
   %
   %%============== End ==============%%
   \def\tlen{1.5cm}
   \def\Rad{3.5pt}
   \def\theight{0.5cm}
  \my@thm@b{#1}{#2}
}

%% first 和 last 没在 MWE 里!
\newcommand\my@lemma@overlay@first[2]{
  \def\rad{7pt}%
  \begin{pgfinterruptpicture}
    \settowidth{\thmtcbtextlen}{\hspace*{10pt}#1.\ \ifdefvoid{\tcbtitletext}{}{(\itshape\tcbtitletext)}}
    % \global\thmtcbtextlen\thmtcbtextlen % \my@thm@a放到interrupt环境外面就需要global
    \begin{tikzpicture}
      \path[use as bounding box]([xshift=\rad]frame.north west) rectangle (frame.south east);
      \my@thm@a{#1}{#2}%
    \end{tikzpicture}
  \end{pgfinterruptpicture}
}
\newcommand\my@lemma@overlay@last[1]{
  \def\rad{7pt}%
  \def\tlen{1.5cm}
  \def\Rad{3.5pt}
  \def\theight{0.5cm}
  \my@thm@b{}{#1}
}

\mynewtcbtheorem{
  theorem={
    counter=tcbthm,
    the counter=\thesection.\arabic{tcbthm},
    autoref name=\bfseries Theorem,
    style={
      arc=0mm,breakable,enhanced,
                % 针对跨页片段的特殊处理
      extras first={
            bottom=3mm, % 第一段的底部不需要留白
        },
      extras middle={
            top=3mm,    % 中间段的顶部不需要留白
            bottom=0mm, % 中间段的底部不需要留白
        },
      extras last={
            top=0mm,    % 最后一段的顶部不需要留白
        },
      % 建议同时加入以下设置以确保彻底消除干扰
      pad at break=2mm,
      bottomsep at break=0mm,
      topsep at break=2mm,
      interior style={top color=黛绿!9 ,middle color=黛绿!6, bottom color=黛绿!3},arc=3pt,boxrule=0pt,top=6mm,bottom=5mm,
      fuzzy shadow={-0.6mm}{0.6mm}{0mm}{0.3mm}{white!50!gray},% 上
      fuzzy shadow={0.6mm}{-0.6mm}{0mm}{0.3mm}{fill=white!40!gray},%下
      opacityframe=0, opacityback=0.98,
      fontupper=\itshape,step={tcbthm},
      before pre=\smallskip, after app=\smallskip,
      overlay unbroken=\my@lemma@overlay@unbroken{Theorem\ \thetcbthm}{黛绿},
      overlay first=\my@lemma@overlay@first{Theorem\ \thetcbthm}{黛绿},
      overlay last=\my@lemma@overlay@last{黛绿},
    }
  },
}
\makeatother
\begin{document}
\chapter{Test}
\begin{theorem}[][Semidefinite vanishing theorem for vector bundle of rank $k$ (General Case)][thm:Semidefinite vanishing theorem for vector bundle of rank $k$ (General Case)]
   Let $M$ be a compact complex manifold, and assume that there exists a hermitian metric on $E$, whose curvature tensor $\Theta$ satisfies the following condition at each point of $M$.
        
   For any $\zeta\in C^r-0$, the quadratic form in $\eta,\Theta(\zeta,\eta)$, has at least $n-k_1$ positive eigenvalues and at least $k_2$ negative eigenvalues. Then 
    \[H^q(M,\Omega(S^\mu E\otimes D))=0\]
    for any $q\not\in (k_1,\ldots,k_2)$ if $\mu\geq 0$.
\end{theorem}

\begin{theorem}[][lorem lipsum]
  \lipsum[1-10]
\end{theorem}
\end{document}

\listoffigures
\goodbreak\thepage

\thepage 这行一般不能包含 typesetting material,否则它可能不会和 \listoffigures 保持在同一页。

\listoffigures
\mbox{}
\thepage

有空格是因为 \mbox{} 离开水平模式,并且有了一个空盒子,导致它后面的空格不会被忽略,从而 \thepage 前面多了个空格。加上注释符就没有空格了。当然这可能会出现不想要的空行。

xeCJKfntef 基于 ulem 实现,ulem 限制很多,不能随便加组,\zhlipsum 就有:

\NewDocumentCommand \zhlipsum { s o +o }
  {
    \group_begin:
      \IfBooleanF {#1}
        ...
  }

保存在宏里的文字一般也无法换行,见 ulem.pdf 第 5 页。
image.png

不是已经实现了吗,没懂哪里有问题,除了 label 单独一行外,也没懂一二种列表有什么区别。

enumitem 的实现,需要用 verb 的地方,在合适的地方用 \scantokens 重新扫描一下就行了(\sitem 的实现方式):

\NewDocumentCommand\sitem{+v}{\item[\scantokens{#1}]}
\newlist{mydesc}{description}{2}
\setlist[mydesc,1]{}
\setlist[mydesc,2]{style=nextline}

\begin{mydesc}
\sitem{\Verb|something|} 劳仑
\sitem{\mintinline{asy}|Rotate(pair z)|} 普桑
  \begin{mydesc}
    \sitem{wa hh} 劳仑\\ 衣
    % \item[wa hh] 也可以用
    \sitem=\Verb|\{}|= 普桑
  \end{mydesc}
\end{mydesc}

label 宽度可以自己改改。
image.png

\documentclass[fontset=fandol]{ctexart}
\ctexset{section/format+={\raggedright}}
\parindent=0pt
\begin{document}

\begingroup\ctexset{section/format+=\centering}
\tableofcontents
\endgroup

\section{aaaa}

\section{bbbb}

\section{cccc}

\section*{ddd}

\end{document}

一般情况下 \section 等命令不建议放在组中(因为它们可能为了实现某些效果会重定义 \par),但只在目录里这么做还是问题不大的,目录条目一般都会使用自定义的格式,而不像普通段落那样。

listing 环境就是一个浮动体,tcolorbox 自己就有对应的功能,没必要再套一个浮动环境,tcolorbox 也不能用 beforeafter 随便套一个环境。\label 也有对应的选项。

如果只要给代码添加目录,无需使用浮动体。要改目录条目的样式只要重定义 \l@tcolorbox 即可(\renewcommand\l@tcolorbox[2]{\@dottedtocline{1}{1.5em}{2.3em}{#1}{#2}}),见 tcolorbox 文档 5.2 节 /tcb/new/list type 选项的说明。

\documentclass[UTF8]{ctexbook}
%代码排版
\usepackage{tcolorbox}
\tcbuselibrary{minted,breakable,hooks}
\newtcblisting[auto counter,list inside=abMATLABlist]{abMATLAB}[3][]{%
    coltitle=black,
    colbacktitle=white,
    colupper=black,
    colback=white,
    boxrule=0pt,
    toprule=0.08em,
    titlerule=0.05em,
    bottomrule=0.08em,
    fonttitle=\bfseries,
    title={\heiti 代码列表 \thetcbcounter: #2},
    listing only,
    sharp corners=all,
    minted language=matlab,
    label={#3}, % \label    %% <--
    float=htbp!, % 浮动环境  %% <--,如果代码不要浮动,删掉这行
    #1,
}

\begin{document}
\tableofcontents
\tcblistof[\chapter*]{abMATLABlist}{MATLAB 代码}
%\tcblistof[\section*]{abMATLABlist}{MATLAB 代码}
%\begin{abMATLAB}{拉普拉斯展开计算行列式}{abMATLABlist:DetLaplace}

%\end{abMATLAB}
\chapter{AAA}

\begin{abMATLAB}{拉普拉斯展开计算行列式}{abMATLABlist:DetLaplace}
function d=DetLaplace(A)
% DETLAPLACE 使用 Lapace 展开计算行列式
% d = DetLaplace(A); 计算矩阵 A 的行列式 (determinant)
% 对第一行 (row) 使用 Laplace 展开 (expansion)
n = length(A);
if n==1
    d=A(1,1);
else
    d=0; v=1;
    for j=1:n
        M1j = [A(2:n,1:j-1) A(2:n,j+1:n)];
        d = d + v*A(1,j)*DetLaplace(M1j);
        v = -v;
    end
end
\end{abMATLAB}
\end{document}

至于 \chapter 前面那个例子可以编译,可能是某个奇怪的 bug,不去管就行了。

\documentclass{article}
\usepackage{ctex,lipsum}
\usepackage[most]{tcolorbox}
\usepackage{geometry}
\geometry{a4paper,left=2.5cm,right=2.5cm,top=2.5cm,bottom=2.5cm}

\makeatletter
\ExplSyntaxOn
\cs_new_protected:Npn \@Line@check@last
  {
    \int_case:nnTF { \tex_lastnodetype:D }
      {
        { 11 } { \tl_put_left:Ne \@Line@save { \vskip\the\lastskip\relax } \unskip }
        { 12 } { \tl_put_left:Ne \@Line@save { \kern\the\lastkern\relax } \unkern }
        { 13 } { \tl_put_left:Ne \@Line@save { \penalty\the\lastpenalty\relax } \unpenalty }
      }
      { \@Line@check@last }
      { \tl_set:Ne \@Line@last@type { \int_value:w \tex_lastnodetype:D } }
  }
\cs_new:Npn \@Line@is@print@number
  {
    \int_case:nnTF { \@Line@last@type }
      {
        { -1 } {}
        { 0 } {}
        { 1 } {}
        { 9 } {}
      }
      { 1~ } { 0~ }
  }
\ExplSyntaxOff

\newsavebox\linebox
\newcommand{\@Line@Number}{%
    \def\@line@no{0}
    \def\@Line@save{\nointerlineskip}%
    \def\@Line@last@type{-1}%
    \setbox\linebox\lastbox%
    \ifvoid\linebox%如果行文字盒子为空则什么都不执行
      \relax%
    \else%
      \@Line@check@last
      {\@Line@Number}%
      \@Line@save
      \ifcase\@Line@is@print@number\else
        \xdef\@line@no{\number\numexpr\@line@no+1\relax}%
        \ifnum\numexpr(\@line@no/5)*5=\@line@no\relax%判断行号能否被5整除
          \noindent\llap{\mbox{\@line@no\hskip7.5mm\relax}}%
        \else%
          \ifnum\@line@no=1%判断行号是否等于1
            \noindent\llap{\mbox{\@line@no\hskip7.5mm\relax}}%
      \fi\fi\fi
      \box\linebox\par
    \fi}
\makeatother

\begin{document}

    \makeatletter
    \noindent 不含行间公式
    \begin{tcolorbox}[breakable]
        \lipsum
        \par\@Line@Number
    \end{tcolorbox}
    
    \clearpage
    \noindent 含行间公式
    \begin{tcolorbox}[breakable]    
    \lipsum[1]
    \begin{align}% 不能用 equation 和 $$
    \int_\Omega x^2{\rm d}V=\frac{1}{5}
    \end{align}
    \lipsum[2-8]
    \par\@Line@Number
    \end{tcolorbox}
    \makeatother

\end{document}

默认就是不打印显式空格,不过某些字体下,LaTeX 会把字符码为 32,类别码为 12 的字符显示为非空白。

新版本里,我修改了实现,可以更新一下(只需更新 texhigh.sty 这个文件)。但是这个问题始终是和字体有关的。

提到的 texhigh 已经设置 \THSetCharReplacement{\ }{\textvisiablespace} 就是字面意思,这是设置字符要被替换为哪些代码,它只设置而不启用,要靠 char-replacements 键来启用。

texhigh 还额外设置了 \raggedright,所以一般是靠左而不是默认分散的,可以设置 font=\ttfamily 移除这个,也可使用 ragged2e 宏包的 \justifyingfont+=\justifying
image.png

其它问题可以参考 Sagittarius Rover 的回答。

@u70550 说的很对,仓库里有中文文档

texhigh 是高亮 TeX 代码的宏包,也可以用来输出颜文字等(实验性质的)。

需要首先安装 texhigh 命令行工具到指定位置:
执行 kpsewhich --var-value SELFAUTOLOC,得到一个路径,然后在 https://github.com/Sophanatprime/texhigh-rs/releases 下载以 texhigh-x86... 开头的对应操作系统的压缩文件(比如 Windows 是 texhigh-x86_64-pc-windows-msvc.zip),将其解压缩后复制到刚才得到的路径中(比如把 texhigh.exe 复制到 D:/texlive/2025/bin/windows)。然后执行 texhigh -V 可以得到版本信息(比如 texhigh 0.4.0),否则就是安装出错了。

然后执行 kpsewhich --var-value TEXMFLOCAL 得到一个路径,再将 https://github.com/Sophanatprime/texhigh 仓库里的 texhigh.stytexhigh.prelude.ths 复制到这个路径中:$TEXMFLOCAL/tex/latex/texhigh$TEXMFLOCAL 就是刚才执行 kpsewhich --var-value TEXMFLOCAL 得到的路径,如何没有对应的路径可以直接创建,比如创建 D:/texlive/texmf-local/tex/latex/texhigh,把这两个文件复制到这个路径即可)。然后再执行 texhash 刷新缓存即可。

总之,安装就是复制文件到指定的路径中,比较简单,不过需要确保命令行工具的版本和宏包版本一致,一般情况下,只要仓库不是刚刚更新,同一时间下载到的版本都是一致的。

然后就和使用其它宏包,比如 minted 是一样的了。

\documentclass{article}
\usepackage[tikz]{texhigh}

\begin{document}

\texhighverb|\hello, \LaTeX|.

\texhighverb[use-ctab=latex3]|\latex_hello:|.

\texhighverb[style=tikz.gradient]|\relax|.

\end{document}

执行 xelatex --shell-escape main.tex(其它引擎也可以,--shell-escape 是必要的)。
image.png

更详细的用法可以参考文档例子以及我写的一个显示TikZ图形和代码的例子

\documentclass{article}
\usepackage{showframe}
\newenvironment{abc}{\par}{\par}
\newcommand\NoindentNextPara{\AddToHookNext{para/begin}{\OmitIndent}}
\begin{document}
text1\par
text2\NoindentNextPara
\begin{abc}
abc
\end{abc}
text4\par
text5
\end{document}

image.png

https://bithesis.bitnp.net/faq/biber-perl-cache.html

image.png

LaTeX Workshop 可以设置环境变量。修改用户设置,biber 命令的环境变量改为:

"latex-workshop.latex.tools": [
        {
            "name": "biber",
            "command": "biber",
            "env": {
                "TEMP": "%WORKSPACE_FOLDER%",
            },
            "args": [
                "%DOCFILE%"
            ]
        },
        ....
]

发布
问题