【问题标题】:Search and replace inside a rectangle in emacs在emacs中的矩形内搜索和替换
【发布时间】:2012-06-23 05:43:12
【问题描述】:

是否可以在 emacs 的矩形区域内执行replace-string 操作?如果有,怎么做?

【问题讨论】:

    标签: search emacs replace


    【解决方案1】:

    在最近的 Emacs(例如 Emacs 25)中,您可以使用 M-% (query-replace) 或 C-M-% (query-replace-regexp) 开箱即用地执行此操作。

    使用M-x rectangle-mark-mode 创建矩形区域。如有必要,使用C-x C-x 将点放在标记之前。然后只需查询替换。

    然而,他们并没有在 Emacs 25 中为 replace-string 进行相同的更改。如果你愿意,你可以这样做,只需添加参数region-noncontiguous-p,就像在query-replace 中一样。代码很简单:

    (defun replace-string (from-string to-string &optional delimited start end backward
                           region-noncontiguous-p)
      "..."
      (declare (interactive-only
                "use `search-forward' and `replace-match' instead."))
      (interactive
       (let ((common
              (query-replace-read-args
               (concat "Replace"
                       (if current-prefix-arg
                           (if (eq current-prefix-arg '-) " backward" " word")
                         "")
                       " string"
                       (if (use-region-p) " in region" ""))
               nil)))
         (list (nth 0 common) (nth 1 common) (nth 2 common)
               (if (use-region-p) (region-beginning))
               (if (use-region-p) (region-end))
               (nth 3 common)
               (if (use-region-p) (region-noncontiguous-p)))))
      (perform-replace
        from-string to-string nil nil delimited nil nil start end backward region-noncontiguous-p))
    

    或者,您可以只下载库replace+.el 并从那里使用replace-string 的版本。它做你想做的事。

    FWIW,我刚刚提交了 Emacs bug#27897 以将此功能添加到 replace-string 和同一库中的其他几个命令 replace.el。

    【讨论】:

    【解决方案2】:

    对于邪恶的用户,您可以使用我的包evil-visual-replace 来获取邪恶视觉块内的query-replace 和replace-regexp。

    【讨论】:

      【解决方案3】:

      如果您处于 CUA 模式,您可以使用绑定到 'M-r' 的 cua-replace-in-rectangle。

      【讨论】:

      • 但这只会替换事物的第一次出现(默认 vim 替换正则表达式行为)。
      【解决方案4】:

      如果启用 CUA 选择模式:

      M-x cua-selection-mode RET

      或永久保存在您的初始化文件中:

      (cua-selection-mode 1)
      

      然后您可以使用它的高级矩形编辑工具。

      (或者如果您是cua-mode 用户,则不需要这样做。)

      • C-RET 标记角。
      • 将点移动到对角。
      • M-r 在标记的矩形内进行 regexp 替换。
      • C-RET 取消标记/退出矩形编辑。

      有关文档,请在 Mx find-library RET cua-base RET

      如果您出于某种原因不想使用 cua 矩形功能(也许如果您真的特别需要 replace-string),那么使用 apply-on-rectangle 的自定义函数将非常简单。

      编辑:实际上,比我预期的要复杂一些,但大部分代码是交互式规范和对“分隔”前缀参数行为的支持(均基于replace-string) .

      编辑 2:我认为这值得以更全面的方式进行:

      以下提供CxrM-%和CxrCM-%,它(希望)按照你的预期行事。

      (require 'rect)
      
      (defun my-search-replace-in-rectangle
        (start end search-pattern replacement search-function literal)
        "Replace all instances of SEARCH-PATTERN (as found by SEARCH-FUNCTION)
      with REPLACEMENT, in each line of the rectangle established by the START
      and END buffer positions.
      
      SEARCH-FUNCTION should take the same BOUND and NOERROR arguments as
      `search-forward' and `re-search-forward'.
      
      The LITERAL argument is passed to `replace-match' during replacement.
      
      If `case-replace' is nil, do not alter case of replacement text."
        (apply-on-rectangle
         (lambda (start-col end-col search-function search-pattern replacement)
           (move-to-column start-col)
           (let ((bound (min (+ (point) (- end-col start-col))
                             (line-end-position)))
                 (fixedcase (not case-replace)))
             (while (funcall search-function search-pattern bound t)
               (replace-match replacement fixedcase literal))))
         start end search-function search-pattern replacement))
      
      (defun my-replace-regexp-rectangle-read-args (regexp-flag)
        "Interactively read arguments for `my-replace-regexp-rectangle'
      or `my-replace-string-rectangle' (depending upon REGEXP-FLAG)."
        (let ((args (query-replace-read-args
                     (concat "Replace"
                             (if current-prefix-arg " word" "")
                             (if regexp-flag " regexp" " string"))
                     regexp-flag)))
          (list (region-beginning) (region-end)
                (nth 0 args) (nth 1 args) (nth 2 args))))
      
      (defun my-replace-regexp-rectangle
        (start end regexp to-string &optional delimited)
        "Perform a regexp search and replace on each line of a rectangle
      established by START and END (interactively, the marked region),
      similar to `replace-regexp'.
      
      Optional arg DELIMITED (prefix arg if interactive), if non-nil, means
      replace only matches surrounded by word boundaries.
      
      If `case-replace' is nil, do not alter case of replacement text."
        (interactive (my-replace-regexp-rectangle-read-args t))
        (when delimited
          (setq regexp (concat "\\b" regexp "\\b")))
        (my-search-replace-in-rectangle
         start end regexp to-string 're-search-forward nil))
      
      (defun my-replace-string-rectangle
        (start end from-string to-string &optional delimited)
        "Perform a string search and replace on each line of a rectangle
      established by START and END (interactively, the marked region),
      similar to `replace-string'.
      
      Optional arg DELIMITED (prefix arg if interactive), if non-nil, means
      replace only matches surrounded by word boundaries.
      
      If `case-replace' is nil, do not alter case of replacement text."
        (interactive (my-replace-regexp-rectangle-read-args nil))
        (let ((search-function 'search-forward))
          (when delimited
            (setq search-function 're-search-forward
                  from-string (concat "\\b" (regexp-quote from-string) "\\b")))
          (my-search-replace-in-rectangle
           start end from-string to-string search-function t)))
      
      (global-set-key (kbd "C-x r M-%") 'my-replace-string-rectangle)
      (global-set-key (kbd "C-x r C-M-%") 'my-replace-regexp-rectangle)
      

      【讨论】:

      • 谢谢!不幸的是,我似乎只能在 emacs GUI 中用C-RET 标记一个角落,而不是在终端模式下。
      • 那是因为您的终端没有发送该序列。您可能会发现 xterm 更成功(另请参阅 stackoverflow.com/questions/4337837/…)。我还用非 CUA 方法的功能更全面的代码更新了我的答案。
      • 功能请求:搜索矩形。我有一个巨大的专栏,我需要检查它除了DPP 之外是否还有其他内容。我使用了一些复杂的正则表达式——如果列真的很大——我得到正则表达式堆栈溢出。
      • 仅为可能像ME混淆的其他人的备注 - M-R才会在选定的矩形处于活动状态时绑定到CUA替换。 span>
      • 感谢您的 lisp,它开箱即用!
      猜你喜欢
      • 1970-01-01
      • 2011-10-16
      • 1970-01-01
      • 2015-11-23
      • 1970-01-01
      • 1970-01-01
      • 2010-10-30
      • 1970-01-01
      • 2010-12-13
      相关资源
      最近更新 更多