Verwenden Sie den Schriftsperrmodus nur für einen Teil des Puffers


7

Ich versuche, der Pod-Dokumentation für Perl-Skripte eine Kommentarfunktion hinzuzufügen, und ich möchte Pod-Kommentare mit einem besonderen Gesicht hervorheben. Ein einfacher Prototyp eines Perl-Skripts könnte sein:

#! /usr/bin/env perl

use strict;
use warnings;

print "Hello\n"; # a Perl comment /* hello */

__END__

=head1 SYNOPSIS

my_program <arg1> [OPTIONS]

/* this is a Pod comment */

Wie wir sehen, wird ein Pod-Kommentar /* */wie in der Programmiersprache C angezeigt . Nur der Teil unter der Zeile __END__ist jedoch die Pod-Dokumentation. Der Teil über dieser Zeile ist regulärer Perl-Code. Wenn ich nun versuche, dem Pod-Kommentar eine Syntaxhervorhebung hinzuzufügen, indem ich zum Beispiel (aufgerufen von cperl-mode-hook):

(font-lock-add-keywords nil '(("\\(/\\*.*?\\*/\\)" 1 'font-lock-warning-face t)))

Ich erhalte Folgendes cperl-modeals Hauptmodus:

Geben Sie hier die Bildbeschreibung ein

Pod-Kommentare werden daher auch in einem regulären Perl-Kommentar hervorgehoben (ein Perl-Kommentar beginnt mit einem #Zeichen), was nicht erwünscht ist (Pod-Kommentare sollten nur in Pod-Abschnitten hervorgehoben werden, nicht im regulären Perl-Code).

Der Einfachheit halber können wir für diese Frage davon ausgehen, dass die Pod-Dokumentation auf das Ende des Dokuments beschränkt ist, beginnend mit den Zeilen nach dem __END__Tag. Ist es möglich, die Position des aktuellen Kommentars zu überprüfen und diese mit der Position der __END__Zeile in Beziehung zu setzen und anhand dieser Informationen zu bestimmen, ob wir uns in einem Pod-Block befinden oder nicht (und dann nur dann eine Syntaxhervorhebung hinzuzufügen, wenn wir uns in einem Pod-Block befinden)? beim Ausführen des Schriftsperrcodes?


Ich habe nicht verwendet, mmm-modeaber ich denke, dies könnte die Lösung für Sie sein.
Kaushal Modi

Wenn es einen pod-modeHauptmodus gibt, der für die Pod-Kommentarbereiche geeignet wäre, ist er mmm-modemöglicherweise anwendbar. Ich bin mir nicht sicher, ob das der Fall ist. Wahrscheinlich benötigen Sie hier nur eine zusätzliche Font-Lock-Konfiguration.
Sanityinc

Antworten:


8

Aktualisierte Lösung

Es gibt eine eingebaute Möglichkeit, dies mit der Schriftsperre zu tun (danke sanityinc).

Diese Antwort enthält alle Details zur Funktionsweise dieser Art von Font-Lock-Schlüsselwörtern: https://stackoverflow.com/a/14675550

(defun pod-comment-highlighter (limit)
  "If looking after __END__ or __END__ is before LIMIT, set match-data to a the location of the pod comment."
  (when (or (save-excursion (search-backward "__END__" (point-min) t 1))
            (search-forward "__END__" limit t 1))
    (re-search-forward "\\(/\\*.*?\\*/\\)" limit t 1)))

(font-lock-add-keywords
 'perl-mode
 '((pod-comment-highlighter 0 font-lock-warning-face t)))

Das Ergebnis ist das gleiche wie bei der ursprünglichen Lösung.

Hier ist es in Aktion:

Geben Sie hier die Bildbeschreibung ein

Originelle Lösung mit Jit-Lock-Funktionen (nicht ideal)

Ich glaube, Sie müssen die Schriftart manuell in einer Funktion ausführen, die dem hinzugefügt wurde jit-lock-functions.

jit-lock-functions sind die Funktionen, die tatsächlich die Schriftart und den Bereich ausführen, die mit den Parametern BEG und END aufgerufen werden, um den Bereich zu kennzeichnen, auf den die Texteigenschaften angewendet werden sollen.

In diesem Szenario erkennt Ihre Funktion zunächst, ob sich der zu färbende Bereich nach dem __END__in Ihrem Puffer befindet, und suchen Sie in diesem Fall manuell nach / * Kommentaren * / und wenden Sie Texteigenschaften auf diese an.

Hier ist eine Implementierung:

(defun pod-comment-highlighter (beg end)
  "Highlight /* this style */ of comments but only if they appear after __END__ in the buffer."
  (save-excursion
    (save-match-data
      (goto-char beg)
      ;; only fontify if __END__ appears before the given region, or, if
      ;; __END__ is inside the region, then start fontifiying after __END__
      (when (or (save-excursion (search-backward "__END__" (point-min) t 1))
                (search-forward "__END__" end t 1))
        (while (re-search-forward "\\(/\\*.*?\\*/\\)" end t 1)
          (add-text-properties (match-beginning 0) (match-end 0) '(face font-lock-warning-face)))))))


;; `jit-lock-register' is normally used to add a jit-lock-function, 
;; but I want to make sure this function is the last function to run and
;; color the buffer so font-lock doesn't undo my applied properties.
;; So add-hook works nicely by passing t in the APPEND parameter
(add-hook 'jit-lock-functions 'pod-comment-highlighter t)

Für Ihr Szenario möchten Sie möglicherweise die Jit-Lock-Funktion in einem Perl-Mode-Hook hinzufügen

Beachten Sie auch, dass diese Funktion nicht "intelligent" ist, sondern nur irgendwo im Puffer nach END sucht. Wenn sie also in einer Zeichenfolge oder einem Perl-Kommentar vorkommt, wo sie keine Wirkung haben sollte, wird dies tatsächlich der Fall sein. Sie können die Funktion erweitern, um bei Bedarf den Kontext zu untersuchen, in dem END auftritt.


1
Normalerweise wäre es nicht gut, Änderungen vorzunehmen jit-lock-function. Das ist ein internes Implementierungsdetail von font-lock. Es sollte einen einfachen font-lockWeg geben, dies zu erreichen.
Sanityinc

1
Sie haben Recht @sanityinc, ich habe den standardisierteren Weg gefunden, dies in der Schriftsperre zu tun, danke. Ich habe in der Vergangenheit Jit-Lock-Funktionen verwendet, das ist also sehr schön zu wissen!
Jordon Biondo

Ach ja, das sieht besser aus!
Sanityinc

Danke @JordonBiondo! Dies war eine sehr lehrreiche Antwort. Es funktioniert perfekt!
Håkon Hægland
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.