我目前正在编写一种需求分析,并想以某种风格列举我的章节和小节:
我的部分应该看起来像正常的,例如“1.1 文件的导入和导出”,但应该定义一个宏“\startLetter”作为标题的第一个字母(这里是“I”)。
以下子节的枚举应以当前 \startLetter 开头,并具有一个递增的三位标识符,该标识符在下一节开始时重置,例如“I001 文本文件导入”。引用这些时,我只想打印字母 + ID,因此“I001”也仍然通过 hyperref 引用。
我当前的设置如下。问题是
- 我不知道如何缩短引用,只显示 ID,而不破坏超链接,
- 引用时 ID 计数器仍会计数。我确信这是因为宏成为节名称的一部分,因此每次都会重新评估。我该如何停止这种情况?
我研究了 titlesec、xparse 和 etoolbox 的 pretocmd 和 apptocmd,但这需要修补 @ssect 命令(?),而我经验不足,无法编辑 Latex 部分的底层命令。有没有一种“新手可以理解”的方法来解决这个问题?
提前致谢 :)
梅威瑟:
\documentclass[10pt,a4paper]{book}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{xstring}
\usepackage{nameref}
\usepackage{hyperref}
\newcommand{\startLetter}{}
\newcounter{reqID}
\newcommand{\reqSection}[1]{%
\section{#1}
\renewcommand{\startLetter}{\StrMid{#1}{0}{1}}
\setcounter{reqID}{1}
}
\newcommand{\leadingZerosID}{%
\ifnum\value{reqID}<100 0\fi\ifnum\value{reqID}<10 0\fi\arabic{reqID}
}
\newcommand{\reqSubsection}[1]{%
\subsection*{\startLetter\leadingZerosID{} #1}
\stepcounter{reqID}
}
\parindent0mm
\begin{document}
\chapter{Any chapter}
\reqSection{Import Export}
\reqSubsection{Text Files Import}
\label{lbl:import-text}
Some useless blindtext. Some useless blindtext. Some useless blindtext. Some useless blindtext.
\reqSubsection{Text Files Export}
\label{lbl:export-text}
Some useless blindtext. Some useless blindtext. Some useless blindtext. Some useless blindtext.
\reqSubsection{Video Files Import}
\label{lbl:import-video}
Some useless blindtext. Some useless blindtext. Some useless blindtext. Some useless blindtext.
\vspace{1cm}
I am refering to requirement \nameref{lbl:export-text}.
\end{document}
答案1
假设我正确理解了这个问题,我认为这可以满足您的需要。基本思想是使用普通的子部分,更改其标题以满足您的要求。这消除了计数器的问题,并允许您使用普通命令\ref
按 ID 号引用。
\documentclass{book}
\makeatletter
\def\firstchar#1{\firstchar@internal#1\relax}
\def\firstchar@internal#1#2\relax{#1}
\makeatother
\newcommand{\reqSection}[1]{%
\section{#1}
\xdef\startLetter{\firstchar{#1}}
}
\newcommand{\leadingZerosSS}{%
\ifnum\value{subsection}<100 0\fi\ifnum\value{subsection}<10 0\fi\arabic{subsection}
}
\renewcommand\thesubsection{\startLetter\leadingZerosSS{}}
\usepackage{hyperref}
\begin{document}
\chapter{Any chapter}
\reqSection{Import Export}
\subsection{Text Files Import}
\label{lbl:import-text}
Some useless blindtext. Some useless blindtext. Some useless blindtext. Some useless blindtext.
\subsection{Text Files Export}
\label{lbl:export-text}
Some useless blindtext. Some useless blindtext. Some useless blindtext. Some useless blindtext.
\subsection{Video Files Import}
\label{lbl:import-video}
Some useless blindtext. Some useless blindtext. Some useless blindtext. Some useless blindtext.
\vspace{1cm}
I am refering to requirement \nameref{lbl:export-text}.
I can refer to the ID using \verb+\ref+ rather than \verb+\nameref+, for example \ref{lbl:export-text}
\end{document}
编辑
由于我没有调查的原因,您的\startLetter
宏对我来说不起作用,所以我自己写了。这个想法(我从 David Carlisle 的回答中学到的)是\firstchar@internal
需要两个参数;#1
是它找到的第一个标记 (*),但#2
必须以 结尾\relax
。#1
作为结果返回,并被#2
忽略。将 (**)\firstchar
附加\relax
到其参数的末尾并将其发送到\firstchar@internal
。所以...
\firschar{abc}
--> \firstchar@internal{abc\relax}
#1 = a
#2 = bc
--> a
(*)它也可能是一组用括号括起来的,但\subsection{{abc} def}
对我来说这似乎不太可能)。
(**) 最初我习惯于a \relax
确保 TeX 会找到两样东西\firstchar{a}
,但实际上这是不必要的,因为在这种情况下#1 = a
和#2
最终会为空。如果您这样做,新实现会导致错误\firstchar{}
,这是有道理的;旧实现将返回a
!