“有意义的”日志条目定义:

“有意义的”日志条目定义:

我正在基于上下文日志条目。每次选定的(修补的)宏被调用时,它应该提供其内容以及有意义的日志条目。

“有意义的”日志条目定义:

每个自定义日志条目提供以下上下文:

  • 节计数器值
  • 章节标题
  • 页码
  • 文件名/路径
  • 电话号码

这就是我要的

<macro content> (<section counter value>:<section title>:<page number>:<file>:<line number>)

问题

我猜我有两个问题:

  1. \thetitle当其中一个选定的宏属于分段命令本身时进行处理。
  2. 在使用宏的情况下,将扩展宏的完整值作为字符串放入日志中\myproduct

我如何实现“有意义的”日志条目

  • \thetitle 获取部分计数器 titlesec
  • \@currentlabelname 获取章节标题 titlesec提供\def\@currentlabelnamenameref(我仅使用直类测试了这一点,即没有底线标题的类)
  • \thepage 获取页面乳胶
  • \the\inputlineno 获取行号LaTeX(使用时指的是当前文件中的 lineno \input
  • max_print_line=10000扩展texmf.cnf日志输出中每行的最大字符数(与这个问题无关,但对于可能还想实现自定义日志的人来说相关)

希望我上面所说的事实是正确的。

问题 2(几乎可以工作,排版良好)

有时我的章节标题包含宏。这可能会导致扩展问题。此外,有时章节标题包含我正在跟踪的宏,这使得\thetitle在日志条目中使用它会变得很棘手,\section{About \myproduct{monkey shampoo}}例如应该产生例如MacGyver.monkey shampoo (2:About MacGyver.monkey shampoo:[1]:test.tex:11)

\documentclass{article}
\usepackage{fontspec}% use xelatex
\usepackage{titlesec}% adds \thetitle and \@currentlabelname
\usepackage{currfile}% adds \currfilepath

% Define a couple commands to track
\newcommand\myapp[1]{\textit{#1}}
\newcommand\myproduct[1]{MacGyver.\textit{#1}}% Purposefully made this one contain more text that what is saved in #1

% The following is normally put into separate file as to modularize the application of patches
% Define a context macro as described
\makeatletter
\def\contextinfo{\thetitle:\@currentlabelname:[\thepage]:\currfilepath:\the\inputlineno}
\makeatother
% Apply Patches
\usepackage{regexpatch}
\xapptocmd{\myapp}{\typeout{ ==> #1 (\contextinfo)}}{}{}
\xapptocmd{\myproduct}{\typeout{ ==> #1 (\contextinfo)}}{}{}% <-- I'd rather show MacGyver.monkey shampoo, but unsure how best to implement
% Note: \typeout is always fully expanded due to \write %http://tex.stackexchange.com/a/60976/13552

\begin{document}
\section{Elephant}
\section{Monkey}
\subsection{Bonabo}
\myapp{listmonkeys}
\myproduct{monkey shampoo}
\end{document}

日志输出

参见上面的问题 2:如何才能让“猴子洗发水“ 是 ”MacGyver.猴子洗发水“或者更简单:MacGyver.\textit{猴子洗发水}

 ==> listmonkeys (2.1:Bonabo:[1]:test.tex:34)
 ==> monkey shampoo (2.1:Bonabo:[1]:test.tex:35)

问题 1(不工作,不排版)

参见上面的问题 1:如何处理在中\thetitle定义的?titlesec\gdef\thetitle{\csname the#1\endcsname}%

\documentclass{article}
\usepackage{fontspec}% use xelatex
\usepackage{titlesec}% adds \thetitle and \@currentlabelname
\usepackage{currfile}% adds \currfilepath

% Define a couple commands to track
\newcommand\myapp[1]{\textit{#1}}
\newcommand\myproduct[1]{MacGyver.\textit{#1}}% Purposefully made this one contain more text that what is saved in #1

% The following is normally put into separate file as to modularize the application of patches
% Define a context macro as described
\makeatletter
\def\contextinfo{\thetitle:\@currentlabelname:[\thepage]:\currfilepath:\the\inputlineno}
\makeatother
% Apply Patches
\usepackage{regexpatch}
\xapptocmd{\myapp}{\typeout{ ==> #1 (\contextinfo)}}{}{}
\xapptocmd{\myproduct}{\typeout{ ==> #1 (\contextinfo)}}{}{}% <-- I'd rather show MacGyver.monkey shampoo, but unsure how best to implement
% Note: \typeout is always fully expanded due to \write %http://tex.stackexchange.com/a/60976/13552

\begin{document}
\section{Elephant \myapp{watcher}}% probably \thetitle has not been set yet, causing error
\section{Monkey \myproduct{monkey shampoo}}
\subsection{Bonabo}
\end{document}

日志输出

! TeX capacity exceeded, sorry [input stack size=5000].

答案1

您必须处理的一个大问题是内容的可扩展性,因为您正在向终端写入内容。为了解决这个问题,我定义了两个版本的\myapp\myproduct函数。常规\myapp\myproduct被声明为健壮的,而\@myapp\@myproduct是可扩展的和简化的版本(例如,删除与字体相关的设置\textit,如)。

我也避免了titlesec并构建我自己的\thenumber(包含章节编号)和\thetitle(包含使用\@myapp和/或的简化版本的章节标题\@myproduct)。

在此处输入图片描述

\documentclass{article}

\usepackage{currfile}% adds \currfilepath

% Define a couple commands to track
\DeclareRobustCommand{\myapp}[1]{\textit{#1}}
\DeclareRobustCommand{\myproduct}[1]{MacGyver.\textit{#1}}
\makeatletter
\newcommand{\@myapp}[1]{#1}
\newcommand{\@myproduct}[1]{MacGyver.#1}
\makeatother

% The following is normally put into separate file as to modularize the application of patches
% Define a context macro as described
\def\contextinfo{\thenumber:\thetitle:[\thepage]:\currfilepath:\the\inputlineno}

% Apply Patches
\usepackage{regexpatch}
\xapptocmd{\myapp}{\typeout{ ==> #1 (\contextinfo)}}{}{}
\xapptocmd{\myproduct}{\typeout{ ==> #1 (\contextinfo)}}{}{}% <-- I'd rather show MacGyver.monkey shampoo, but unsure how best to implement
% Note: \typeout is always fully expanded due to \write %http://tex.stackexchange.com/a/60976/13552

%\usepackage{xparse}% Loaded by regexpatch
\let\oldsection\section
\makeatletter
\RenewDocumentCommand{\section}{s o m}{%
  \begingroup
  % Extract the counter representation
  \stepcounter{section}%
  \xdef\thenumber{\thesection}%
  \addtocounter{section}{-1}%
  % Temporarily change \myapp and \myproduct to be expandable and ordinary
  \let\myapp\@myapp
  \let\myproduct\@myproduct
  % Extract the title with possible \myapp and \myproduct (now ordinary/expandable)
  \protected@xdef\thetitle{#3}%
  \endgroup
  % Regular section
  \IfBooleanTF{#1}
    {\oldsection*{#3}}
    {\IfValueTF{#2}
       {\oldsection[#2]{#3}}
       {\oldsection{#3}}}
}
\makeatother

\begin{document}

\section{Elephant \myapp{watcher}}% probably \thetitle has not been set yet, causing error
\section{About \myproduct{monkey shampoo}}
\subsection{Bonabo}

\end{document}

输出.log

 ==> watcher (1:Elephant watcher:[1]:test.tex:48)
 ==> monkey shampoo (2:About MacGyver.monkey shampoo:[1]:test.tex:49)

答案2

这是你想要的吗?

\documentclass{article}
\usepackage{fontspec}% use xelatex
\usepackage{titlesec}% adds \thetitle and \@currentlabelname
\usepackage{nameref}
\usepackage{regexpatch}

\usepackage{currfile}% adds \currfilepath


% Define a couple commands to track
\newcommand\myapp[1]{\textit{#1}}
\newcommand\myproduct[1]{MacGyver.\textit{#1}}% Purposefully made this one contain more text that what is saved in #1

% The following is normally put into separate file as to modularize the application of patches
% Define a context macro as described

\makeatletter
\def\contextinfo{\thetitle\space:\@currentlabelname:[\thepage]:\currfilepath:\the\inputlineno}
\DeclareRobustCommand{\WriteToLog}[1]{%
  \gdef\@currentlabelname{#1}\immediate\write-1{ ==> #1 (\contextinfo)}
}
\AtBeginDocument{%
\xapptocmd{\myapp}{\WriteToLog{#1}}{}{}
\xapptocmd{\myproduct}{\WriteToLog{#1}}{}{}
}
\makeatother

\begin{document}
\section{Elephant \myapp{watcher}}\label{foo}% probably \thetitle has not been set yet, causing error
\section{Monkey \myproduct{monkey shampoo}}
\subsection{Bonabo}
\end{document}

答案3

“宏追踪器”解决方案 更新 2016-07-12

基于 Werner 的代码,我想出了一个很好的日志解决方案。

在生成干净日志输出的过程中:

##############################################################################
  Document Diagnostics
##############################################################################
Main File: logs.tex
Page Count: 2


 xparsemacro
##############################################################################
--BEGIN-----------------------------------------------------------------------
==> pre-section example (::logs.tex:[1]:144)
==> post-section example (1:Section:logs.tex:[1]:147)
==> post-section example (1.1:Subsection:logs.tex:[1]:150)
==> post-section example (1.1.1:Subsubsection:logs.tex:[1]:153)
==> post-section example (1.1.1.1:Paragraph:logs.tex:[1]:156)
==> in-section call (2:\xparsemacro {in-section call}:logs.tex:[1]:159)
--END-------------------------------------------------------------------------

该代码最适合用作标签的简单、单一输入宏,这些宏可能分散在您的文本中。此外,将环境变量max_print_line设置为高于 79 的数字后,日志看起来会更好。例如,export max_print_line=1000在我的/usr/local/texlive/2016/texmf-dist/web2c/texmf.cnf文件中,我注释掉了

770 %error_line = 79
771 %half_error_line = 50
772 %max_print_line = 79

并将它们添加到/usr/local/texlive/2016/texmf.cnf

 11 error_line = 254
 12 half_error_line = 238
 13 max_print_line = 1000

如何使用

  1. 使用以下方式定义单输入(#1)宏xparse's \NewDocumentCommand (请注意,\newcommand当使用包含类似以下格式化宏时,可能会导致递归调用\texttt
  2. \doforeach{}将宏添加到不带斜线的跟踪宏列表中

实验代码

\listfiles
\documentclass{article}
\usepackage{regexpatch}
\usepackage{xparse}
\usepackage{etoolbox} % define \do
\usepackage{atveryend} % define \AtEndAfterFileList
\usepackage{currfile} % define \currfilepath
% --------------------------------------------------------------------------------------------------
% My Macros (Variable Placeholders)
%
\newcommand\latexmacro[1]{#1}
\newcommand\latexmacrott[1]{\texttt{latex}.#1}
\DeclareRobustCommand{\latexrobusttt}[1]{\texttt{latexrobust}.#1}
\NewDocumentCommand{\xparsemacro}{m}{#1}
\NewDocumentCommand{\xparsemacrott}{m}{\texttt{xparse}.#1}
% --------------------------------------------------------------------------------------------------
% Log Delimiters
%
\catcode`#=12 % Define out log output delimiter lines using # as catcode 12 instead of 6
  \newcommand{\macloglineL}{##############################################################################}
  \newcommand{\macloglineB}{--BEGIN-----------------------------------------------------------------------}
  \newcommand{\macloglineE}{--END-------------------------------------------------------------------------}
\catcode`#=6
% --------------------------------------------------------------------------------------------------
% Initialize Variables and Define Context-specific log entry
%
\def\currnum{}% initialize (for when section not yet typeset)
\def\currtitle{}% initialize (for when section not yet typeset)
\def\contextinfo{\currnum:\currtitle:\currfilepath:[\thepage]:\the\inputlineno}
% --------------------------------------------------------------------------------------------------
% Create loop macro that supports macros as items
%
\makeatletter
\newcommand\doforeach[2]{\renewcommand\do[1]{#2}\docsvlist{#1}}% Needs etoolbox http://tex.stackexchange.com/questions/318875/how-can-i-loop-through-macros-with-foreach-and-pass-them-to-xapptocmd 
% -----------------------------------------------------------------------------------------------
% Make Document Diagnostics Header
%
\def\docdiagnosticsheader{%
\typeout{%
\macloglineL
^^J%
\space\space Document Diagnostics
^^J%
\macloglineL%
^^J%
Main File: \jobname.tex
^^J%
Page Count: \thepage
}
}%
\AtEndAfterFileList{\docdiagnosticsheader}
% Patch loop (syntax: \doforeach{macro,macro,macro}{what to do for each item})
% Patches tag macros
%
\doforeach{latexmacro,latexmacrott,latexrebusttt,xparsemacro,xparsemacrott}{% macro names wmacout slashes
  \expandafter\ifx\csname #1-tracker\endcsname\relax
    % does not exist, so create it
    \expandafter\def\csname #1-tracker\endcsname{^^J^^J #1 ^^J\macloglineL^^J\macloglineB}
  \else
    % exists, do nothing
  \fi
  \expandafter\xapptocmd\csname#1\endcsname{\expandafter\protected@xdef\csname #1-tracker\endcsname{\unexpanded\expandafter\expandafter\expandafter{\csname #1-tracker\endcsname}^^J==> \unexpanded{##1}           (\contextinfo)}}{\typeout{MACMessage: Successfully patched #1}}{\typeout{MACWarning: Failed to patch #1}}% 2 \expandafter needed, yet 3 are here because one is just to prep the \csname token.
\AtEndAfterFileList{\expandafter\typeout{\csname #1-tracker\endcsname^^J\macloglineE}}% Uncomment to enable tracking in log output
}%
\makeatother


% --------------------------------------------------------------------------------------------------
% The following temporarily redefine sectioning commands to extract titleno and title as \currnum and \currtitle, respectively for \contextinfo
%
\let\oldsection\section%  Redefine section to grab number + title when tracking macros
\makeatletter
\RenewDocumentCommand{\section}{s o m}{%
  \begingroup
  \stepcounter{section}% Extract the counter representation
  \xdef\currnum{\thesection}%
  \addtocounter{section}{-1}%
  \protected@xdef\currtitle{#3}% Extract the title wmac possible tracked macros
  \endgroup
  \IfBooleanTF{#1}% Regular section
    {\oldsection*{#3}}
    {\IfValueTF{#2}
       {\oldsection[#2]{#3}}
       {\oldsection{#3}}}
}
\makeatother

\let\oldsubsection\subsection%  Redefine section to grab number + title when tracking macros
\makeatletter
\RenewDocumentCommand{\subsection}{s o m}{%
  \begingroup
  \stepcounter{subsection}% Extract the counter representation
  \xdef\currnum{\thesubsection}%
  \addtocounter{subsection}{-1}% Restore for normal subsection
  \protected@xdef\currtitle{#3}% Extract the title wmac possible tracked macros
  \endgroup
  \IfBooleanTF{#1}% Regular section
    {\oldsubsection*{#3}}
    {\IfValueTF{#2}
       {\oldsubsection[#2]{#3}}
       {\oldsubsection{#3}}}
}
\makeatother

\makeatletter
\RenewDocumentCommand{\subsubsection}{s o m}{%
  \begingroup
  \stepcounter{subsubsection}% Extract the counter representation
  \xdef\currnum{\thesubsubsection}%
  \addtocounter{subsubsection}{-1}% Restore for normal subsection
  \protected@xdef\currtitle{#3}% Extract the title wmac possible tracked macros
  \endgroup
  \IfBooleanTF{#1}% Regular section
    {\oldsubsubsection*{#3}}
    {\IfValueTF{#2}
       {\oldsubsubsection[#2]{#3}}
       {\oldsubsubsection{#3}}}
}
\makeatother

\let\oldparagraph\paragraph%  Redefine section to grab number + title when tracking macros
\makeatletter
\RenewDocumentCommand{\paragraph}{s o m}{%
  \begingroup
  \stepcounter{paragraph}% Extract the counter representation
  \xdef\currnum{\theparagraph}%
  \addtocounter{paragraph}{-1}% Restore for normal subsection
  \protected@xdef\currtitle{#3}% Extract the title wmac possible tracked macros
  \endgroup
  \IfBooleanTF{#1}% Regular section
    {\oldparagraph*{#3}}
    {\IfValueTF{#2}
       {\oldparagraph[#2]{#3}}
       {\oldparagraph{#3}}}
}
\makeatother




\begin{document}
\latexmacro{pre-section example}
\xparsemacro{pre-section example}
\section{Section}
\latexmacro{post-section example}
\xparsemacro{post-section example}
\subsection{Subsection}
\latexmacro{post-section example}
\xparsemacro{post-section example}
\subsubsection{Subsubsection}
\latexmacro{post-section example}
\xparsemacro{post-section example}
\paragraph{Paragraph}
\latexmacro{post-section example}
\xparsemacro{post-section example}
%\section{\latexmacrott{in-section call}}
%\section{\latexrebusttt{in-section call}}
\section{\xparsemacro{in-section call}}
\section{\xparsemacrott{in-section call}}
%\subsection{\latexmacro{in-subsection call}\xparsemacro{in-subsection call}}
%\subsubsection{\latexmacro{in-subsubsection call}\xparsemacro{in-subsubsection call}}
%\paragraph{\latexmacro{in-paragraph call}\xparsemacro{in-paragraph call}}
\end{document}

相关内容