(자동) LaTeX 소스 파일에 주석을 달아 읽기 쉽도록 만듭니다.

(자동) LaTeX 소스 파일에 주석을 달아 읽기 쉽도록 만듭니다.

다음을 수행하는 간단한 방법을 찾고 있습니다.

입력하다:

\begin{document}
...
\section{}
...
\subsection{}
...
\subsubsection{}
...
\section{}
...
\end{document}

산출:

\begin{document}
...
%1
\section{}
...
%1.1
\subsection{}
...
%1.1.1
\subsubsection{}
...
%2
\section{}
...
\end{document}

이것의 목적은 긴 문서를 더 읽기 쉽게 만드는 것입니다. 나는 문서의 전체 구성에서 내가 어디에 적합한지 항상 알고 싶습니다.

답변1

여러 번 작동하는 빠른 솔루션이 있습니다. 이는 개인적인 용도로만 사용 가능합니다(1). 내부 편집, 오류 제어 등을 추가하여 개선될 수 있습니다. 그러나 나는 그것이 또한 유용하다고 생각한다. 아이디어는 LaTeX 번호 매기기 자체를 활용하는 것입니다.

따라서 먼저 문서에 태그를 추가해야 합니다(어쨌든 좋습니다).

\documentclass[12pt]{article}
\begin{document}
\section{a}
\label{sec:a}

\section{b}
\label{sec:b}

\subsection{b a}
\label{sec:ba}

\newpage

\subsection{b b}
\label{sec:bb}

\section{c}
\label{sec:c}
\end{document}

다음으로 Latex를 이전과 같이 실행합니다 walla.tex. 이제 이 작은 Python 스크립트를 실행합니다.

#!/usr/bin/env python
#
# 
import sys
import re

labels=[]
# build a list of label
for l in open(sys.argv[1] + ".aux"):
    if l.find("newlabel{") != -1: 
        m = re.search(r'\\newlabel{(.*?)}{{(.*?)}{(.*?)}}', l)
        if m:
            labels.append("label: %s will be number: %s at page: %s" % (
                m.group(1), m.group(2), m.group(3)))
        else:
            labels.append(l)

# scan input file
for l in  open(sys.argv[1] + ".tex"):
    if l.find("\\label") != -1:
        # we have a label, try to match it
        m = re.search(r'\\label{(.*?)}', l)
        # if not m: continue ERROR not managed here
        key = m.group(1) 
        for lab in labels:
            if lab.find(key) != -1:
                # modify this to pretty print
                sys.stdout.write("%%%%%% %s\n" % lab.strip())
                break
    # output the tex file avoiding old ones
    if not l.startswith(r'%%% label'):
        sys.stdout.write(l)

를 호출 find_tex_labels하고 실행 가능하게 만든 다음 실행합니다 find_tex_labels walla > walla_annotated.tex(인수에는 확장자가 없습니다).

출력에 주석이 달린 LaTeX 파일이 표시됩니다.

\documentclass[12pt]{article}
\begin{document}
\section{a}
%%% label: sec:a will be number: 1 at page: 1
\label{sec:a}

\section{b}
%%% label: sec:b will be number: 2 at page: 1
\label{sec:b}

\subsection{b a}
%%% label: sec:ba will be number: 2.1 at page: 1
\label{sec:ba}

\newpage

\subsection{b b}
%%% label: sec:bb will be number: 2.2 at page: 2
\label{sec:bb}

\section{c}
%%% label: sec:c will be number: 3 at page: 2
\label{sec:c}
\end{document}

...이것은 모든 태그에 적용됩니다. LaTeX가 없는 장치에서 편집할 때 방정식 등을 상호 참조하는 데 매우 유용하다고 생각합니다. 이제 원본 walla.tex를 새 것으로 교체할 수 있습니다.

동기화를 유지하는 것은 귀하의 책임입니다. 어디에서나 "%%% 라벨" 주석을 사용하지 마십시오.


각주:

