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
nil
for thefixedcase
argument, which causesreplace-match
to capitalize the replacement when the text being replaced is capitalized. Passt
instead and this bit of the code will work.I have two general comments about your code.
All of your uses of
progn
are unnecessary. The body ofsave-excursion
is an implicitprogn
and so are the bodies oflet
andlet*
.You search forwards and then backwards to try to find the bounds of the symbol underneath point. Emacs already has a
thingatpt
library 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