0

C スタイルのものとキャメルケースのもの (つまり、c_style <-> cStyle) の間で ID を変換する単純な Emacs 関数を作成しようとしています。しかし、何らかの理由で、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

あなたの問題は の 2 番目の引数replace-matchです。ドキュメントから:

2 番目の引数 fixedcase が非 nil の場合、置換テキストの大文字と小文字を変更しません。
それ以外の場合は、テキスト全体を大文字にするか、単語のイニシャルだけを大文字にするか、
置き換えられたテキストに基づいています。
置き換えられたテキストが大文字のみの場合
少なくとも 1 つの複数文字の単語がある場合、newtext をすべて大文字に変換します。
それ以外の場合、置換されたテキストですべての単語が大文字になっている場合、
newtext の各単語を大文字にします。

引数を渡しnilています。これにより、置換されるテキストが大文字になっているときに置換が大文字になります。代わりに渡すと、コードのこのビットが機能します。fixedcasereplace-matcht

あなたのコードについて 2 つの一般的なコメントがあります。

  1. の使用はすべてprogn不要です。の本体save-excursionは暗黙的prognであり、 および の本体も同様letですlet*

  2. ポイントの下にあるシンボルの境界を見つけるために、順方向に検索してから逆方向に検索します。Emacsにはthingatpt、ポイントまたはその近くのものを見つけるためのライブラリが既にあります。あなたの場合、見つかったシンボルの開始位置と終了位置を与える(bounds-of-thing-at-point 'symbol)コンスセルを返すだけを呼び出すことができます。(START . END)

于 2009-02-19T12:41:06.410 に答える