(1) 나는 그것을 완벽하게 하겠다고 여러 번 약속했습니다. 그러다가 그것을 사용하는 유일한 사람이라는 점을 고려하여 오류가 나타나면 수정하고... 정리할 시간이 없습니다.

답변2

상대적으로 어려운 부분은 다음 줄이 부분 표시자인 경우 업데이트가 필요한지 확인하기 위해 주석 줄을 버퍼링해야 한다는 것입니다. 해당 데이터가 동일한 행이나 다음 행에 있으면 훨씬 더 간단합니다.

다음이 도움이 될 것입니다. 호출할 수도 python script.py input output있고, 출력을 생략하고 표준 출력에 쓸 수도 있습니다. "python script.py xx.tex xx.tex"를 수행하는 대신 임시 파일에 쓰고 원본 파일에 다시 복사하세요.

이렇게 하면 양식의 기존 행이 업데이트되어 변경되지 않은 %x.y.z rest of comment채로 유지됩니다 rest of comment. 해당 주석이 아직 없으면 삽입됩니다. 세그먼트화된 명령과 마찬가지로 특수 주석도 행의 시작 부분에서 시작해야 합니다.

import sys

class ProcessLaTeX:
    def __init__(self, ifp, ofp):
        self.ofp = ofp
        self.prev_comment = None
        self.level = []
        for line in ifp:
            self.process(line)
        # emit last line if comment
        if self.prev_comment:
            self.ofp.write(self.prev_comment)

    def output(self, line):
        pass

    def process(self, line):
        if line[0] == '%':
            # store comment line, emitting any previously stored line
            if self.prev_comment:
                self.ofp.write(self.prev_comment)
            self.prev_comment = line
            return
        lvl = self.check_level(line)
        if lvl > -1:
            self.output_level_comment(lvl)
        if self.prev_comment:
            self.ofp.write(self.prev_comment)
            self.prev_comment = None
        self.ofp.write(line)

    def output_level_comment(self, lvl):
        if self.prev_comment: # check if we overwrite an old one
            # do not use the starting '%' and final newline
            words = self.prev_comment[1:-1].split(' ', 1)
            for c in words[0]:
                if c not in '01234567890.':
                    self.ofp.write(self.prev_comment)
                    self.prev_comment = None
                    break
        self.level.append(0) # in case this is a deeper level
        self.level[lvl] += 1
        self.level = self.level[:lvl+1] # cut of excess levels
        lvls = '%' + '.'.join([str(l) for l in self.level])
        if self.prev_comment: # overwrite the previous words[1]
            words[0] = lvls
            outs = ' '.join(words)
            if not outs[-1] == '\n':
                outs += '\n'
            self.prev_comment = None
        else:
            outs = lvls + '\n'
        self.ofp.write(outs)

    def check_level(self, line):
        if line and not line[0] == '\\':
            return -1
        cmd = line[1:].split('{', 1)[0]
        try:
            res = ['section', 'subsection', 'subsubsection',
                     'paragraph', 'subparagraph'].index(cmd)
        except ValueError:
            return -1
        return res

out = sys.stdout if len(sys.argv) < 3 else open(sys.argv[2], 'w')
pl = ProcessLaTeX(open(sys.argv[1]), out)

답변3

내 생각엔 당신이 찾고 있는 nl것은섹션 구분 기호옵션. 에서 info nl:

  • nl입력을 (논리적) 페이지로 나눕니다. 각 논리적 페이지 상단의 줄 번호는 기본적으로 1로 재설정됩니다. nl모든 입력 파일을 단일 문서로 처리합니다. 파일 간의 줄 번호나 논리적 페이지를 재설정하지 않습니다.

  • 논리 페이지는 세 부분으로 구성됩니다.머리글,, 그리고보행인. 모든 섹션은 비어 있을 수 있습니다. 각각은 다른 스타일과 다른 스타일로 번호가 매겨질 수 있습니다.

  • 논리 페이지의 각 섹션 시작은 입력 파일에서 다음 구분 기호 문자열 중 정확히 하나를 포함하는 줄로 표시됩니다.

    • \:\:\:- 제목의 시작 부분
    • \:\: - 주제의 시작 부분
    • \: - 바닥글의 시작 부분입니다.

