如果第一行和最后一行不够长,如何在 Emacs 中删除一个矩形文本?

Posted

技术标签:

【中文标题】如果第一行和最后一行不够长,如何在 Emacs 中删除一个矩形文本?【英文标题】:How can I kill a rectangle of text in Emacs if the first and last lines are not long enough? 【发布时间】:2011-12-07 04:31:11 【问题描述】:

在 Emacs 中,我有时想删除或复制一个矩形文本,例如:

XX first line
XX second line is longer
XX 3rd line short

我想复制三行,每行都没有前导“XX”。但是,不可能标记所需矩形的两个角,因为第一行和第三行没有到达我所追求的矩形的右边缘。那么如何在emacs中复制上面没有前导“XX”的三行呢?

【问题讨论】:

【参考方案1】:

从第一行开始标记矩形,当您位于 3d 行的末尾时,只需键入空格,直到行足够长。这是我通常做的。

复制后可以输入M-\ (delete-horizontal-space) 删除添加的空格。

【讨论】:

如果删除选择模式打开,则在标记矩形开始后按 C-g。这会取消突出显示,但标记仍处于活动状态,因此进一步的步骤将按照说明进行。 是的,你是对的,标记将保持活动状态,因此取消选择仍然有效 您不能总是这样做(例如,当缓冲区为只读时)。不过,看起来rectangle-mark-mode 将是fixed in Emacs 25。【参考方案2】:

我看到两个选项跳出来。

首先是使用M-x Artist-mode, 这将让您移动到您想要的第一行/最后一行的位置。 此时你剪切矩形C-x r k,然后粘贴 随心所欲。不要忘记输入 C-c C-c 退出artist mode。

第二个是使用常规 C-w 将所有三行剪切掉 然后在粘贴时,删除行首XXs 的矩形。

【讨论】:

您无需输入artist-mode 即可使用C-x r k。只需标记所需矩形的左上角和右下角即可。至于展开到第三行,按空格键。 @jeremiahd - 使用artist-mode 可以替代按空格键,您只需使用移动绑定即可。 是的,我知道。我只是指出问题中要求的行为没有必要。 @jeremiahd 是的,也不需要按空格(您的答案),这就是我们有两个不同答案的原因。您会注意到我的回答不需要用户删除水平空格。 对,这就是我发表评论而不是答案的原因;这是一个旁白,而不是更正【参考方案3】:

你可以看看cua-selection-mode(M-x cua-selection-mode)。

它允许你做你想做的事,但只能在图形化的 emacs 中(而不是在终端中)。键绑定有点不同:您使用 C-RET(而不是 C-SPC)开始区域,然后使用 C-w/C-y(不使用矩形命令)简单地剪切/拉出矩形。

你可以在this blog找到一个例子。

要永久启用该模式,只需添加

(cua-selection-mode t)

到您的 .emacs。

附:完整的 cua 模式还将更改进一步的键绑定。没有必要使用它。

【讨论】:

这种情况下矩形选择有点尴尬,但是如果你从左上角开始,移动到最长行的末尾,然后向下移动到最后一行,就可以了。跨度> 【参考方案4】:

对 inbulit defuns 的简单修改。 kill-right-rectangle 函数做你想做的事。 我相信会有更好的方法来做到这一点。尽管如此,它仍然有效。

关于以下代码的两点。 - 由于这个想法是让文本到达行尾,因此您甚至不需要指定最后一列。只需在第一行标记(在您的示例中指向“f”)并向下到第三行以“3”调用该函数。 (我们只需要一列,所以不需要向右移动光标) - 如果缓冲区是只读的,这将不起作用。它只是没有实现。

(defun end-column (POINT)
  "returns end column"
  (save-excursion
    (goto-char POINT)
    (move-end-of-line 1)
    (current-column)))

(defun apply-on-right-rectangle (function start end &rest args)
  (let (startcol startpt endcol endpt final-point)
    (save-excursion
      (goto-char start)
      (setq startcol (current-column))
      (beginning-of-line)
      (setq startpt (point))
      (goto-char end)
      (setq endcol (current-column))
      (forward-line 1)
      (setq endpt (point-marker))
      ;; ensure the start column is the left one.
      (if (< endcol startcol)
          (let ((col startcol))
            (setq startcol endcol endcol col)))
      ;; start looping over lines
      (goto-char startpt)
      (while (< (point) endpt)
        (setq endcol (end-column (point)))
        (apply function startcol endcol args)
        (setq final-point (point))
        (forward-line 1)))
    final-point))

(defun delete-extract-right-rectangle (start end &optional fill)
  (let ((lines (list nil)))
    (apply-on-right-rectangle 'delete-extract-rectangle-line start end lines fill)
    (nreverse (cdr lines))))

(defun kill-right-rectangle (start end &optional fill)
  (interactive "r\nP")
  (condition-case nil
      (setq killed-rectangle (delete-extract-right-rectangle start end fill))
    ((buffer-read-only text-read-only)
     (setq killed-rectangle (extract-rectangle start end))
     (if kill-read-only-ok
         (progn (message "Read only text copied to kill ring") nil)
       (barf-if-buffer-read-only)
       (signal 'text-read-only (list (current-buffer)))))))

【讨论】:

以上是关于如果第一行和最后一行不够长,如何在 Emacs 中删除一个矩形文本?的主要内容,如果未能解决你的问题,请参考以下文章

将 hl-line 最后放在 Emacs 背景堆栈中

在弹性行中使用`nowrap`时,请避免将最后一个元素推离屏幕

在 UILabel 中格式化多行文本?

使用vi打开文件如何跳到某一行,第一行或者最后一行呢

Excel如何选中第一行到最后一行?

不要在特定位置使用长按手势移动表格视图单元格