为什么Emacs“downcase”函数拒绝做下挫?

时间:2009-02-19 07:52:49

标签: emacs elisp

我正在尝试编写简单的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行为造成的。

2 个答案:

答案 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代替,这段代码将起作用。

我对您的代码有两条一般性评论。

  1. 您对progn的所有使用都是不必要的。 save-excursion的正文是隐式prognletlet*的正文也是如此。

  2. 您向前搜索然后向后搜索以尝试在点下方找到符号的边界。 Emacs已经有一个thingatpt库来查找该点或附近的内容。在您的情况下,您可以调用(bounds-of-thing-at-point 'symbol),它返回一个cons小区(START . END),给出找到的符号的起始位置和结束位置。

答案 1 :(得分:1)

我认为你需要替换匹配的第二个arg为t而不是nil。