2009-02-19 115 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

我認爲你需要替換匹配的第二個參數,而不是零。

相關問題