我正在尝试编写简单的Emacs函数来转换C风格和camelCase之间的ID(即c_style< - > cStyle)。但由于某些原因,内置downcase
函数的Emacs保留了完整的单词。 M-x downcase-word
工作正常,所以我完全迷失了。欢迎任何想法。
(defun toggle-id-style ()
"Toggle between C-style ids and camel Case ones (i.e. c_style_id -> cStyleId and back)."
(interactive)
(save-excursion
(progn
(re-search-forward "[^A-Za-z0-9_]" nil t)
(let ((end (point))
(case-fold-search nil))
(progn
(re-search-backward "[^A-Za-z0-9_]" nil t)
(let* ((cstyle (if (string-match "_" (buffer-substring-no-properties (point) end)) t nil))
(regexp (if cstyle "_\\(\\w+\\)" "\\([A-Z][a-z0-9]+\\)") )
(func (if cstyle 'capitalize (lambda (s) (concat "_" (downcase s) ) ))))
(progn
(while (re-search-forward regexp end t)
(replace-match (funcall func (match-string 1)) nil nil)))))))))
;;M-x replace-regexp _\(\w+\) -> \,(capitalize \1) ;; c_style -> cStyle
;;M-x replace-regexp \([A-Z][a-z0-9]+\) -> _\,(downcase \1) ;;cStyle -> c_style
如果我转换c_style
,它可以正常工作,但当我尝试转换cStyle
时,我得到了c_Style
。是的,我已经检查过这是由于downcase
行为造成的。
答案 0 :(得分:4)
你的问题是replace-match
的第二个参数。来自文档:
If second arg fixedcase is non-nil, do not alter case of replacement text. Otherwise maybe capitalize the whole text, or maybe just word initials, based on the replaced text. If the replaced text has only capital letters and has at least one multiletter word, convert newtext to all caps. Otherwise if all words are capitalized in the replaced text, capitalize each word in newtext.
您正在为nil
参数传递fixedcase
,这会导致replace-match
在替换的文本大写时将替换值大写。通过t
代替,这段代码将起作用。
我对您的代码有两条一般性评论。
您对progn
的所有使用都是不必要的。 save-excursion
的正文是隐式progn
,let
和let*
的正文也是如此。
您向前搜索然后向后搜索以尝试在点下方找到符号的边界。 Emacs已经有一个thingatpt
库来查找该点或附近的内容。在您的情况下,您可以调用(bounds-of-thing-at-point 'symbol)
,它返回一个cons小区(START . END)
,给出找到的符号的起始位置和结束位置。
答案 1 :(得分:1)
我认为你需要替换匹配的第二个arg为t而不是nil。