为什么Emacs会这样说;唐卡斯;功能拒绝做下套管?

为什么Emacs会这样说;唐卡斯;功能拒绝做下套管?,emacs,elisp,Emacs,Elisp,我试图编写简单的Emacs函数来转换C风格的ID和camelCase风格的ID(即C_风格的cStyle)。但出于某种原因,Emacs内置的downcase函数保留了单词的完整性M-x简写单词工作正常,所以我完全迷路了。欢迎提出任何意见 (defun toggle-id-style () "Toggle between C-style ids and camel Case ones (i.e. c_style_id -> cStyleId and back)." (interac

我试图编写简单的Emacs函数来转换C风格的ID和camelCase风格的ID(即C_风格的cStyle)。但出于某种原因,Emacs内置的
downcase
函数保留了单词的完整性<代码>M-x简写单词工作正常,所以我完全迷路了。欢迎提出任何意见

(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_样式
,效果很好,但是当我尝试转换
cStyle
时,我得到了
c_样式
。是的,我已经检查过这是由于
downcase
行为造成的。

我想你需要替换匹配的第二个参数是t而不是nil。

我想你需要替换匹配的第二个参数是t而不是nil。

你的问题是
替换匹配的第二个参数。从文件中:

若第二个arg fixedcase为非nil,则不要更改替换文本的大小写。 否则,可能会将整个文本大写,也可能只是单词的首字母, 基于替换的文本。 如果替换的文本只有大写字母 并且至少有一个多字母单词,将newtext转换为所有大写字母。 否则,如果替换文本中的所有单词都大写, 新课文中的每个单词都大写。 您正在为
fixedcase
参数传递
nil
,这会导致
replace match
在被替换文本大写时将替换内容大写。改为传递
t
,这一位代码将起作用

我对您的代码有两个一般性的评论

  • 您对
    progn
    的所有使用都是不必要的。
    保存偏移
    的主体是一个隐式的
    progn
    let
    let*
    的主体也是如此

  • 您可以向前搜索,然后向后搜索,以尝试在点下方找到符号的边界。Emacs已经有了一个
    thingatpt
    库来查找点上或点附近的内容。在您的情况下,您只需调用
    (point'symbol的边界)
    ,它返回一个cons单元格
    (START.END)
    ,给出找到的符号的开始和结束位置


  • 您的问题是
    替换匹配的第二个参数。从文件中:

    若第二个arg fixedcase为非nil,则不要更改替换文本的大小写。 否则,可能会将整个文本大写,也可能只是单词的首字母, 基于替换的文本。 如果替换的文本只有大写字母 并且至少有一个多字母单词,将newtext转换为所有大写字母。 否则,如果替换文本中的所有单词都大写, 新课文中的每个单词都大写。 您正在为
    fixedcase
    参数传递
    nil
    ,这会导致
    replace match
    在被替换文本大写时将替换内容大写。改为传递
    t
    ,这一位代码将起作用

    我对您的代码有两个一般性的评论

  • 您对
    progn
    的所有使用都是不必要的。
    保存偏移
    的主体是一个隐式的
    progn
    let
    let*
    的主体也是如此

  • 您可以向前搜索,然后向后搜索,以尝试在点下方找到符号的边界。Emacs已经有了一个
    thingatpt
    库来查找点上或点附近的内容。在您的情况下,您只需调用
    (point'symbol的边界)
    ,它返回一个cons单元格
    (START.END)
    ,给出找到的符号的开始和结束位置

  • 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.