2009-02-19 81 views
0

我试图编写简单的Emacs函数来转换C风格的人和骆驼人的风格(即c_style < - > cStyle)之间的ID。但由于某种原因,Emacs内置的downcase函数会保留完整的单词。 M-x downcase-word工作正常,所以我完全失去了。任何想法都欢迎。为什么Emacs的“downcase”函数会拒绝执行downcaasing?

(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,但是当我试图转换cStylec_Style作为结果,它工作正常。是的,我检查了这是由于downcase行为。

回答

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. 

你传递nilfixedcase的说法,这将导致replace-match时被替换的文字为大写大写更换。而不是通过t,这一点的代码将工作。

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

  1. 所有您使用的progn是不必要的。 save-excursion的主体是隐含的prognletlet*的主体也是如此。

  2. 向前搜索,然后向后搜索,试图找到点下方符号的边界。 Emacs已经有一个thingatpt库来查找点或附近的东西。在你的情况下,你可以打电话(bounds-of-thing-at-point 'symbol),它返回一个cons cell (START . END)给出找到的符号的开始和结束位置。

1

我认为你需要替换匹配的第二个参数,而不是零。