2012-04-28 2 views
4

Я пытаюсь написать основной режим Emacs для работы с данными биологической последовательности (т. Е. ДНК и пептиды), и я хочу реализовать подсветку синтаксиса, когда разные буквы окрашены по-разному. Поскольку режим должен быть способен различать последовательности ДНК и аминокислотные последовательности и окрасить их по-разному, я помещаю каждую последовательность в файлы в одной строке с односимвольным префиксом (+ или #), который должен указывать, как следующая строка должны быть выделены.Выделение синтаксиса Emacs вложенных регулярных выражений

Так, например, если файл содержит строку с надписью:

+AAGATCCCAGATT 

В s «А» все должны быть в одном цвете, который отличается от остальной части линии.

Я попытался следующие как тест:

(setq dna-keyword 
'(("^\+\\([GCT\-]*\\(A\\)\\)*" (2 font-lock-function-name-face)) 
) 
) 

(define-derived-mode bioseq-mode fundamental-mode 
    (setq font-lock-defaults '(dna-keyword)) 
    (setq mode-name "bioseq mode") 
) 

Но что соответствует только последний А вместо того, чтобы все из них.

Моя первая мысль состояла в том, чтобы попытаться совместить всю строку с одним регулярным выражением, а затем использовать другое регулярное выражение для соответствия только А внутри этой строки, но я понятия не имею, возможно ли это в контексте режима блокировки шрифтов или как это будет сделано. Любые идеи о том, как сделать что-то подобное, или как это сделать по-другому?

ответ

6

Действительно, Emacs обеспечивает только то, что вам нужно для этого, с функцией «привязанного соответствия» режима блокировки шрифтов. Синтаксис немного волосатый, но он позволяет указывать дополнительные «совпадения» (в основном, регулярное выражение, идентификатор подвыражения и имя лица), которое (по умолчанию) будет применяться после позиции, в которой основное «регулярное выражение» «конкатенация» заканчивается Конец строки. Существуют более сложные способы настройки именно того диапазона текста, к которому они применяются, но это общая идея.

Вот простой пример, который также показывает, как вы можете определить свое собственное лицо с целью:

(defface bioseq-mode-a 
    '((((min-colors 8)) :foreground "red")) 
    "Face for As in bioseq-mode") 

(defface bioseq-mode-g 
    '((((min-colors 8)) :foreground "blue")) 
    "Face for Gs in bioseq-mode") 

(setq dna-keyword 
     '(("^\\+" ("A" nil nil (0 'bioseq-mode-a))) 
     ("^\\+" ("G" nil nil (0 'bioseq-mode-g))))) 

Вы также можете указать два или более привязанные matchers для одной главной согласовани (главная согласованью здесь является регулярным выражением "^\\+"). Чтобы выполнить эту работу, каждый привязанный сопрягатель после первого должен явно вернуться к началу строки перед началом поиска; в противном случае он только начнет выделяться после последнего появления предыдущего привязанного сопряжения. Это достигается путем помещения (начало строки) в слот PRE-MATCH-FORM (элемент 2 списка, см. Ниже).

(setq dna-keyword 
     '(("^\\+" 
     ("A" nil nil (0 'bioseq-mode-a)) 
     ("G" (beginning-of-line) nil (0 'bioseq-mode-g))))) 

Я думаю, что это в основном вопрос вкуса, который вы предпочитаете; второй способ может быть немного более четким, если у вас много разных привязанных совпадений для одной строки, но я сомневаюсь, что существует значительная разница в производительности.

Вот соответствующий бит документации для font-lock-defaults:

HIGHLIGHT должны быть либо MATCH-HIGHLIGHT или MATCH-анкер.

[....]

MATCH-Anchored должен иметь вид:

(Сличитель предматчевой-ФОРМА послематчевой-ФОРМА MATCH-HIGHLIGHT ...)

где MATCHER является регулярным выражением для поиска или имени функции для вызова, чтобы сделать поиск, как для MATCH-HIGHLIGHT выше, но за одним исключением; Смотри ниже. PRE-MATCH-FORM и POST-MATCH-FORM оцениваются до первого, а после используется последний экземпляр MATCH-ANCHORED MATCHER. Поэтому они могут быть , используемые для инициализации до и очистки после использования MATCHER. Как правило, PRE-MATCH-FORM используется для перемещения в какое-либо положение относительно оригинала MATCHER, прежде чем начать с MATCH-ANCHORED's MATCHER. POST-MATCH-FORM может использовать для возврата назад, прежде чем возобновить работу с MATCHER родителем MATCH-ANCHORED.

Вышеупомянутое исключение выглядит следующим образом. Предел поиска MATCHER по умолчанию соответствует концу строки после оценки PRE-MATCH-FORM. Однако, если PRE-MATCH-FORM возвращает позицию, превышающую позицию после PRE-MATCH-FORM оценивается, эта позиция используется как предел поиска. Как правило, плохая идея вернуть позицию больше конца строки , т. Е. Вызвать поиск MATCHER по линиям.

Я всегда считаю, что я должен прочитать шрифт блокировки документов примерно в три раза, прежде чем он начинает иметь смысл для меня ;-)

Смежные вопросы