【问题标题】:Toggle case of next letter in elisp在 elisp 中切换下一个字母的大小写
【发布时间】:2014-03-13 22:28:21
【问题描述】:

我希望能够切换点下字母的大小写。为此,我写了这个:

(defun toggle-case-next-letter ()
  "Toggles the case of the next letter, then moves the point forward one character"
  (interactive)
  (let* ((p (point))
        (upcased (upcasep (char-after)))
        (f (if upcased 'downcase-region 'upcase-region)))
    (progn
      (f p (+ 1 p))
      (forward-char))))

但是,当我运行它时(我已将其绑定到 M-#),我得到了 progn: Symbol's function definition is void: f。我认为这意味着f 没有被绑定,但我不确定。

Upcasep 定义为:

(defun upcasep (c) (eq c (upcase c)))

是 let 绑定的问题,还是其他问题? (另外,如果有更好的方法来做到这一点,那也很好)。

请注意,最初我有 (upcased (upcasep (buffer-substring-no-properties p (+ 1 p)))),我已将其更正为 (upcased (upcasep (char-after)),因为使用上面定义的 upcasep 始终是 nil 字符串(所以我不能再次小写)。

【问题讨论】:

    标签: emacs elisp


    【解决方案1】:

    你有一个典型的 lisp-1 / lisp-2 混淆案例。这是一个修复(只是一个funcall):

    (defun toggle-case-next-letter ()
      "Toggles the case of the next letter, then moves the point forward one character"
      (interactive)
      (let* ((p (point))
            (upcased (char-upcasep (buffer-substring-no-properties p (+ 1 p))))
            (f (if upcased 'downcase-region 'upcase-region)))
        (progn
          (funcall f p (+ 1 p))
          (forward-char))))
    

    这就是我所拥有的:

    (global-set-key (kbd "C->") 'upcase-word-toggle)
    (global-set-key (kbd "C-z") 'capitalize-word-toggle)
    
    (defun char-upcasep (letter)
      (eq letter (upcase letter)))
    
    (defun capitalize-word-toggle ()
      (interactive)
      (let ((start (car
                    (save-excursion
                      (backward-word)
                      (bounds-of-thing-at-point 'symbol)))))
        (if start
            (save-excursion
              (goto-char start)
              (funcall
               (if (char-upcasep (char-after))
                   'downcase-region
                 'upcase-region)
               start (1+ start)))
          (capitalize-word -1))))
    
    (defun upcase-word-toggle ()
      (interactive)
      (let ((bounds (bounds-of-thing-at-point 'symbol))
            beg end
            regionp)
        (if (eq this-command last-command)
            (setq regionp (get this-command 'regionp))
          (put this-command 'regionp nil))
        (cond
          ((or (region-active-p) regionp)
           (setq beg (region-beginning)
                 end (region-end))
           (put this-command 'regionp t))
          (bounds
           (setq beg (car bounds)
                 end (cdr bounds)))
          (t
           (setq beg (point)
                 end (1+ beg))))
        (save-excursion
          (goto-char (1- beg))
          (and (re-search-forward "[A-Za-z]" end t)
               (funcall (if (char-upcasep (char-before))
                            'downcase-region
                          'upcase-region)
                        beg end)))))  
    

    【讨论】:

    • 这使得它可以将点下的字母大写,但它不会再次小写它们 - 似乎(upcasep "D")nil,即使(upcasep ?D)t。但是,我们似乎对upcasep 有相同的定义...
    • "D" 是一个字符串。 ?D 是一个字符。字符串与equal 进行比较(昂贵,这就是我不使用它的原因)。字符与eq(便宜)进行比较。
    • 所以比较buffer-substring 使用eq 返回的东西总是为零?
    • 是的,除非两个字符串是同一个对象。许多其他语言具有相同的严格平等和非严格平等的概念。
    • let 下不需要progn
    【解决方案2】:

    我无法让 @abo-abo 的答案为我工作,但使用他的 cmets 我能够更好地用谷歌搜索并在 http://chneukirchen.org/dotfiles/.emacs 找到以下内容

    (defun chris2-toggle-case ()
      (interactive)
      (let ((char (following-char)))
        (if (eq char (upcase char))
            (insert-char (downcase char) 1 t)
          (insert-char (upcase char) 1 t)))
      (delete-char 1 nil)
      (backward-char))
    (global-set-key (kbd "M-#") 'chris2-toggle-case)
    

    如果您删除 (backward-char),这将回答原始问题。

    【讨论】:

      猜你喜欢
      • 2020-07-19
      • 1970-01-01
      • 1970-01-01
      • 2015-04-24
      • 1970-01-01
      • 1970-01-01
      • 2013-02-04
      • 1970-01-01
      • 2017-07-29
      相关资源
      最近更新 更多