명령줄에서 설정할 수 nl있는 논리적 페이지 제한기입니다 . 예를 들면 다음과 같습니다.-d

nl -dCC <infile

...어디CC\:문서에 표시된 문자를 대체할 두 문자를 나타냅니다 . 귀하의 의견을 고려할 때 이것이 필요하다고 생각하지 않습니다. 해당되는 경우 기본값을 삽입하고 일부 입력 필터링을 수행하면 됩니다. 이는 자체적으로 재귀적으로 필터링하도록 설계된 쉘 함수 nl와 쌍을 이룹니다.sed

sd() { n='
';     nl -bp"^\\\\$1section" -w1 -s"$n\:\:\:$n" |
       sed '/./!d;/^[0-9]/!s/^[[:blank:]]*//;/^%[0-9.]*$/h;t
            s/./%&/;x;/%/G;s//./2;/\n.*/h;s///;x;s/\n//;N
            s/\(\(.*\)\(\n\)\)\(\(.*\)\(..\)\)/\4\3\1\5/'
}

예제 데이터와 비슷한 것을 입력하고 출력을 몇 번 다시 파이프로 연결했습니다.

sd <<\IN |sd sub | sd subsub | sd subsubsub
\begin{document}
\section{}
some ordinary lines
\subsection{}
whatever
\subsubsection{}
\subsection{}
\subsubsection{}
\subsubsubsection{}
\section{}
\subsection{}
\end{document}
IN

위에 인쇄된 대로 실행합니다.

\begin{document}
%1
\section{}
some ordinary lines
%1.1
\subsection{}
whatever
%1.1.1
\subsubsection{}
%1.2
\subsection{}
%1.2.1
\subsubsection{}

\:\:\:
%1.2.1.1
\:\:
\subsubsubsection{}
%2
\section{}
%2.1
\subsection{}
\end{document}

보시다시피 필터 작업은완전히완료되었지만 작업이 완료된 것 같습니다. 입력 본문은 입력 내용에 따라 번호가 매겨지며, nl각 논리 페이지 수를 세기 시작합니다.-b-bp'attern'오직논리적 페이지 헤더 구분 기호입니다 \:\:\:.

따라서... 출력을 필터링합니다. 이미 sed구분 기호 arg에 구분 기호 세트가 포함되어 있으며 기본적으로 다음 단계에서 부분 구분 기호를 찾을 수 있도록 약간 재정렬합니다. 그러나 이전 공간에 마지막 줄의 복사본도 유지합니다. 숫자로 시작하는 줄을 만났을 때 예약된 공간이 비어 있지 않으면 해당 줄을 예약된 공간의 내용에 추가하고 그 뒤에 . 그리고 감자도요.nl-ssednlsed^%[0-9.]*$h.

그래도 - 내가 말했듯이 아직 끝나지 않았습니다. 마지막으로 출력에 섹션 구분 기호와 빈 줄이 남았습니다. 따라서 청소하려면 다음을 수행하십시오.

sd <<\IN |sd sub | sd subsub | sd subsubsub | grep -v '^\\:\|^$'
\begin{document}
\section{}
some ordinary lines
\subsection{}
whatever
\subsubsection{}
\subsection{}
\subsubsection{}
\subsubsubsection{}
\subsubsection{}
\subsubsubsection{}
\section{}
\subsection{}
\end{document}
IN

산출:

\begin{document}
%1
\section{}
some ordinary lines
%1.1
\subsection{}
whatever
%1.1.1
\subsubsection{}
%1.2
\subsection{}
%1.2.1
\subsubsection{}
%1.2.1.1
\subsubsubsection{}
%1.2.2
\subsubsection{}
%1.2.2.1
\subsubsubsection{}
%2
\section{}
%2.1
\subsection{}
\end{document}

관련 정보