让我们看看以下功能。
它的作用并不重要,重要的是它
它使用了两次字符串"(let\\*?[ \t]*"
:
(defun setq-expression-or-sexp ()
"Return the smallest list that contains point.
If inside VARLIST part of `let' form,
return the corresponding `setq' expression."
(interactive)
(ignore-errors
(save-excursion
(up-list)
(let ((sexp (preceding-sexp)))
(backward-list 1)
(cond
((looking-back "(let\\*?[ \t]*")
(cons 'setq
(if (= (length sexp) 1)
(car sexp)
(cl-mapcan
(lambda (x) (unless (listp x) (list x nil)))
sexp))))
((progn
(up-list)
(backward-list 1)
(looking-back "(let\\*?[ \t]*"))
(cons 'setq sexp))
(t
sexp))))))
由于在两个(或更多)位置更新字符串很头疼,
我必须这样defconst
:
(defconst regex-let-form "(let\\*?[ \t]*")
虽然代码变得更易于维护,但它的可读性也降低了,
因为很难一眼看出regex-let-form
究竟是什么:
(defun setq-expression-or-sexp ()
"Return the smallest list that contains point.
If inside VARLIST part of `let' form,
return the corresponding `setq' expression."
(interactive)
(ignore-errors
(save-excursion
(up-list)
(let ((sexp (preceding-sexp)))
(backward-list 1)
(cond
((looking-back regex-let-form)
(cons 'setq
(if (= (length sexp) 1)
(car sexp)
(cl-mapcan
(lambda (x) (unless (listp x) (list x nil)))
sexp))))
((progn
(up-list)
(backward-list 1)
(looking-back regex-let-form))
(cons 'setq sexp))
(t
sexp))))))
因为它是一个常数,为什么不font-lock
它
并使regex-let-form
看起来好像是"(let\\*?[ \t]*"
?
这是一项可行的工作,因为:
可以像这样对字符串进行字体锁定:http://www.emacswiki.org/emacs/PrettyLambda, 甚至是这样的:rainbow-mode。
并且可以使用字体锁定常量。它已经完成了c ++模式, 但据我所知,目前还没有emacs-lisp-mode。
然后它仍然只是连接两者。不幸的是,我不知道
足够的font-lock
内脏来做,但也许其他人呢?
或者已经有一个包这样做?
答案 0 :(得分:1)
从this answer调整代码, 我已经解决了这个问题:
(font-lock-add-keywords
'emacs-lisp-mode
'((fl-string-constant . 'font-lock-constant-face)) 'append)
(defun fl-string-constant (_limit)
(while (not
(ignore-errors
(save-excursion
(skip-chars-forward "'")
(let ((opoint (point))
(obj (read (current-buffer)))
obj-val)
(and (symbolp obj)
(risky-local-variable-p obj)
(special-variable-p obj)
(stringp (setq obj-val (eval obj)))
(progn
(put-text-property
(1- (point)) (point) 'display
(format "%c\"%s\"" (char-before) obj-val))
(set-match-data (list opoint (point)))
t))))))
(if (looking-at "\\(\\sw\\|\\s_\\)")
(forward-sexp 1)
(forward-char 1)))
t)
这将在常量名称后面显示字符串常量的值。 它与精确的字符串常量一起运行得非常好。 速度是一个问题 - 欢迎提出改进建议。
另外,我找不到比risky-local-variable-p
更好的东西来确定
这是一个常数。该文档说defconst
标记变量
特别危险,但没有别的。
答案 1 :(得分:1)
hl-defined.el
(今天更新,2013-10-20)可以突出显示常量Emacs-Lisp符号,即当前值为符号本身的变量。如果您的defconst
已经过评估,那么这将按照您的要求进行。
答案 2 :(得分:0)
这似乎有用(来源:http://www.emacswiki.org/emacs/PrettyLambda):
(font-lock-add-keywords 'emacs-lisp-mode
`(("\\<\\(regex-let-form\\)\\>" (0 (prog1 nil
(compose-region (match-beginning 1)
(match-end 1)
"\"(let\\\\*?[ \\t]*\""))))))
虽然我认为将regex-let-form
添加到现有let
块中将是一个更清晰的解决方案:
(let ((sexp (preceding-sexp))
(regex-let-form "(let\\*?[ \t]*"))
...
答案 3 :(得分:-1)
也许你的例子没有表明真正的问题,你真的想做一些显示替换或字体锁定,如你所说。
但我会回答你的例子以及所提出的问题,关于可维护性与可读性:只需let
- 绑定你的正则表达式。与defconst
不同,绑定将在附近,并且与绑定变量的出现明显相关。
这通常是人们的行为。同样,你可能还有另一个用例 - 我只是对这个问题作出了狭隘的回应。