I'm trying to write simple Emacs function to convert ids between C style ones and camelCase ones (i.e. c_style <-> cStyle). But for some reason, Emacs built in downcase function leaves the word intact. M-x downcase-word works fine so I completely lost. Any ideas are welcome.
(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
It works fine if I convert c_style but when I'm trying to convert cStyle I got c_Style as result. Yes, I've checked that this is due to downcase behaviour.
-
I think you need the second arg of replace-match to be t instead of nil.
-
Your problem is the second argument to
replace-match. From the documentation: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.
You're passing
nilfor thefixedcaseargument, which causesreplace-matchto capitalize the replacement when the text being replaced is capitalized. Passtinstead and this bit of the code will work.I have two general comments about your code.
All of your uses of
prognare unnecessary. The body ofsave-excursionis an implicitprognand so are the bodies ofletandlet*.You search forwards and then backwards to try to find the bounds of the symbol underneath point. Emacs already has a
thingatptlibrary to find things at or near the point. In your case you can just call(bounds-of-thing-at-point 'symbol)which returns a cons cell(START . END)giving the start and end positions of the symbol that was found.
0 comments:
Post a Comment