정규식을 가져오기 위해 패키지 "listings"에서 "moredelim"을 사용할 수 있습니까?

정규식을 가져오기 위해 패키지 "listings"에서 "moredelim"을 사용할 수 있습니까?

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}

여기에 이미지 설명을 입력하세요

관련 정보