问题
Following code will visually replace "hello world" with "HW" by passing a progn form to font lock keywords.
(font-lock-add-keywords
nil '(("\\(hello world\\)"
(0 (progn (put-text-property (match-beginning 1) (match-end 1)
'display "HW")
nil)))))
I've look into C-h v font-lock-keywords
to see if this is a documented feature of font lock. The hello world element seemed to be of this form:
(MATCHER HIGHLIGHT ...)
which would mean that (0 ...)
is HIGHLIGHT and the doc says
HIGHLIGHT should be either MATCH-HIGHLIGHT or MATCH-ANCHORED.
and
MATCH-HIGHLIGHT should be of the form:
(SUBEXP FACENAME [OVERRIDE [LAXMATCH]])
So I guessed 0 was SUBEXP and (progn ...)
was FACENAME. But if (progn ..)
were a valid FACENAME, the following code would work but it doesn't work.
;; (MATCHER . FACENAME)
(font-lock-add-keywords
nil '(("goodbye lenin"
. (progn (put-text-property (match-beginning 1) (match-end 1)
'display "GL")
nil))))
That brings me to the question of how the first code works and whether it is relying on an undocumented feature.
Update:
Side note: simpler way of visual replacement without font lock errors
(font-lock-add-keywords
nil '(("my llama"
(0 (progn (put-text-property (match-beginning 0) (match-end 0)
'display "ML")
nil)))))
回答1:
It does work - but your MATCHER
is not correct - the result of the match is not stored. This, for example does not work:
(font-lock-add-keywords
nil '(("goodbye lenin"
(0 (progn (put-text-property (match-beginning 1) (match-end 1)
'display "GL")
nil)))))
while this does:
(font-lock-add-keywords
nil '(("\\(goodbye lenin\\)"
. (progn (put-text-property (match-beginning 1) (match-end 1)
'display "GL")
nil))))
The documentation says: "FACENAME
is an expression whose value is the face name to use.
Instead of a face, FACENAME
can evaluate to a property list
of the form (face FACE PROP1 VAL1 PROP2 VAL2 ...)
in which case all the listed text-properties will be set rather than
just FACE
."
Here, the FACENAME
expression (progn
) evaluates to nil
, so no properties or faces are being set - the only effect that caused by put-text-property
.
回答2:
One
problem with ("goodbye lenin" . (progn (put-text-property
(match-beginning 1) (match-end 1) 'display "GL") nil))
is that it is
just another way to write: ("goodbye lenin" progn (put-text-property
(match-beginning 1) (match-end 1) 'display "GL") nil)
, and these
equivalences can lead to ambiguities, which is why in this case you get
errors.
So the form (MATCHER . HIGHLIGHT)
, (match . FACENAME)
and such
should only be used when HIGHLIGHT
and FACENAME
are not themselves
lists.
来源:https://stackoverflow.com/questions/18570224/how-does-a-progn-form-in-font-lock-keywords-work