You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Emacs Lisp编写函数实现Haskell语法高亮?

Got it, let's get your Haskell function definition highlighting working in Emacs. The function-based approach is the right call here since Elisp regex doesn't support lookarounds, but there are a few issues in your code that are keeping it from working properly.

First, let's go over the main problems:

  • Invalid newline character syntax: In find-equal-character, you wrote ? which is not valid Elisp—newlines need to be written as ?\n. That's probably causing errors right off the bat.
  • Inefficient character lookup: Your get-cur-character uses buffer-substring which creates unnecessary strings; we can use char-after directly for better performance and cleaner code.
  • Match data preservation: While your logic checks for the equals sign, we need to make sure the match data from the initial regex search stays intact so font-lock knows exactly what text to highlight.

Here's the fixed and improved version of your code:

(defun get-cur-character (pos)
  ;; Grab the character at the given position using char-after (more efficient)
  (char-after (1- pos)))

(defun find-equal-character (pos)
  (let ((curchar nil)
        (result nil)
        (max-pos (point-max)))
    (while (and (not (equal curchar ?\n)) (< pos max-pos))
      (setq curchar (get-cur-character pos))
      (setq pos (1+ pos))
      (when (equal curchar ?=)
        (setq result t)
        (setq curchar ?\n))) ; Exit loop as soon as we find =
    result))

(defun highlight-haskell-function (limit)
  (save-excursion
    (when (re-search-forward "^\\([a-z]+\\w*\\)" limit t)
      ;; Only return true if we found an equals sign after the match
      (when (find-equal-character (match-end 0))
        t)))) ; Match data from re-search-forward is still valid here

;; Make sure we add the keywords after haskell-mode is loaded
(eval-after-load 'haskell-mode
  '(font-lock-add-keywords 'haskell-mode
                            '((highlight-haskell-function . 'font-lock-keyword-face))))

(provide 'haskell-mode)

Let's walk through the changes:

  • Fixed newline syntax: Replaced the broken ? with ?\n so Elisp recognizes the newline character correctly.
  • Optimized character fetching: get-cur-character now uses char-after, which is faster and avoids creating unnecessary substrings.
  • Early loop exit: Once we find the = sign, we set curchar to ?\n to break out of the loop immediately instead of scanning the rest of the line.
  • Safe loading: Used eval-after-load to ensure we don't try to modify haskell-mode before it's been loaded into Emacs—this prevents errors on startup.
  • Preserved match data: By returning t only when both the regex match and equals sign check pass, we keep the match data from the initial re-search-forward intact. Font-lock uses this match data to know which part of the buffer to apply the face to.

To use this:

  1. Save this code in a file (e.g., haskell-function-highlight.el)
  2. Add (require 'haskell-function-highlight) to your Emacs config file (init.el or .emacs)
  3. Open a Haskell file—any function starting with a lowercase letter (followed by letters, digits, or underscores) with an = on the same line should now be highlighted with the keyword face.

If you want to use a different face (like the standard function name face), just change font-lock-keyword-face to font-lock-function-name-face in the font-lock-add-keywords line.

One quick note: Your current regex ^\\([a-z]+\\w*\\) doesn't match function names with hyphens (like my-cool-function), which are common in Haskell. If you want to support those, adjust the regex to ^\\([a-z][\\w-]*\\)—this allows hyphens in the function name.

内容的提问来源于stack exchange,提问作者user9775773

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:23:20