Frage

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.

War es hilfreich?

Lösung

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

Andere Tipps

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. 

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top