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

注册于 4年前

回答
223
文章
2
关注者
23

在每个章节的开始处将计数器的值写入 aux 文件中,

\usepackage{atveryend}
\makeatletter
\newcounter{problem} % 问题总个数
\protected\def\write@problem@counter #1{% 计数器写入辅助文件, #1 为第几个
  \immediate\write\@auxout{\string\global\string\@namedef
    {label/problem/atchap\number #1}{\number\value{problem}}}}
\AtBeginDocument{%
  \providecommand\totalproblemcount{0}% 总个数:\totalproblemcount
  \write@problem@counter{0}} % 第 0 个
\AfterLastShipout{\immediate\write\@auxout{%
    \string\gdef\totalproblemcount{\value{problem}}}% 总个数:\totalproblemcount
  \stepcounter{problem}%
  \write@problem@counter{\numexpr\value{chapter}+1}} % 第 n+1 个
% 得到保存的第 #1 个 problem 的值
\def\getproblemcount #1{\ifcsname label/problem/atchap\number\numexpr #1\relax\endcsname
  \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  {\@nameuse{label/problem/atchap\number\numexpr #1\relax}}{-1}}
% #1+1 个与 #1 个的差 
\def\problemcounterdiff #1{%
  \ifnum\getproblemcount{#1+1}>\z@
    \the\numexpr\getproblemcount{#1+1}-\getproblemcount{#1}\relax
  \else 0???\fi}
\makeatother

然后在 \chapter 开始(或结尾)时,将第 \value{chapter} 个写入 aux 文件:

\renewcommand\chapter{
  ...
  \refstepcounter{chapter}
  ...
  \write@problem@counter{\value{chapter}}
  ...
}

还需在每个问题开始时都递增 problem 计数器。

如果你使用了 unicode-math 宏包,则必须将这重定义的代码放在 \AtBeginDocument 中,或者直接在正文而非导言区修改它。如\AtBeginDocument{\recommand\Re ...},因为 unicode-math 使用这种方式重新定义了 \Re

这个问题涉及到 TeX 的内部处理,最好读过 TeX by topic 的第 1、2 章

首先说说 TeX 是怎样处理一个输入行的。
TeX 从文件中读入一行,去掉行终止符(catcode=5),去掉行尾空格,插入 \endlinechar,一般为 return 字符(ASCII 13)。
然后逐个读取字符,当遇到控制词(转义符+一串catcode=11的字符)或控制空格(转义符+空格字符ASCII 32)时进入状态 S,此状态后续的空格符(catcode=10)被忽略,如果在这个状态遇到行终止符,则连同这个行终止符及本行未读入的字符都被忽略了。

问题出现在 \newenvironment 这一行。
当读到控制序列 \let 后,进入状态 S,随即遇到行终止符 ^^M(ASCII 13),它连同这行未处理的字符都被忽略了。所以正常情况下,一直到文件的结束 TeX 都没有遇到与 { 匹配的那个 }

但为什么你的没有报错呢?是因为你之前把 ^^M 的 catcode 设置为 10 了,这是空格的 catcode,而不是行结束符(catcode=5)的。如果你把之前的 ^^M 的 catcode 设为 5,就会得到 low-level 的错误。

为了正确定义这个环境,需首先修改 ^^M 的 catcode,然后定义完再恢复:

\catcode`\^^M=13 % 这里最好使用注释符
\newenvironment{makeEnterMacro}{\catcode`\^^M\active \let^^M\LaTeX\relax}{\catcode`\^^M=5 }% 同上
\catcode`\^^M=5 % 同上

MWE:

\documentclass[UTF8]{ctexart}\pagestyle{empty}
\begin{document}

\catcode`\^^M=13 %
\newenvironment{makeEnterMacro}{\catcode`\^^M\active \let^^M\LaTeX\relax}{\catcode`\^^M=5 }%
\catcode`\^^M=5 %

\begin{makeEnterMacro}
此环境
怎么就出错了呢
\end{makeEnterMacro}

\end{document}

得到了想要的结果:
image.png

另外,如果你更新到了最新的 LaTeX 发行版(2022-06-01),则可以直接修改 \obeyedline,然后使用 \obeylines

\makeatletter
\newenvironment{mychoices}
  {\def\obeyedline{\@ifnextchar\end{\par}{\item}}\obeylines
    \begin{itemize}}
  {\end{itemize}}
\makeatother

\begin{mychoices}
选
项
\end{mychoices}

\int_step_inline:nn 不能被完全展开,而且 expand 选项只会展开一次,只能使用类似 \int_step_inline:nn {} { \tl_put_right:Nn ... } 的方式将内容存入宏中,然后再在 tblr 中展开这个宏。

\documentclass{ctexart}
\usepackage{tabularray}

\ExplSyntaxOn
% \tl_new:N \l__my_choice_colspec_tl % colspec 选项可要可不要
\tl_new:N \l__my_choice_content_tl
\NewDocumentCommand \choiceTable { +O{} O{1} m m } % tblr options, first num, last num, ...
  {
    % \tl_set:Nx \l__my_choice_colspec_tl { \prg_replicate:nn { #3-#2+2 } { l } } % colspec 选项
    \tl_clear:N \l__my_choice_content_tl
    \tl_put_right:Nn \l__my_choice_content_tl { 题号 }
    \int_step_inline:nnnn {#2} { 1 } {#3}
      { \tl_put_right:Nn \l__my_choice_content_tl { & ##1 } }
    \tl_put_right:Nn \l__my_choice_content_tl { \\ 答案 }
    \tl_put_right:Nx \l__my_choice_content_tl
      { \prg_replicate:nn { #3 - #2 } { & } } % 第二行的 & & & ...
    % \tl_put_right:Nn \l__my_choice_content_tl { \\ } % 最后一个 \\ 可要可不要
    \begin{tblr} [ expand = \l__my_choice_content_tl ] {#1}
      \l__my_choice_content_tl 
    \end{tblr}
  }
\ExplSyntaxOff


\begin{document}

\choiceTable[hlines,vlines]{5}{}

\choiceTable[hlines,vlines][6]{10}{}

\end{document}

image.png

当然,这个实现并不能自动换行,但是也不难实现,只要在适当位置插入 \\ 等内容即可。

\smallcolorbox 的定义中,删掉 tcolorbox 盒子的 breakable 选项即可(或设置它为 false)。

tcolorbox 盒子在另一个盒子中(如 \parbox),breakable 不可用。

另外,\set_wisdom:nn\add_wisdom:nn\use_wisdom: 等名称最好改为 \wisdom_set:nn\wisdom_add:nn\wisdom_use:,模块名应该在前面。

structure.tex 文件中,注释掉这一行即可:

%\usepackage{XCharter} % Use the XCharter fonts

使用 XeTeX 编译时,上面两行也可注释掉:

%\usepackage[utf8]{inputenc} % Required for inputting international characters
%\usepackage[T1]{fontenc} % Output font encoding for international characters

在此环境之前使用 \colorlet{graphicbackground}{white} 就可以了。

默认情况下,graphicbackground 颜色是没有被定义的,这个例子中,TikZ 将其定义为了棕黄色(图片的背景颜色)。

其实就是画两遍,先用背景色画一遍,再用黑色画一遍。

也可以用 preaction 实现,

% \draw [-,line width=8pt,draw=graphicbackground](D) to [bend right, looseness=1] (A);
% \draw (D) to [bend right, looseness=1] node [near start] {b} node [near end] {e} (A);
% 改为
\draw[preaction={draw=white,line width=8pt}] (D) to [bend right, looseness=1] node [near start] {b} node [near end] {e} (A);

这二者还是有细微差别的。

其实需要的就是一个多维数组而已。简单描述一下就是:

a[M][N] = {...} % 以 1 起始
for (i=1; i<=M; i++)
    for (j=1; j<=N; i++)
        node(a[i][j]);

只是在 LaTeX 中(包括 LaTeX3)并没有这样的数据结构。LuaTeX 倒是可以用 table 实现。

要使用宏来实现,简单的就是使用多个 seq 或 clist 或 prop。这样实现的话效率很低。

或者也可以直接用宏保存:

% \@namedef := \expandafter \def \csname #1\endcsname
\@namedef{data@1@1}{A}
\@namedef{data@1@2}{B}
\@namedef{data@2@1}{C}
\@namedef{data@2@2}{D}

然后直接用

% \UseName := \csname #1\endcsname
\foreach \i .....
   \foreach \j .....
     {\node {\UseName{data@\i @\j}};}

使用 tcolorbox,实现了一部分,四个星的内部还要着色有点麻烦。

image.png

\documentclass{ctexart}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, calc, fadings, decorations.markings}
\usepackage{pgfornament}
\usepackage[many]{tcolorbox}

\makeatletter
\definecolor{framegolden}{HTML}{FFA500}
\definecolor{framegray}{HTML}{302E22}
\newdimen\ys@frame@linewidth
\newdimen\ys@frame@radius

\pgfdeclarehorizontalshading{ys@fade@circle}{500bp}
{color(0bp)=(pgftransparent!100); color(25bp)=(pgftransparent!100);
color(45bp)=(pgftransparent!0); color(55bp)=(pgftransparent!0);
color(75bp)=(pgftransparent!100); color(100bp)=(pgftransparent!100)}
\pgfdeclarefading{ys circle}{\pgfuseshading{ys@fade@circle}}
\tcbset{
  ys/frame/line width/.code={\pgfmathsetlength\ys@frame@linewidth{#1}},
  ys/frame/line width=1.4pt,
  ys/frame/radius/.code={\pgfmathsetlength\ys@frame@radius{(#1)*1em}},
  ys/frame/radius=2,
  ys/frame style/.style={
    interior code={
      % 外框
      \path[draw=framegolden,fill=framegray,fill opacity=.2,line width=\ys@frame@linewidth]
        ([xshift=\ys@frame@radius]frame.north west)--([xshift=-\ys@frame@radius]frame.north east) 
        arc(-180:-90:\ys@frame@radius)--
        ([yshift=-\ys@frame@radius]frame.north east)--([yshift=\ys@frame@radius]frame.south east)
        arc(90:180:\ys@frame@radius)--
        ([xshift=-\ys@frame@radius]frame.south east)--([xshift=\ys@frame@radius]frame.south west)
        arc(0:90:\ys@frame@radius)--
        ([yshift=\ys@frame@radius]frame.south west)--([yshift=-\ys@frame@radius]frame.north west)
        arc(-90:0:\ys@frame@radius)--cycle;
      % 内线
      \path[draw=framegolden,line width=.8\ys@frame@linewidth,line cap=round] 
        ([xshift=\ys@frame@radius+2\ys@frame@linewidth,yshift=-1ex]frame.north west)
          --([xshift=-\ys@frame@radius-2\ys@frame@linewidth,yshift=-1ex]frame.north east)
        ([yshift=-\ys@frame@radius-2\ys@frame@linewidth,xshift=-1ex]frame.north east)
          --([yshift=\ys@frame@radius+2\ys@frame@linewidth,xshift=-1ex]frame.south east)
        ([xshift=\ys@frame@radius+2\ys@frame@linewidth,yshift=1ex]frame.south west)
          --([xshift=-\ys@frame@radius-2\ys@frame@linewidth,yshift=1ex]frame.south east)
        ([yshift=-\ys@frame@radius-2\ys@frame@linewidth,xshift=1ex]frame.north west)
          --([yshift=\ys@frame@radius+2\ys@frame@linewidth,xshift=1ex]frame.south west);
      % 四角
      \path[draw=framegolden,line width=1.5\ys@frame@linewidth,line cap=round]
        ([xshift=\ys@frame@radius-2.7\ys@frame@linewidth,yshift=-1ex]frame.north west)
          --([xshift=1ex,yshift=-1ex]frame.north west)
          --([xshift=1ex,yshift=-\ys@frame@radius+2.7\ys@frame@linewidth]frame.north west)
        ([xshift=-\ys@frame@radius+2.7\ys@frame@linewidth,yshift=-1ex]frame.north east)
          --([xshift=-1ex,yshift=-1ex]frame.north east)
          --([xshift=-1ex,yshift=-\ys@frame@radius+2.7\ys@frame@linewidth]frame.north east)
        ([xshift=-\ys@frame@radius+2.7\ys@frame@linewidth,yshift=1ex]frame.south east)
          --([xshift=-1ex,yshift=1ex]frame.south east)
          --([xshift=-1ex,yshift=\ys@frame@radius-2.7\ys@frame@linewidth]frame.south east)
        ([xshift=\ys@frame@radius-2.7\ys@frame@linewidth,yshift=1ex]frame.south west)
          --([xshift=1ex,yshift=1ex]frame.south west)
          --([xshift=1ex,yshift=\ys@frame@radius-2.7\ys@frame@linewidth]frame.south west);
    },
    segmentation code={
      \draw[color=framegolden,path fading=ys circle]
      ([xshift=5\ys@frame@radius]segmentation.west) to[ornament=88]([xshift=-5\ys@frame@radius]segmentation.east);
    },
  },
  ys style/.style={frame hidden,ys/frame style},
}
\makeatother

\begin{document}

\begin{tcolorbox}[enhanced,ys style]
\centering
\medskip
{\zihao{-3}\bfseries 引蝶之章\ 第一幕}
\par\bigskip

{\zihao{2}\bfseries 奈何蝶飞去}

\par\medskip
\tcblower

\centering
\tcbox[enhanced,frame hidden,top=0pt,bottom=0pt,left=4.5em,right=4.5em,
  interior code={\path[fill=framegolden,path fading=ys circle](interior.north west) rectangle (interior.south east);},
]{已开启}
\end{tcolorbox}

\end{document}

问题可简化为

\documentclass[zihao=-4]{ctexart}
\usepackage{geometry}
\geometry{a4paper,left=25mm,right=25mm,top=25mm,bottom=25mm, headheight=20mm}

\usepackage{expl3}
\usepackage{tabularx}
\usepackage{layouts}
\ctexset{linestretch=1.245, autoindent=2\ccwd} 
\begin{document}
 
\ExplSyntaxOn

\begin{tabular*}{\linewidth}{p{0.25\linewidth}p{0.25\linewidth}p{0.25\linewidth}p{0.25\linewidth}}
  \int_step_inline:nn { 4 } { A. 5 \int_compare:nNnTF {#1} = { 4 } { \\ } { & } }
\end{tabular*}
\par
????????

\ExplSyntaxOff

\end{document}

实际还可进一步简化,

\begin{tabular}{l}
A \\ \relax
\end{tabular}
\par
???????

上面这个同样会出现“多余的”空行。
image.png

其原因是,\relax 是在表格新的一行中。这个表格实际有两行,只不过第二行是空白行。

回到你的问题,实际上,将 \int_step_inline:nn 相应的换成 \int_step_function:nN 则不会出现多余的空行。
这涉及到 \int_step_inline:nn 的内部实现。

为了能够处理嵌套的 ...inline:nn 情况,有一个专门记录嵌套数的 int,它在一个新的嵌套开始前加1,在嵌套完成后减 1。在你的代码中,嵌套完成时的最后一个记号是 \\,在这个记号之后,...inline:nn 还会追加一个减 1 的操作,这操作在 LaTeX 看来,语法上并不属于表格的当前行,因为当前行已经在此前的 \\ 处结束了,它是下一行的内容。自然就会留下一个空白行。

想要移除这个空白行也很简单,方法也很多,如自己定义一个不追加加一减一操作的 ...inline:nn

\cs_set_protected:Npn \my_int_step_inline:nn #1#2 
  {
    \cs_gset:Npn \__my_tmp:w ##1 {#2} 
    \int_step_function:nN {#1} \__my_tmp:w
  }

这是完全可行的(要注意全局定义 \__my_tmp:w,因为每一个单元格都在一个组中),只是嵌套使用时会有点小问题。

给出 MWE 以及 log 文件。

是否正确安装了 mtpro2 字体库?

\part 的结构为:

\clearpage (\cleardoublepage)
...
\thispagestyle{<pagestyle>}
...
\newpage
...

由于使用了 \clearpage\newpage,使用 \thispagestyle 无法修改 part 页的 pagestyle。
\chapter 则没有尾部的 \newpage,thispagestyle` 可以生效。

如果使用 titlesec 宏包,它提供了 \assignpagestyle 来修改页面样式。如:

\assignpagestyle{\part}{empty}
\assignpagestyle{\chapter}{empty}

将修改 \part\chapter 的 pagestyle 为 empty。此命令应在 \titleformat{<command>}... 后使用。它可以在任意位置使用,将影响其后的 pagestyle。

当使用 ctex 文档类时,可使用 \ctexset{part/pagestyle=..., chapter/pagestyle=...} 直接设置 pagestyle。但当加载 titlesec 后无效。

对于本例,若要全局修改,只需在导言区使用:

%\usepackage{titlesec}
\titleformat{\part}[display]{\Huge\bf}{第\thepart 部分}{1em}{}
\assignpagestyle{\part}{empty}

若只修改个别,则

\assignpagestyle{\part}{empty}
\part{...}
\assignpagestyle{\part}{plain} % 改回来,默认为 plain

tcolorbox 的每个块默认是单独放在一个 minipage 中的,如果要实现这样的需求,必须使用 \footnotemark\footnotetext 单独设置。

...[title={title\footnotemark}]...

\footnotetext{foot1}

但这样的话标题中的脚注标记与 upper 部分中的标记不同,为此,可以使用 nccfoots 宏包提供的
\Footnotemark\Footnotetext 来设置脚注标记符号。

\documentclass[11pt,twocolumn]{ctexart}
\usepackage{tcolorbox}
\usepackage{nccfoots}
\begin{document}
\begin{tcolorbox}[%colbacktitle=black!10!white,
    title=title\Footnotemark{a}]
\footnotetext[1]{foot1}
    content\footnote[2]{foot2}
\end{tcolorbox}
\end{document}

image.png

使用 caption 宏包提供的 \captionof 命令,可在非浮动体中生成相应的 caption。

\documentclass{article}
\usepackage{caption}
\usepackage{tcolorbox}
\usepackage{hyperref}

\begin{document}

\begin{tcolorbox}
\begin{center}
\includegraphics[width=3cm]{example-image-golden}
\captionof{figure}{test}\label{fig:1}
\end{center}
\end{tcolorbox}

\ref{fig:1}
\end{document}

tl、str、clist、seq、prop 等类型都有对应的 map 函数,

\..._map_function:NN <data> <func>
\..._map_tokens:Nn   <data> <tokens>
\..._map_inline:Nn   <data> <code>

它们将 <func><tokens> 作用于 <data> 的每一项,也即,在 <data> 的每一项前添加 <func><tokens>,变成:

<func> <item1> <func> <item2> <func> <item3> ...

<tokens> <item1> <tokens> <item2> <tokens> <item3> ...

对于 \..._map_inline:Nn 则是先将一个 <temp func> 定义为 <code>,它可使用一个参数,代表当前的 item。再对 <temp func> 使用 \..._map_function:NN

你这个可以用 \tl_map_inline:nn,或者 \clist_map_inline:nn,前者速度更快:

\tl_map_inline:nn { ABCD }
  {
    \exp_args:Nc \NewDocumentCommand { xxColor #1 } { } 
      {
        \bool_lazy_and:nnTF
          { \bool_not_p:n \l_choice_隐藏答案_bool }
          { \use:c { l_choice_ #1 _bool } }
          { { \color{red} \bfseries #1 . } }
          { #1 . }
      }
  }

发布
问题