我可以在“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}

在此輸入影像描述

相關內容