0

我正在尝试编写简单的 Emacs 函数来在 C 样式和 camelCase 之间转换 id(即 c_style <-> cStyle)。但是出于某种原因,Emacs 内置downcase函数使这个词保持原样。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行为造成的。

4

2 回答 2

4

您的问题是replace-match. 从文档中:

如果第二个 arg 固定大小写不为零,则不要更改替换文本的大小写。
否则可能将整个文本大写,或者只是单词首字母,
基于替换的文本。
如果被替换的文本只有大写字母
并且至少有一个多字母单词,将 newtext 转换为全部大写。
否则,如果替换文本中的所有单词都大写,
将 newtext 中的每个单词大写。

您正在传递参数,当被替换的文本大写时,这会导致nil替换大写。而是通过,这部分代码将起作用。fixedcasereplace-matcht

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

  1. 你所有的使用progn都是不必要的。的主体save-excursion是隐含的,和的主体也是progn如此。letlet*

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

于 2009-02-19T12:41:06.410 回答
1

我认为您需要替换匹配的第二个参数为 t 而不是 nil。

于 2009-02-19T12:33:35.990 回答