マイナーモードで複雑な構文の強調表示を追加する方法


10

マイナーモードでさまざまな面を持つコードを強調表示したいと思います。

ここに私が欲しいものに近いスクリーンショットがあります:

python-syntax-highlight

私が見逃していることの1つは、にコメント文字#があること font-lock-comment-faceです。考えは、アウトラインに「属している」コメントをプレーンテキストとして強調表示することで、読みやすくなります。いつもの目立たない顔で定期的なコメントをしている間。

これが私が使ったコードです:

(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)))

実は、私がfont-lock-syntactic-face-function操作するインターフェースについては、複雑なデータ構造を受け取り、state異なる点の状態を持ち、顔を返すこと以外は何の手掛かりもありません 。

誰かがこのインターフェースを説明できますか?おそらくもっと良いものはありますか?

回答:


6

font-lock-syntactic-face-functionフォントロックからの通常の変数です。具体的には、構文フォントロックフェーズからのものです(強調は私のものです)。

この変数が非nilの場合、指定された構文要素(文字列またはコメント)に使用する面を決定する関数でなければなりません。通常、値はfont-lock-defaultsのother-vars要素を介して設定されます。

関数は1つの引数、によって返されたポイントの解析状態で呼び出されparse-partial-sexp、faceを返す必要があります。デフォルト値は、コメントの場合はfont-lock-comment-faceを、文字列の場合はfont-lock-string-faceを返します(フォントロックのFacesを参照)。

parse-partial-sexp次に、Emacsの現在の構文状態を説明するリストを返します。これは、本質的には、構文テーブルを現在のバッファーに適用した結果です。リストはかなり複雑なので、ここでは割愛します。のドキュメント文字列で完全なリファレンスを確認できますparse-partial-sexp。この関数の目的は、特定のルールの下で構文要素に適用される面を変更することです。関数の最初の部分はこれを示しています。現在の文字列がdocstringの場合は、別の面を使用してください。

ただし、顔は常に構文要素全体、つまり文字列またはコメント全体に適用されます。この関数を使用して個々の部分を強調表示することはできません。コードのstateように、この目的のために指定された部分だけを見る必要(python-info-docstring-p state)があります。この場所ではポイントを使用しないでください。pointフォントロックのこの段階での値が適切に定義されているかどうかさえわかりません。


断片をまとめると、目的に合った関数が使用されていないため、機能させることができません。

私はあなたが望むハイライトを実装しようとはしていませんが、あなたの目的には深すぎると思います。私が正しく理解していれば、コメントでアウトラインを強調表示したいだけです。

私が正しい場合font-lock-keywordsは、特別な方法で次のことが必要です:

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

ここでoutline-face、見出しに適用する顔は、tこの場所での以前のフォントロックを上書きすることを意味し、位置をmy/find-outline-in-comment取得font-lock-defaultsしてコメントの最初のアウトラインを検索するマッチャー関数(のdocstringを参照)です(point)とその位置の間で、一致データで強調表示されるアウトラインの範囲を返します。

アウトラインを見つけるには、前方にスキャンしてコメントを(使用font-lock-comment-faceまたは構文状態を)探し、次にを使用looking-atしてコメントにアウトラインがあるかどうかを確認します。


1

font-lock-syntactic-face-functionそのように定義することを検討してください:

(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))))

これはpython-mode.elでテストされ、コメントフェースなしで「#*」で始まるセクションが残っています。

(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))))

モードで管理されている間:

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

の代わりにnil、有効な顔であれば機能します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.