Bagaimana cara menambahkan penyorotan sintaksis kompleks dalam mode minor?

10

Saya ingin menyorot kode dengan berbagai wajah dalam mode minor.

Berikut screenshot yang dekat dengan yang saya inginkan:

python-syntax-highlight

Satu hal yang saya hilang adalah memiliki karakter komentar #di font-lock-comment-face. Idenya adalah untuk memiliki komentar yang "milik" garis besar disorot sebagai teks biasa, sehingga lebih mudah dibaca. Sementara memiliki komentar reguler dengan wajah yang biasanya kurang menonjol.

Berikut kode yang saya gunakan:

(setq-local font-lock-defaults
            '(python-font-lock-keywords
              nil nil nil nil
              (font-lock-syntactic-face-function
               . lpy-font-lock-syntactic-face-function)))

(defun lpy-font-lock-syntactic-face-function (state)
  "Return syntactic face given STATE.
Returns 'defalt face for comments that belong to an outline."
  (cond ((nth 3 state)
         (if (python-info-docstring-p state)
             font-lock-doc-face
           font-lock-string-face))
        ((save-excursion
           (while (and (> (point) (point-min))
                       (progn (move-beginning-of-line 0)
                              (eq (char-after) ?\#))))
           (forward-line 1)
           (looking-at "#\\*+ "))
         'default)
        (t
         font-lock-comment-face)))

Masalahnya adalah, saya tidak memiliki petunjuk tentang antarmuka yang font-lock-syntactic-face-functionberoperasi, selain menerima struktur data yang kompleks state, memiliki status titik yang berbeda, dan mengembalikan wajah.

Bisakah seseorang menjelaskan antarmuka ini? Apakah mungkin ada yang lebih baik?

abo-abo
sumber

Jawaban:

6

font-lock-syntactic-face-functionadalah variabel reguler dari Kunci Font, lebih khusus dari fase Kunci Font Sintaksis (penekanan milikku):

Jika variabel ini non-nil, itu harus fungsi untuk menentukan wajah yang akan digunakan untuk elemen sintaksis yang diberikan (string atau komentar). Nilai ini biasanya ditetapkan melalui elemen vars lain di font-lock-defaults.

Fungsi ini disebut dengan satu argumen, keadaan parse pada titik dikembalikan oleh parse-partial-sexp, dan harus mengembalikan wajah . Nilai default mengembalikan font-lock-comment-face untuk komentar dan font-lock-string-face untuk string (lihat Wajah untuk Kunci Font).

parse-partial-sexppada gilirannya mengembalikan daftar yang menggambarkan keadaan sintaksis Emacs saat ini, yang pada dasarnya adalah hasil dari penerapan tabel sintaks ke buffer saat ini. Daftarnya agak rumit, maka saya akan menyimpannya di sini; Anda dapat melihat referensi lengkap di docstring of parse-partial-sexp. Tujuan dari fungsi ini adalah untuk mengubah wajah yang diterapkan pada elemen sintaksis di bawah aturan tertentu. Awal fungsi Anda menunjukkan ini: Jika string saat ini adalah docstring, gunakan wajah yang berbeda untuk itu.

Namun, wajah selalu berlaku untuk seluruh elemen sintaksis, yaitu seluruh string atau komentar. Anda tidak dapat menyorot setiap bagian dengan fungsi ini, dan Anda hanya harus melihat apa yang diberikan stateuntuk tujuan ini — seperti (python-info-docstring-p state)halnya dalam kode Anda. Jangan tidak menggunakan jalur di tempat ini; Saya bahkan tidak yakin apakah nilai pointdidefinisikan dengan benar pada tahap penguncian font ini.


Menyatukan potongan-potongan, Anda menggunakan fungsi yang salah untuk tujuan Anda, itulah sebabnya Anda tidak bisa membuatnya berfungsi.

Saya belum mencoba menerapkan penyorotan yang Anda inginkan, tetapi saya pikir Anda menggali caranya, terlalu dalam untuk tujuan Anda. Jika saya memahami hal-hal dengan benar, Anda hanya ingin menyoroti garis besar dalam komentar.

Jika saya benar, maka Anda hanya perlu font-lock-keywordsdengan cara khusus, yaitu:

(my/find-outline-in-comment-p 0 'outline-face t)

di mana outline-facewajah yang ingin Anda terapkan pada judul, tberarti untuk menimpa penguncian font sebelumnya di tempat ini, dan my/find-outline-in-commentmerupakan fungsi pencocokan (lihat dokumentasi font-lock-defaults) yang mengambil posisi dan mencari garis besar pertama dalam komentar antara (point)dan posisi itu, mengembalikan luasan garis besar untuk disorot dalam data pertandingan.

Untuk menemukan garis besar, Anda akan memindai ke depan untuk komentar (menggunakan font-lock-comment-faceatau keadaan sintaksis) dan kemudian menggunakan looking-atuntuk memeriksa apakah komentar memiliki garis besar.

lunaryorn
sumber
1

Pertimbangkan untuk mendefinisikan font-lock-syntactic-face-functionseperti itu:

(setq font-lock-syntactic-face-function
      (lambda (state)
    (cond ((nth 3 state)
           font-lock-string-face)
          ((and (nth 4 state)(nth 8 state))
            MY-COMMENT-FACE
          (t  font-lock-comment-face))))

Ini diuji dengan python-mode.el, meninggalkan bagian yang dimulai dengan "# *" tanpa wajah komentar:

(setq py--font-lock-syntactic-face-function
      (lambda (state)
    (cond ((nth 3 state)
           font-lock-string-face)
          ((and (nth 4 state)(nth 8 state)
            (progn (save-excursion
                 (goto-char (nth 8 state))
                 (looking-at (concat comment-start (regexp-quote "*"))))))
           nil)
          (t font-lock-comment-face))))

Sementara itu diatur dengan mode:

(font-lock-syntactic-face-function
                    . py--font-lock-syntactic-face-function)

Alih-alih nil, wajah apa pun yang valid harus bekerja.

Andreas Röhler
sumber