Emacs 记住文本选择

Posted

技术标签:

【中文标题】Emacs 记住文本选择【英文标题】:Emacs remember text selection 【发布时间】:2011-03-17 17:19:00 【问题描述】:

在使用 gEdit 满足我的大部分编码需求几年后,我决定尝试新的东西,并尝试学习使用 Emacs。我知道这会很困难,因为我听说 Emacs 有多么复杂,但我被它的强大所吸引。最难的事情是习惯于在 .emacs 文件中编写 ELisp 来更改有关编辑器的内容。我目前不能自己做,但我在这里和那里找到了一些有用的 sn-ps 来更改一些选项。

我遇到很多问题的一件事是让 Emacs 记住我在命令之后选择的文本。例如,我通常会突出显示一段代码以大量缩进它。但是,如果我在 Emacs 中执行此操作,它只会在取消选择所有文本之前移动选定的文本一次。有谁知道解决这个问题的方法吗?

无论如何,对于我认为是一个简单的问题,我深表歉意,但经过一个小时的谷歌搜索和在 SO 上四处寻找之后,我认为值得一问。我还有一些关于 Emacs 的问题,但我会保存它们并在我解决这些问题后单独提问。谢谢!

更新

有些人询问我使用的是什么模组以及我输入的是什么类型的文本。虽然我对 Emacs 模式了解不多,但我目前正在编辑一个纯文本文件。像这样的:

Hello, I am a simple text file
that is made up of three separate 
lines.

如果我突出显示所有三行并点击 TAB,我会得到:

    Hello, I am a simple text file
    that is made up of three separate 
    lines.

这很好,但是,如果我像下面的一些建议那样使用 C-x C-x 来重新选择文本并再次点击 TAB,我会得到:

        Hello, I am a simple text file
            that is made up of three separate 
                lines.

我希望这会有所帮助!

【问题讨论】:

见***.com/questions/815540/… 【参考方案1】:

FWIW,这是您新添加示例行为的原因。 (我不是在这里“解决”问题,但我发布它是为了揭开你所看到的神秘面纱。)

这是由 emacs -q 确定的,它禁用了我的自定义,因此以下是 emacs 23.2 的默认行为。

    您处于文本模式。您应该在屏幕底部的模式行中看到(Text) 或类似内容,C-h m 会告诉您(在次要模式列表下)“文本模式:用于编辑供人类阅读的文本的主要模式。” Emacs 决定(通过auto-mode-alist 变量)如果您访问与某些扩展名匹配的文件名(例如.txt),它应该切换到文本模式。

    在文本模式下,在突出显示区域的情况下按 TAB 会导致在该区域的每一行上依次调用 indent-according-to-mode。找到这个的稍微复杂的路径从C-h k TAB开始,它告诉我们TAB绑定到indent-for-tab-command,在这种情况下调用indent-region——该函数名称没有在帮助中明确说明,但可以在代码中看到——它检查缓冲区局部 indent-region-function 变量,它是 nil,并且:“nil 的值意味着真的在每一行上运行 indent-according-to-mode。”

    indent-according-to-mode 检查indent-line-function 变量,该变量具有缓冲区本地值indent-relative

    使用C-h f indent-relative RET 查看此功能的帮助。 (阅读本文)。

虽然您可能还没有经验知道如何检查所有内容(或者不一定想要!),并且完全理解它告诉您的所有内容,但这是一个示例Emacs 使用户能够弄清楚发生了什么(这使得改变事物变得可行)。我基本上只是使用C-h k(describe-key)、C-h f(describe-function)和C-h v(describe-variable)来遵循文档。查看indent-for-tab-command 的源代码就像单击其帮助页面中显示的文件名一样简单。

我建议执行以下操作以帮助查看indent-relative 在每一行上运行时发生的情况:

M-x set-variable x-stretch-cursor tM-x set-variable ruler-mode-show-tab-stops tM-x ruler-mode

现在对于每一行,将光标放在该行的最开头并按 TAB。您最终会将所有三行缩进到第一个制表位(标尺中的“T”)。

现在重复一遍 - 再次确保您位于每行的开头,在现有缩进的前面。

第一行的第一个字符(当前是一个制表符)再次缩进到第一个制表位,因为没有前行可供它检查。

接下来,第二行的第一个字符缩进以匹配前一行的第一个非空白字符的位置。因为第二行的第一个字符也是一个制表符,所以第二行的实际文本被向前推了一个制表符。

第三行也是如此。它的第一个制表符与第二行的第一个非空白字符对齐,具有与以前相同的相对效果,为您提供示例中的最终状态。

为了强调,请注意如果您现在将输入行“a b c”放在现有行的上方,然后返回到下一行的开头(之前的第一行)并按 TAB 会发生什么。现在第一个制表符将缩进与“b”一致。假设 indent-tabs-mode 变量为真(意味着您有实际的制表符),那么这不会对行中单词的位置产生实际影响,因为“缩进”带有空格的制表符直到空格数超过了标签的宽度(但这完全是另一锅鱼!)

这实际上意味着 Emacs 中的 text-mode 在这种情况下不会像您希望的那样运行。当然,其他主要模式在按 TAB 时可以做完全不同的事情。

就像 Emacs 一样,你不喜欢的东西可以用 elisp 改变或规避。一些搜索(尤其是在 Emacs Wiki 中)会经常为您遇到的问题找到有用的解决方案。

