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

注册于 3年前

回答
184
文章
2
关注者
19

在正常的 LaTeX3 环境(类代码,字符码等)下是一样的。

\cs_new:cn 实际上是 \exp_args:Nc \cs_new:Nn
\exp_args:Nc <#1> <#2>\expandafter<#1>\csname <#2>\endcsname
所以实际上 \cs_new:cn 就是先把第一个参数变成一个控制序列,然后再把 \cs_new:Nn 放在这个控制序列的前面。

难点在于既要使用 alignat 环境(包含编号),又要有大括号,又要跨括号对齐。任意两点其实都不算难,但是三点都要实现就比较麻烦了。这里提供两种并不优雅的解决方案。

一个是使用 array 环境。

% \usepackage{array,multirow}
{\renewcommand\arraystretch{1.3}\[
\begin{array}{r@{} *{2}{r@{}>{{}}c<{{}}@{}} l@{\qquad}r} %% @{} 为了去除间距
\multirow{2}*{$\biggl\{\biggr.$}& x  & + & 3y & = & 11 & (1) \\
                                & 2x & - & y  & = & -9 & (2) \\
\multirow{2}*{result$\biggl\{\biggr.$} & x & = & x_1 &&& (1') \\
                                       & y & = & y_1 &&& (2')
\end{array}
\]}

效果如下:
image.png
这里的大括号是对齐的
image.png
不过编号的位置需要设置,这里使用一个 \quad

另一个就是使用 empheq 宏包的 empheq 环境,该宏包属于 mathtools 的一部分,(详细用法查看其参考文档)。
实际上,不要求括号处对齐是比较容易实现的:

% \usepackage{amsmath,empheq}
\begin{empheq}[left={ }\empheqlbrace]{alignat*=2}
x  &+{}& 3y &= 11, \tag{1} \\
2x &-{}&  y &= -9 \tag{2}
\end{empheq}

\begin{empheq}[left=\llap{result}\empheqlbrace]{align*}
x&=x_1, \tag{1'} \\
y&=y_1 \tag{2'}
\end{empheq}

image.png

如果在括号处对齐则需要半手动调整间距了:

% \usepackage{amsmath,empheq}
\newdimen\tmpadim
\newdimen\tmpbdim
%% 这两个是为了计算宽度
\settowidth\tmpadim{$
  \begin{alignedat}{2}
    x  &+{}& 3y &= 11, \\
    2x &-{}&  y &= -9 
  \end{alignedat}
$}
\settowidth\tmpbdim{$
  \begin{aligned}
    x &= x_1, \\
    y &= y_1
  \end{aligned}
$}

\begin{empheq}[left={ }\empheqlbrace]{alignat*=2}
x  &+{}& 3y &= 11, \tag{1}\label{eq:1} \\
2x &-{}&  y &= -9 \tag{2}
\end{empheq}

\begin{empheq}[left=\llap{result}\empheqlbrace]{align*}
x&=x_1, \hspace{\dimexpr\tmpadim-\tmpbdim} \tag{1'}\label{eq:1'} \\ % 插入一个间距
y&=y_1 \tag{2'}
\end{empheq}

\eqref{eq:1} and \eqref{eq:1'}

image.png
括号处是对齐的:
image.png

我们知道,如果一个宏是使用如下方式定义的:

\def\foo#1\T{something #1 else...}

那么在使用该宏时必须使用 \T 作为(第一个)参数的分隔符,也就是必须使用

\foo balabala\T

如若没有 \T,TeX 将会报错。

你的代码就是这种错误。

因为使用了 \cs_new:Npn \__tk_before_slashsearch:w #1 / #2 \s_stop,所以参数分隔符 /\s_stop 是必须给出的。
但是 \clist_map_function:NN <clist> <func> 所做的仅仅是把 <clist><item> 置于 <func> 之后,也就是

\__tk_before_slashsearch:w <item>

这样 \s_stop 是没有的,所以必须通过一个辅助函数给出,也就是原来 \__tk_slashed_items:n 的作用之一。

因为这里的 \tk_iteratesearch:N 必须可扩展,所以不能使用 \clist_map_inline:Nn

没懂你想干什么。但是呢 LaTeX3 提供了一个 \cs_to_str:N 命令,用于输出控制序列的名字。

\documentclass{article}

\ExplSyntaxOn
\cs_new_protected_nopar:Npn \csusewithname #1
  {
    \cs_to_str:N #1
    #1
  }
\ExplSyntaxOff

\begin{document}

\csusewithname\section{sec 1}

\csusewithname\label{lab:1}
\ref{lab:1}

\end{document}

image.png

出现这种情况是因为 extarrows 宏包内部使用了 amsmath 宏包的 \ext@arrow 命令,该命令的第 #6#7 参数对应于 \xlongrightarrow[<#6>]{<#7>}。只是这 #6#7 会被使用两次,一次用于测量盒子的宽度,另一次则用于输出。(见 \ext@arrow 的定义,位于 amsmath.sty

知道这个就容易修改了:

\makeatletter
\newif\ifext@arrow@measuring@
\let\saved@ext@arrow\ext@arrow % 保存原始定义
\def\ext@arrow#1#2#3#4#5#6#7{%
  \mathrel{\mathop{%
    \setbox\z@\hbox{#5\displaystyle}%
    \ext@arrow@measuring@true% 增加一个
    \setbox\tw@\vbox{\m@th
      \hbox{$\scriptstyle\mkern#3mu{#6}\mkern#4mu$}%
      \hbox{$\scriptstyle\mkern#3mu{#7}\mkern#4mu$}%
      \copy\z@
    }%
    \hbox to\wd\tw@{\unhbox\z@}}%
  \ext@arrow@measuring@false% 增加一个,实际上是不需要的,由于 \mathop 构建一个组
  \limits
    \@ifnotempty{#7}{^{\if0#1\else\mkern#1mu\fi
                       #7\if0#2\else\mkern#2mu\fi}}%
    \@ifnotempty{#6}{_{\if0#1\else\mkern#1mu\fi
                       #6\if0#2\else\mkern#2mu\fi}}}%
}
% 直接写 \def\arrowmeasuring#1#2{\ifext@arrow@measuring#1\else#2\fi} 也可以
\def\arrowmeasuring{\ifext@arrow@measuring@\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}

\def\fake@footnotemark{\textsuperscript{\the\numexpr\value{footnote}+1\relax}}
\def\longrightmark{\arrowmeasuring{\fake@footnotemark}{\footnotemark}} % 增加一个判断
\makeatother

然后呢就可以使用

\begin{tabular}{cc}
  a & b \\
  $\xlongrightarrow{x + y \longrightmark}$ & d
\end{tabular}
\footnotetext{note1}

或者

\begin{table}[htbp]
  \begin{tabular}{cc}
    a & b \\
    $\xlongrightarrow{x + y \arrowmeasuring{\csname fake@footnotemark\endcsname}{\tablefootnote{note2}}}$ & d
  \end{tabular}
\end{table}

都能正确生成了。

一个更好的办法是使用 etoolbox 宏包的 \patchcmd 命令,而不直接重定义 \ext@arrow

%\usepackage{etoolbox}
\patchcmd\ext@arrow{\mathop}{\ext@arrow@measuring@true\mathop}{}{}
% 不在 \mathop 之内,必须加上
\patchcmd\ext@arrow{\limits}{\ext@arrow@measuring@false\limits}{}{}

完整的例子:

\documentclass[UTF8,11pt]{ctexart}
\usepackage{hyperref}
\usepackage{extarrows}
\usepackage{tablefootnote}

\usepackage{etoolbox}

\makeatletter
\newif\ifext@arrow@measuring@
\let\saved@ext@arrow\ext@arrow % 保存原始定义
\def\fake@footnotemark{\textsuperscript{\the\numexpr\value{footnote}+1\relax}}
\patchcmd\ext@arrow{\mathop}{\ext@arrow@measuring@true\mathop}{}{}
\patchcmd\ext@arrow{\limits}{\ext@arrow@measuring@false\limits}{}{}
\def\arrowmeasuring#1#2{\ifext@arrow@measuring@#1\else#2\fi}
\def\longrightmark{\arrowmeasuring{\fake@footnotemark}{\footnotemark}}
\def\amsmeasuring#1#2{\ifmeasuring@#1\else#2\fi}
\makeatother

\begin{document}

\begin{tabular}{cc}
  a & b \\
  $\xlongrightarrow{x + y \longrightmark}$ & d
\end{tabular}
\footnotetext{note1}

\begin{table}[htbp]
  \begin{tabular}{cc}
    a & b \\
    $\xlongrightarrow{x + y \arrowmeasuring{\csname fake@footnotemark\endcsname}{\tablefootnote{note2}}}$ & d
  \end{tabular}
\end{table}

\end{document}

image.png

image.png

\ext@arrow 的修改应该是不会影响正常使用的。这对于所有使用 \ext@arrow 定义的命令都是有效的,如 \xrightarrow 等。

另一个方案见:https://tex.stackexchange.com/questions/335968/skipped-footnote-numbers-in-math-mode

不建议在数学模式下使用 footnote

应该是vscode的配置问题。LaTeX Workshop 配置有点迷。

宏包本身没有冲突。

而且,listingminted 使用一个就好了。

newtxmath 宏包应该没有 \wideparen 命令。

为了解决这一点,只要在 newtxmath 宏包加载前使用 \let\widering\relax 取消 \widering 的定义即可,因为 newtxmath 也定义了同样的命令。

\usepackage{yhmath}%为了使用该宏包里的圆弧帽命令wideparen{}
\let\widering\relax
\usepackage{newtxtext}
\usepackage{newtxmath}

cases 环境无法做到这一点,本质上,cases 环境只是两列的 array 环境。

考虑使用 amsmath 宏包的 alignat 环境(的 inline 版 alignedat)。括号使用 \left\{ \right.cases 环境也是使用该方法实现)。

四.已知线性方程组 $\left\{\begin{alignedat}{3}
% 这里的 {} 是为了保持+的间距,并不优雅
3\lambda     &x_{1} +{}&(2\lambda +1) &x_{2} +{}&(\lambda+1) x_{3} &=\lambda\\
(2\lambda+1) &x_{1} +{}&(2\lambda +1) &x_{2} +{}&(\lambda-2) x_{3} &=\lambda+1\\
(4\lambda-1) &x_{1} +{}&     3\lambda &x_{2} +{}&  2\lambda  x_{3} &=1
\end{alignedat}\right.$.
求$\lambda$为何值时,方程组无解,有唯一解,有无穷多解?

image.png

\IfBooleanTF{#1}
        {}
        {
            \int_add:Nn \l_counter_tl {1}
            {
                \heiti
                \color{\tl_use:N \l_color_tl}
                \Large 
                \int_use:N \l_counter_tl 
            } 
        }

直接写就可以了,\int_... 会自动展开。当然也可以使用 \exp_after:wN \int_... \l_counter_tl,不过 \exp_after:wN 是多余的。

你也可以在 \str_case:nn 中使用 \tl_set_eq:NN \l_counter_tl \..._int。这是因为 \tl_set_eq:NN 就是 \let

另外 \color 中的 \tl_use:N 是不必要的,它会自动扩展。(而且 \tl_ue:N 实际上只是检查了一下命令是否存在)
(而 \color_select:n 则必须首先扩展。)

\int_add:Nn .. 1 可简写为 \int_incr:N ..,并且速度更快。

(LaTeX3的命名规范,变量:\⟨scope⟩_⟨module⟩_⟨description⟩_⟨type⟩,函数:\⟨module⟩_⟨description⟩:⟨arg-spec⟩moduledescription 应该用_分隔,module一般是必须的。)

使用 hyperref 宏包后,\newlabel 的第二个参数需要5个值。

\makeatletter
\bgroup\catcode`\ =9 \endlinechar=-1 % 简单模拟LaTeX3环境
\newcounter{probdaily} % \int_new:N \g_probdaily_counter_int
\AfterLastShipout{
  \immediate\write\@auxout
    {\string\newlabel{ProbdailyTotal}
      {
        {\the\c@probdaily} % \int_use:N \g_probdaily_counter_int
        {}
        {}
        {}
        {}
      }
    }
}
\egroup
\makeatother

LaTeX2e 2020-10-01 版本之后,ateveryend 宏包是不需要的,\AfterLastShipout 已原生提供。

\documentclass{article}
\usepackage{hyperref}

\makeatletter
\bgroup\catcode`\ =9 \endlinechar=-1
\newcounter{probdaily}
\AfterLastShipout{
  \immediate\write\@auxout
    {\string\newlabel{ProbdailyTotal}
      {
        {\the\c@probdaily}
        {}
        {}
        {}
        {}
      }
    }
}
\egroup
\makeatother

\begin{document}

Hello, \LaTeXe.

\stepcounter{probdaily}

\stepcounter{probdaily}

\ref{ProbdailyTotal} = 3

\stepcounter{probdaily}

\end{document}

image.png

ntheorem 宏包的 \thref 命令即提供此功能。查看文档第2.7节、3.2.1节、4.1节。
并且兼容已有的定理环境。

\documentclass[11pt]{ctexart}
\usepackage{amsmath}
\usepackage[amsmath,hyperref,thref]{ntheorem} % 注意 amsmath 和 hyperref 选项
\usepackage{hyperref}

\newtheorem{theorem}{定理}[section]
\renewcommand\thetheorem{\arabic{theorem}}
\newtheorem{corollary}{推论}[theorem]
\renewcommand\thecorollary{\arabic{corollary}}

\begin{document}

\section{test}

\begin{theorem}\label{th1}
  S = ah
\end{theorem}

\begin{corollary}\label{co1}
  abcd
\end{corollary}

% 不空白      和有空白
见\thref{th1} 和 \thref{co1}. 
% 之所以出现的是“定理1.1”和“推论1.1.1”是因为ntheorem宏包暂不支持重定义 `\the<theorem>`。

\end{document}

image.png

但是由于 ntheorem 宏包不支持重定义 \the<theorem>,此时可使用 cleveref 宏包的 \crefformat{}{} 命令修改:

% \usepackage{cleveref}
%\renewcommand\the....
\crefformat{theorem}{#2定理 #1#3}
\crefformat{corollary}{#2推论 #1#3}

完整的例子如下:注意此时 ntheorem 宏包是不需要的。

\documentclass[11pt]{ctexart}
\usepackage{amsmath}
% \usepackage[amsmath,thref,hyperref]{ntheorem}
\usepackage{hyperref}
\usepackage{cleveref}
\def\thref{\cref}

\newtheorem{theorem}{定理}[section]
\renewcommand\thetheorem{\arabic{theorem}}
\crefformat{theorem}{#2定理 #1#3}
\newtheorem{corollary}{推论}[theorem]
\renewcommand\thecorollary{\arabic{corollary}}
\crefformat{corollary}{#2推论 #1#3}

\begin{document}

\section{test}

\begin{theorem}\label{th1}
  S = ah
\end{theorem}

\begin{corollary}\label{co1}
  abcd
\end{corollary}

见\thref{th1} 和 \thref{co1}.

\hyperref[th1]{定理 1} 和 \hyperref[co1]{推论 1}

\end{document}

image.png

若要将全文的公式全都靠左,只要使用 fleqn 文档类选项:

\documentclass[fleqn]{article}

若要将单个公式靠左,使用 amsmath 宏包的 flalignflalgin* (无编号)环境:

% \usepackage{amsmath}
普通
\begin{equation}
E^2=m^2c^4+c^2p^2
\end{equation}

首尾各一个 \&
\begin{flalign}
& E^2=m^2c^4+c^2p^2 &
\end{flalign}

尾部两个 \&
\begin{flalign}
E^2=m^2c^4+c^2p^2 & &
\end{flalign}

多行只要最后一行加 \&
\begin{flalign}
& E^2=m^2c^4+c^2p^2 \\
& E=mc^2 &
\end{flalign}

或者都加 \&
\begin{flalign}
& E^2=m^2c^4+c^2p^2 & \\
& E=mc^2 &
\end{flalign}

右在前面加两个 \&
\begin{flalign}
&& E^2=m^2c^4+c^2p^2 \\
&& E=mc^2 
\end{flalign}

无编号
\begin{flalign*}
& E^2=m^2c^4+c^2p^2 \\
& E=mc^2 &
\end{flalign*}

image.png

不能。 至少texlive2020。应该使用更新的版本(texlive2021)。

一个可行的方案见:https://tex.stackexchange.com/questions/520034/fallback-for-harfbuzz-fonts

LuaTeX 下使CJK字符的排版是通过 luatexja 宏包实现的,而 XeTeX 下则是通过 xeCJK 实现。
latexja 是使用 lua (harfbuzz) 直接修改底层代码,xeCJK 通过在宏层面来实现(通过 \xeCJK_glyph_if_exist:N.. 判断每一个字符在当前字体下是否有glyph,若没有则依次在给定的FallBack字体下查找)。和上面的链接原理上是一致的。这个对于没有字体相关知识的人来说还是不要瞎折腾了。

但是呢,ctex 在 LuaTeX 下提供了 AlternateFontCharRange 特性,你可以通过它们来设置字符在 Range 中的字体。

\documentclass{article}
\usepackage{ctex}

\setCJKfamilyfont{simsong}{FZFangSong-Z02S}% 方正仿宋简体
\setCJKfamilyfont{bigsong}{FZFangSong-Z02S}
  [
    AlternateFont={
      {big}{KaiTi}, % 楷体
    }
  ]

\ctexset{
  declarecharrange={
    {big} { "9FA0 -> "9FA5 },
  },
}

\begin{document}
\Huge
\def\testchars{\char"9F99\char"9F9A\char"9F9B\char"9FA0\char"9FA1\char"9FA2\char"9FA5}
{
\CJKfamily{simsong}
\testchars
}
{
\CJKfamily{bigsong}
\testchars
}

\end{document}

image.png

不过这个会将字符 Range 都设为相同的字体,与 FallBack 不同。
但是你可以使用 harfbuzz 的 Face:collect_unicodes() 函数来判断是否存在该字形。

如果在 LaTeX 下,还是老老实实用 XeTeX 吧。
当然,你可以用 ConTeXt,它完全支持 FallBack 特性,也没有断行问题。

另外再多说一句,你说的“影响断行算法”,不过是影响 xeCJK 插入的glue而导致使用颜色和不使用颜色断行位置的差异。但是这个差异是完全可以很容易消除的。

例如,使用 \raggedright 强制左对齐:

\documentclass{book}
\usepackage{ctex}
\usepackage{xcolor}

\raggedright
\setlength\parindent{2\ccwd}

\newcommand{\book}[1]{#1}
\newcommand{\testtext}{補\sm{史記}的\zm{褚先生}名\sm{少孫},%
是\zm{漢朝}\zm{元}\zm{成}間的一個博士。}

\begin{document}
\Huge

\newcommand{\sm}[1]{\textcolor{red}{#1}}
\newcommand{\zm}[1]{\textcolor{blue}{#1}}
\testtext

\renewcommand{\sm}[1]{#1}
\renewcommand{\zm}[1]{#1}
\testtext

\end{document}

image.png

或者修改 CJKglue

发布
问题