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

注册于 5年前

回答
259
文章
2
关注者
25

\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%"
            ]
        },
        ....
]

最简单的办法是加上这行

\pgfkeys{...
  /mycmd/.search also={/tikz}, % <- 自动找 /tikz/...
}
\documentclass{article}
\usepackage{tikz}

\pgfkeys{%
  /mycmd/.is family,
  /mycmd/.cd,
  /mycmd/.search also={/tikz},
  default/.style={color=black},
  color/.store in = \mycmdcolor,
}

\pgfkeys{%
  /tikz/mycmd/.code args={#1}{%
    \pgfkeys{/mycmd, default, #1}
    \pgfkeysalso{color=\mycmdcolor,}
  }
}

\newcommand{\mydraw}[1][]{%
\draw[mycmd={#1}] (0,0) -- (4,0); }

\begin{document}
\begin{tikzpicture}
  \mydraw[color=blue, line width=1mm]
\end{tikzpicture}
\end{document}

\documentclass[tikz,border=5pt]{standalone}
\usepackage{tkz-euclide}

\ExplSyntaxOn\makeatletter
\pgfmathdeclarefunction{pointveclen}{3}{
  \begingroup
  \tikz@scan@one@point\pgfutil@firstofone(#1)\relax
    \pgf@xx\pgf@x \pgf@xy\pgf@y
  \tikz@scan@one@point\pgfutil@firstofone(#2)\relax
    \pgf@yx\pgf@x \pgf@yy\pgf@y
  \pgfmathparse{veclen(\the\pgf@xx+#3\the\pgf@yx,\the\pgf@xy+#3\the\pgf@yy)}
  \pgfmath@smuggleone\pgfmathresult
  \endgroup
}
\NewDocumentCommand\tkzAutoLabelPolygons{O{} r()} {
  \group_begin:
  \seq_gclear:N \g_tmpa_seq
  \foreach \x in {#2} { \seq_gput_right:Ne \g_tmpa_seq { \x } }
  \seq_get_left:NN \g_tmpa_seq \l_tmpa_tl
  \seq_get_right:NN \g_tmpa_seq \l_tmpb_tl
  \seq_gput_left:NV \g_tmpa_seq \l_tmpb_tl
  \seq_gput_right:NV \g_tmpa_seq \l_tmpa_tl
  \int_step_inline:nnn { 2 } { \seq_count:N \g_tmpa_seq - 1 }
    {
      \seq_gpop_left:NN \g_tmpa_seq \l_tmpa_tl
      \tl_set:Ne \l_tmpb_tl { \seq_item:Nn \g_tmpa_seq { 1 } }
      \tl_set:Ne \l_tmpc_tl { \seq_item:Nn \g_tmpa_seq { 2 } }
      \pgfinterruptboundingbox
      \coordinate (tempa) at ($1cm/pointveclen("\l_tmpa_tl","\l_tmpb_tl","-")
        *($(\l_tmpa_tl)-(\l_tmpb_tl)$)$);
      \coordinate (tempb) at ($1cm/pointveclen("\l_tmpc_tl","\l_tmpb_tl","-")
        *($(\l_tmpc_tl)-(\l_tmpb_tl)$)$);
      \coordinate (tempc) at ($0.3*1cm/pointveclen("tempa","tempb","+")
        *($(tempa)+(tempb)$)$);
      \endpgfinterruptboundingbox
      \path (\l_tmpb_tl) -- ($(\l_tmpb_tl)-(tempc)$)
        node[label~style,anchor=center,#1] {$\l_tmpb_tl$};
    }
  \group_end:
}
\ExplSyntaxOff\makeatother

\begin{document}

\begin{tikzpicture}
  \tkzDefPoints{-1/-1/A, 1/-2/B, 3/0/C, 2/4/D, 0/5/E,-3/2/F}  
  \tkzDrawPolygons[thick](A,...,F)
  \tkzAutoLabelPolygons(A,...,F)
\end{tikzpicture}

\begin{tikzpicture}
  \tkzDefPoints{-1/-1/A, 1/-2/B, 0.5/0/C, 2/4/D, 0/5/E,-3/2/F}
  \tkzDrawPolygons[thick](A,...,F)
  \tkzAutoLabelPolygons(A,...,F)
\end{tikzpicture}

\end{document}

image.png

见 The TeXBook 第 258 页(2021 年版),The LaTeX Companion 第三版 5.3.4、5.3.5 节。

TeX 遇到某些内容和输出这些内容所在的页码并不一定相同,比如,TeX 在准备第 5 页所需的内容时遇到太多文字,直到第 5 页输出完成后才能知道哪些文字是多余的,然而它们是在第 5 页中发现的,却并不是在第 5 页输出的,这就存在某些问题,比如假如这些多出来的文字中获取了 page 计数器的值,由于它在第 5 页中执行,得到的结果是 5,而不是 6。TeX 为了解决这个问题提供了几个方案,一个是把要获取的这些值延迟到页面输出完成之后再获取,另一个就是 mark 机制。

firstmark 就是输出的那一页最开始遇到的 mark,botmark 就是最后遇到的 mark,topmark 就是上一页的 botmark。最开始的 TeX 只有一个 mark 类,e-TeX 扩展为了 32767 个。

如果你用 LaTeX 2022-06-01 及之后的版本,那么 LaTeX 提供了 \FirstMark \LastMark \TopMark,并且不但能获得当前页的,还能获得上一页、当前栏、上一栏的。建议使用这些命令。如果用的是 2025-06-01 的版本,还能获得 multicols 每一栏的 marks。

不过,如果 marks 出现在其它盒子中,那么 TeX 无法正确更新,可以用我写的 updatemarks 宏包。

\changetext 的修改是局部的,而 shipout 钩子总是放在一个组中执行,必须要全局修改。

\AddToHookNext{shipout}{\global\advance\textheight2cm\relax}

不过,如果修改 \textheight 正好发生在 paracol 环境中间,是无效的,原因未知。

设置 TEXINPUTS 环境变量,.tex .sty 这类文件都在 $TEXMF/tex// 目录里查找,而 TeX 文档的位置在 $TEXDOCS$TEXMF/doc//) 这个变量里(texmf.cnf 的变量,不是环境变量)。

cmd:
set TEXINPUTS=;$TEXDOCS

powershell:
$env:TEXINPUTS=';$TEXDOCS'

不过最好不要设置 $TEXDOCS 来编译文档,因为这里的目录包含许多配置文件(比如 hyperref.cfg,你设置上面的环境变量再用 xelatex 编译就会发现报错),会出现什么完全不能预测。
可以先修改 TEXINPUTS 然后用 kpsewhich 找到所需的文件,只用特定目录一般问题不大:

set TEXINPUTS=;$TEXDOCS
kpsewhich lshort-zh-cn-style.sty
% 注意要先清除
set TEXINPUTS=
set TEXINPUTS=;$TEXMFDIST/doc/latex/lshort-chinese//
xelatex main.tex

可以查看 texdoc kpathsea 文档了解更多内容。

xecjk 会在 cjk 文字之间插入 \CJKglue,这个值一般为 \hskip 0pt plus 0.08\baselineskip,这个 stretch 比较小,一般小于 1em,在宽度为 3em 时,两个汉字间需要插入的空白大于 cjkglue 的伸长部分,所以会报 warning。

英文空格会变成一个 glue,根据需要会使用 \spaceskip\xspaceskip;xecjk 的中文与西文之间会插入 \CJKecglue,都可以用于控制所插入的空白的 stretch 和 shrink。

CJKfilltwosides 就调整了 \CJKglue,使得空白可以无限伸长。

X-Y problem?
你想要的是在两个字符中间插入任何东西,只要这些字符连同它中间的东西一共是三个字符的宽度就行?还是要保证不论输入几个字符,总宽度固定就行?还是不论输为何,其最终结果是两个汉字,然后在两个汉字中间插入 \quad?还是就是给定两汉字,中间插入 \quad

这几个问题难度不同,解决办法可以说是完全不同。最简单就是第四个,这种你可以直接写 \newcommand\mycmd[2]{#1\quad#2}\mycmd 余华。对于第一个问题还可以还可以看 xecjk 的文档,它有分散对齐汉字的环境。

无需任何宏包:

\documentclass{article}

\makeatletter
\def\@zheng@i{\vrule height2ex depth-1.8ex width2ex\relax} % U+1D372
\def\@zheng@ii{\@zheng@i\kern-2ex\hbox to2ex
  {\hfil\vrule height2ex depth-.2ex width.2ex\hfil}} % U+1D373
\def\@zheng@iii{\@zheng@ii\kern-1ex\hbox to1ex
  {\vrule height1.1ex depth-0.9ex width0.8ex\hfil}} % U+1D374
\def\@zheng@iv{\@zheng@iii\kern-2ex\hbox to2ex
  {\hskip 0.3ex\vrule height1.3ex depth-0.2ex width0.2ex\hfill}} % U+1D375
\def\@zheng@v{\@zheng@iv\kern-2ex\vrule height0.2ex width2ex\relax} % U+1D376
\protected\def\@zheng#1{%
  \edef\x{\ifcase#1 \or\noexpand\@zheng@i\or\noexpand\@zheng@ii\or\noexpand\@zheng@iii
    \or\noexpand\@zheng@iv\or\unexpanded{\@zheng@format{\@zheng@v}}%
    \else\unexpanded{\@zheng@format{\@zheng@v}\zheng{#1-5}}\fi}\x}
\protected\def\zheng#1{\leavevmode\expandafter\@zheng\expandafter{\the\numexpr#1}}
\long\def\@zheng@format#1{\mbox{#1}\ }
\protected\long\def\zhengformat#1{\long\def\@zheng@format##1{#1}}
\makeatother

\begin{document}

12345 \zheng{1} \zheng{2} \zheng{3} \zheng{4} \zheng{5}

12345 \zheng{1}\zheng{2}\zheng{3}\zheng{4}\zheng{5}

6 \zheng{6}

horizontal 42:
\zhengformat{\mbox{#1}\ }
\zheng{42}

vertical 42:
\zhengformat{\mbox{#1}\\}
\begin{tabular}[t]{c}
\zheng{42}
\end{tabular}

\end{document}

image.png

有的字体比如 Noto Unicode、霞骛文楷、Plangothic P1 等有这些字形,下载这些字体后直接用 \fontspec{..} \symbol{"1D372} 即可。

\documentclass[UTF8]{ctexart}%pdflatex编译
\usepackage[showframe,margin=1in]{geometry}
\usepackage{enumitem}
    \setlist[enumerate]{nosep,labelsep=0pt,leftmargin=2em}
\usepackage{multicol}
    \setlength{\columnseprule}{.4pt}
    \setlength{\columnsep}{1cm}

\makeatletter
\newcommand\brule[3][\z@]{\leavevmode
  {\setlength\@tempdima{#2}\setlength\@tempdimb{#1}\setlength\@tempdimc{#3}%
   \@tempcnta=\fpeval{ceil(\@tempdima/5pt)}
   \kern\z@
   \loop\ifnum\@tempcnta>\z@
     \vrule \@width 5pt \@height \@tempdimc \@depth -\@tempdimb \hskip\z@skip
     \advance\@tempcnta\m@ne
   \repeat \unskip
}}
\makeatother
\begin{document}

\noindent\textbf{16. }补写出下列句子中的空缺部分。(6分)

\begin{multicols}{2}

\begin{enumerate}[label=(\arabic{enumi})]
    \item 
    王湾《次北固山下》的名句“\brule{9em}{.4pt},\brule{9em}{.4pt}”,描写时序交替中的景物,暗示着时光流逝,蕴含着自然理趣。
    \item 
    小慧为朋友家的农家乐餐厅写宣传横幅,直接使用了陆游《游山西村》里的“\brule{9em}{.4pt},\brule{9em}{.4pt}”两句诗,朋友看了觉得很贴切。
    \item 
    行至群山深处,见到一挂瀑布飞泻而下,水石激荡,轰鸣作响,于老师回头对学生们说:“这不就是古诗中写的‘\brule{9em}{.4pt},\brule{9em}{.4pt}’嘛!”
\end{enumerate}

\end{multicols}

\noindent\textbf{参考答案:}

\begin{enumerate}[label=(\arabic{enumi})]
    \item 
    海日生残夜\quad 江春入旧年
    \item 
    山重水复疑无路\quad 柳暗花明又一村
    \item 
    飞流直下三千尺\quad 疑是银河落九天(飞湍瀑流争喧豗\quad 砯崖转石万壑雷)
\end{enumerate}

\end{document}

image.png

略微改进版:

\newcommand\brule[3][\z@]{\leavevmode
  {\setlength\@tempdima{#2}\setlength\@tempdimb{#1}\setlength\@tempdimc{#3}%
   \@tempcnta=\fpeval{ceil(\@tempdima/5pt)} \@tempdima=\dimexpr5pt/\@tempcnta\relax\relax
   \ifnum\@tempcnta>\z@
     \loop\ifnum\@tempcnta>\z@
       \vrule \@width 5pt\@height\@tempdimc \@depth-\@tempdimb \hskip\z@\@minus\@tempdima\relax
       \advance\@tempcnta\m@ne
     \repeat
   \unskip\fi
}}

发布
问题