【讨论】:

【参考方案2】:

在 Emacs 取消选择后尝试键入 C-x C-x。

然后,不要点击tab(我从来不知道tab 会按照你说的那样做!这完全被打败了。),而是点击M-8 C-x C-i。可惜它有这么多键,但它应该做你想做的事——也就是说,把所有东西都推到 8 列上。如果您想要其他数量的列,显然将M-8 替换为其他内容。

【讨论】:

我试过这个,它有点工作。 Emacs 确实重新选择了我的文本,我可以再次点击制表符,但是,它通过在其上方的行上方增加一个制表符空间来增加选择的每一行。例如,如果我突出显示三行并点击制表符,它会将所有行缩进 1 个制表符空间。接下来,我点击 C-x C-x 重新选择文本。然后我再次点击制表符,第 1 行缩进 1 个额外的制表符空格,第 2 行缩进 2 个额外的制表符空格,第 3 行缩进 3 个制表符空格。现在我的文件看起来像一个阶梯!任何其他想法! 虽然按这么多键有点困难,但这确实有效,这就是我的目标。我从来不知道 Emacs 会这么难,但我想随着时间的推移它会变得更容易。谢谢!【参考方案3】:

我通常做的只是在停用该区域的命令后键入 C-x C-x (exchange-point-and-mark)。

【讨论】:

我尝试了您的命令(与 offby1 给出的相同),并在我对 offby1 的评论中列出了结果。任何想法为什么? 你当时处于什么主要模式?你在编辑什么样的文本?您能否将其缩小到显示该行为的最小文本片段并将其添加到您的原始问题中?【参考方案4】:

你是如何缩进的,在哪种模式下?

任何编程模式下的缩进规则通常都应该是正确的。 (如果他们不这样做,那可能更表明您希望以不同方式配置该模式的规则,但我怀疑这是已经提出的另一个问题)。

如果您处于文本模式或类似模式并且仅使用 TAB,那么我可以看到问题。

请注意,如果您使用的是 indent-rigidlyC-x C-iC-x TAB,这是同一件事),那么您可以通过重复命令重复缩进同一区域,即使如果突出显示已从视图中消失。

您还可以在indent-rigidly 上使用前缀arg 使其缩进多次。例如C-u C-u C-x C-i(比它看起来更容易键入)将缩进 16 个空格(4 x 4,因为前缀 arg 默认为 4,并且它在每次重复时相乘)。同样,M-8 C-x C-i 缩进 8 个空格。这在某些情况下很好,但在其他情况下太麻烦了。

我个人建议将(cua-selection-mode 1) 放入您的 .emacs 中并使用它来进行严格的缩进。 Trey Jackson made a handy blog about it。有了这个,你可以C-RET开始矩形选择,down你需要多少行,TAB重复缩进行,C-RET退出模式。

当矩形处于活动状态时,RET 会循环通过角。对于左角,在前面键入插入。对于右角,在之后键入插入。对于单列矩形,为此,底部计为“左”,顶部计为“右”。

Trey 的博客列出了所有可用的功能(或查看源文件:cua-base.el)

请注意,Emacs 中的缩进通常为 an unexpectedly complicated topic。

【讨论】:

哇,这确实比我想象的要复杂。我会尝试一下你的建议,但我可以肯定地说,只需要在 gEdit 中突出显示文本并按所需的次数按 Tab 后就很难习惯。恐怕我不确定您所说的哪种模式是什么意思?对不起,我对 Emacs 语言学还是很陌生。我目前正在编辑一个纯文本文件,尽管我也会大量使用 Emacs 来编辑 Java 文件。我希望这会有所帮助!感谢您的建议! 模式是 Emacs 的基础;它们使它能够针对不同类型的内容表现出不同/适当的行为。每个缓冲区有一个单一的“主要模式”和可能在任何给定缓冲区中活动的许多“次要模式”。模式行指示主要模式(至少)。您还可以键入 C-h m 以查看有关您键入该命令的缓冲区的所有活动模式的信息。 鉴于这对您来说是多么新鲜,我强烈建议您遵循一些教程和其他帮助工具。他们将在初始学习曲线上取得显着进展。 Emacs 有一个内置教程 (C-h t)。它不短,但 Emacs 也不小 :) 以下是其他几个起点:***.com/questions/210791/good-resources-for-emacs***.com/questions/502399/… @phils,我会试试这个。谢谢!【参考方案5】:

您可以通过以下方式做到这一点:

(add-hook 'text-mode-hook (lambda () (set (make-local-variable 'indent-region-function) (lambda (s e) (indent-rigidly s e tab-width)))))

然后选择一个区域并点击TAB。将以制表符宽度缩进该区域。然后你可以用C-x C-x交换点和标记,然后再次点击TAB重复。

不过,我同意之前建议直接使用indent-rigidly 的答案。

【讨论】:

以上是关于Emacs 记住文本选择的主要内容,如果未能解决你的问题,请参考以下文章

请问在linux终端,怎么用键盘选中需要复制的文本啊?就跟vim中的块选择类似的功能。

理解 Emacs 完成模式选择

Emacs术语模式:通过双击鼠标选择单词

如何在 Emacs 中选择或突出显示一个块?

放弃 VSCode,再次选择使用十年之久的 Emacs

Emacs 补全:自动补全还是公司? [关闭]