如何为第一行出现的关键字设置face?

发布于 2024-11-08 17:06:27 字数 615 浏览 0 评论 0原文

如何为指定关键字设置外观,但仅在第一行设置? 例如,只有这个文件

--- cut here ---
hello world    <-- this "hello" should have face set
hello world    <-- while this "hello" should not
--- cut here ---

第一个hello应该设置脸部

我尝试过这个

(defun first-line-hello(limit)
  (and (save-excursion (beginning-of-line)
                       (bobp))
       (re-search-forward "hello" limit)))

 (font-lock-add-keywords 'emacs-lisp-mode
                         '((first-line-hello . font-lock-warning-face)))

,但似乎由于某种原因(bobp)在字体锁定关键字中使用时总是返回true。我也尝试使用 line-number-at-pos 得到相同的结果。

How do I set face for specified keywords but only ones in first line?
For example having this file

--- cut here ---
hello world    <-- this "hello" should have face set
hello world    <-- while this "hello" should not
--- cut here ---

only first hello should have face set

I tried this

(defun first-line-hello(limit)
  (and (save-excursion (beginning-of-line)
                       (bobp))
       (re-search-forward "hello" limit)))

 (font-lock-add-keywords 'emacs-lisp-mode
                         '((first-line-hello . font-lock-warning-face)))

but it seems that for some reason (bobp) returns always true when used in font-lock-keywords. I also tried using line-number-at-pos with the same result.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

过潦 2024-11-15 17:06:27

你已经很接近了,但还有一些问题。 “限制”可能远远超出第一行的末尾,如果搜索失败,您不需要出现错误,并且无论搜索通过/失败,您都需要移动点。这一切都归结为更改函数中的一行:

(defun first-line-hello(limit)
  (and (save-excursion (beginning-of-line)
                       (bobp))
       (re-search-forward "hello" (min (point-at-eol) limit) 'go)))

You're close, but there are a few problems. 'limit' could be well beyond the end of the first line, you need to not have an error if the search fails, and you need to move point regardless of the search pass/fail. Which all boils down to changing one line in your function:

(defun first-line-hello(limit)
  (and (save-excursion (beginning-of-line)
                       (bobp))
       (re-search-forward "hello" (min (point-at-eol) limit) 'go)))
欲拥i 2024-11-15 17:06:27

Emacs 有一个 正则表达式构造仅与缓冲区开头的空字符串匹配,因此请尝试以下操作:

(font-lock-add-keywords 'emacs-lisp-mode '(("\\`hello" . font-lock-warning-face)))

文档说:

‘\`’
    matches the empty string, but only at the beginning of the buffer or string being matched against. 

Emacs has a regexp construct that matches the empty string only at the beginning of the buffer, so try this:

(font-lock-add-keywords 'emacs-lisp-mode '(("\\`hello" . font-lock-warning-face)))

The docs say:

‘\`’
    matches the empty string, but only at the beginning of the buffer or string being matched against. 
香草可樂 2024-11-15 17:06:27

缓冲区的第一行?段落的第一行?

无论如何,我认为您可以使用自己的次要模式来完成此操作,在该模式中您可以按照自己喜欢的方式扫描缓冲区/区域。在扫描中,您需要从头开始,记下第一次看到每个关键字的位置,突出显示它,然后继续扫描。如果您在扫描过程中看到重复的关键字,请不要突出显示该关键字。

我相信你不能用简单的字体锁定关键字来做到这一点。无论出现在何处,它们始终是关键字。但是您可以使用字体锁定的自定义匹配器来做到这一点。获取有关 font-lock-keywords 的帮助,您将看到:

用户级关键字列表中的每个元素都应采用以下形式之一:

匹配器
...

其中 MATCHER 可以是要搜索的正则表达式,也可以是要搜索的函数名称
调用进行搜索(使用一个参数调用,即搜索的限制;
它应该返回非零,移动点,并适当地设置match-data如果
它成功了;就像re-search-forward 那样)。

这些匹配器函数或正则表达式在缓冲区中的任意位置、看似任意的时间被调用或评估。由于这个原因,使用正则表达式是行不通的,但是使用函数,您可以扫描回缓冲区开头,re-search-forward 查找关键字,并查明它是否是第一个当您看到该关键字时,然后采取适当的操作。您还可以缓存关键字的首次出现位置,然后在更改后挂钩中管理缓存,但这会变得非常复杂。

编辑重读时我发现您已经尝试过后一个想法,但它对您不起作用。奇怪的。

First line of a buffer? First line of a paragraph?

Regardless, I think you could do it with your own minor mode, in which you scan the buffer/region the way you like. In your scan you would need to start from the beginning, note the location of the first time you saw each keyword, highlight it, and continue scanning. if you see a repeated keyword during the scan, then don't highlight that one.

I believe you cannot do it with simple font-lock-keywords. They are always keywords, regardless where they appear. But you could do it with custom matchers for font-lock. Get help on font-lock-keywords and you will see:

Each element in a user-level keywords list should have one of these forms:

MATCHER
...

where MATCHER can be either the regexp to search for, or the function name to
call to make the search (called with one argument, the limit of the search;
it should return non-nil, move point, and set match-data appropriately if
it succeeds; like re-search-forward would).

These matcher functions or regexps get called or evaluated at arbitrary positions in the buffer, at seemingly arbitrary times. Using a regexp wouldn't work for that reason, but using a function, you could scan back to beginning-of-buffer, re-search-forward for the keyword, and find out if it's the first time you've seen the keyword, and then take appropriate action. You could also cache the first-seen location of a keyword, and then manage the cache in a after-change hook, but that's getting pretty complicated.

EDIT on re-reading I see you'ver tried this latter idea and it isn't working for you. strange.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文