
listings
정규식을 강조 표시하여 일반 문자열 개체처럼 보이도록 패키지를 사용할 수 있는지 알고 싶습니다 . 참고: 정규 표현식의 구문은 문맥에 무관하지 않으므로 사례를 100% 인식하는 솔루션을 기대할 수 없습니다. 어쨌든, 예를 들어 Ruby에서 나는 쓰고 싶습니다.
(/[a-z]+/)
왼쪽 괄호를 기준점으로 사용하여 listings
정규식을 인식하도록 지시합니다 (산술 나누기와 구별하기 위해)./[a-z]+/
(
\lstset{moredelim=[s][\color{red}]{(/}{/}}
그러나 이는 정규 표현식 자체뿐만 아니라 왼쪽 괄호에도 색상을 지정합니다. 파서를 더 잘 이해하기 위해 구문을 다음과 같이 수정했습니다.
\lstset{moredelim=[s][\color{red}\textcolor{black}{:macro:}]{(/}{/}}
그러나 놀랍게도 ":macro:"는 다음에 적용됩니다.각토큰 중: (/
, [
, a
, -
, z
, ]
및 /
, 에 의해 발견되었습니다 moredelim
. 나는 ":macro:"가 다음에 적용될 것이라고 잘못 예상했습니다.전체일치하는 표현 (/[a-z]+/
. 그런데 진술을 이중 별표 버전으로 변경하면 상황은 다음과 같습니다.
\lstset{moredelim=**[s][\color{red}\textcolor{black}{:macro:}]{(/}{/}}
listings
그러나 이 경우 정규 표현식은 표현식 내의 키워드 색상을 지정하여 구문 분석됩니다 . 이것은 내가 원하는 것이 아닙니다. (
정규 표현식을 찾기 위해 앵커로만 사용하고 싶습니다 . 나중에 정규 표현식 자체와 별도로 앵커를 처리하고 싶습니다(다른 색상 제공).
moredelim
구체적으로 말하자면, 해당 항목을 포함하는 첫 번째 토큰만 선택 (/
하고 이를 다른 토큰과 별도로 처리할 수 있는지 알고 싶습니다.
문제를 조사하기 위한 MWE가 여기에 제공됩니다.
\documentclass{article}
\usepackage[english]{babel}
\usepackage{listings}
\usepackage{xcolor}
\lstnewenvironment{lstRuby}{
\lstset{
language={},
moredelim=[s][\color{red}\textcolor{black}{:macro:}]{(/}{/}
}
}{}
\begin{document}
\setlength{\parindent}{0pt}
\ttfamily
This is the code:
(/[a-z]+/)
This is what I want to achieve:
(\textcolor{red}{/[a-z]+/})
This is what I get using listings:
\begin{lstRuby}
(/[a-z]+/)
\end{lstRuby}
\end{document}
답변1
이 답변은 더 이상 질문자와 관련이 없을 수 있습니다. 하지만 이 문제는 해결하기가 상당히 어려웠기 때문에 실제로 해결했어야 했고 다른 사람들과 관련이 있을 수도 있으므로 어쨌든 답변을 게시하겠습니다.
질문과 의견에서 언급했듯이 moredelim=**[s]
변형은 구분된 전체 텍스트를 하나의 단위/그룹으로 처리하므로 구분된 그룹의 시작 부분과 끝 부분(을 통해 \aftergroup
)에 임의의 텍스트를 삽입할 수 있습니다. 문제는 구분 기호 사이의 텍스트에도 다른 스타일이 적용된다는 것입니다. 반면에 는 moredelim=[s]
다른 스타일을 적용하지 않고 동일한 클래스(문자, 기타 등)의 각 문자 덩어리에 구분 기호 그룹 스타일을 적용합니다. 이렇게 하면 구분 기호 바로 앞과 뒤에만 텍스트가 삽입되는 것을 방지할 수 있습니다.
원하는 효과를 달성하는 쉬운 방법은 없는 것 같으므로 여기서는 몇 가지 내부 요소를 연결해야 합니다. 및 매크로 \lst@DelimOpen
는 \lst@DelimClose
목록에서 새 구분 기호 쌍이 발견될 때의 작업을 제어합니다. 그래서 우리는 두 개의 후크 \@delim@open@hook
와 를 설치하도록 재정의했습니다 \@delim@close@hook
. 여기에서 우리는 현재 어떤 스타일이 활성화되어 있는지(비교를 통해 \lst@currstyle
) 확인할 수 있으며 그에 따라 적절한 작업을 선택할 수 있습니다. 이 접근 방식을 사용하면 여러 가지 멋진 구분 기호를 병렬로 사용할 수 있습니다. \@delim@close@hook
실행되는 메모~ 전에\aftergroup
마지막 문자 덩어리가 출력되므로 구분된 그룹의 마지막 문자 뒤로 최종 작업을 이동하는 트릭을 다시 사용해야 합니다 .
최종 구현에서는 필드가 출력에서 원래 구분 기호를 제거하는 moredelim=[is][\regexstyle]{(/}{/)}
정규 표현식의 스타일을 정의하는 데 사용됩니다. 정규식의 모든 내부 텍스트에 적용되는 실제 스타일입니다. 여기서는 명확하게 이름이 지정된 래퍼 매크로를 사용해야 합니다. 그렇지 않으면 테스트에서 잘못된 결과가 발생할 수 있습니다. 및 원래 시작 및 끝 구분 기호 위치에 각각 코드를 삽입하는 매크로입니다.i
\regexstyle
\lst@currstyle
\regexstyle@start
\regexstyle@end
전체 예는 다음과 같습니다.
\documentclass{article}
\usepackage{listings}
\usepackage{xcolor}
\lstnewenvironment{lstRuby}{%
\lstset{
language={},
moredelim=[is][\color{green}]{*}{*},
moredelim=[is][\regexstyle]{(/}{/)},
emphstyle=\color{blue},
emph={foo}
}%
}{}
\makeatletter
\let\orig@lst@DelimOpen=\lst@DelimOpen
\def\lst@DelimOpen#1#2#3#4#5#6\@empty{%
\orig@lst@DelimOpen{#1}{#2}{#3}{#4}{#5}{#6}\@empty
\@delim@open@hook
}
\let\orig@lst@DelimClose=\lst@DelimClose
\def\lst@DelimClose{%
\@delim@close@hook
\orig@lst@DelimClose
}
\def\@delim@open@hook{%
\def\@temp{\regexstyle}%
\ifx\lst@currstyle\@temp
\regexstyle@start
\fi
}
\def\@delim@close@hook{%
\def\@temp{\regexstyle}%
\ifx\lst@currstyle\@temp
\aftergroup\regexstyle@end
\fi
}
\def\regexstyle{\color{red}}
\def\regexstyle@start{({\regexstyle /}}
\def\regexstyle@end{{\regexstyle /})}
\makeatother
\begin{document}
\setlength{\parindent}{0pt}
\ttfamily
This is the code:
(/[a-z]+/)
This is what I want to achieve:
(\textcolor{red}{/[a-z]+/})
This is what I get using listings:
\begin{lstRuby}
text (/[a-z]+/) /[a-z]+/ *foo*
text foo (/foo|\/|foo/) *bar*
\end{lstRuby}
\end{document}