当点位于换行符时,关闭Emacs中的缩进标签模式会导致移动到列时出现故障

时间:2013-12-27 12:26:16

标签: emacs elisp

当光标处于换行符并且我已关闭(move-to-column pos t)时,我遇到问题indent-tabs-mode正常工作,即:(setq-default indent-tabs-mode nil)

在这种情况下,如果例如该点位于第0列,并且此时有一个换行符(使用(whitespace-mode)查看换行符很有帮助)并发出命令{{ 1}}该点不会移动到第10列。而是将该点移动到第9列。

更新

要说明问题,请首先考虑以下Emacs缓冲区

enter image description here

(颜色归因于(move-to-column 10 t))。光标位于缓冲区第二行的第0列。光标前面有一个换行符。我现在发出命令(whitespace-mode),我得到了以下屏幕

enter image description here

请注意,光标位于第9列(不是第10列,应该如此)。如果光标未定位到换行符,并且在接下来的10个缓冲区中没有换行符,则(move-to-column 10 t)按预期工作。例如,请考虑以下情况

enter image description here

请注意,现在没有换行符(位于缓冲区第三行的开头),并且在以下10个缓冲区位置中没有换行符。如果我现在发出{{1}我得到了

enter image description here

我们看到这一点已经转移到第10列,因为它应该......

1 个答案:

答案 0 :(得分:2)

现在至少部分回答:

我在Ubuntu 13.04下使用emacs 24.3.1。 在那里,效果只能用whitespace-mode重现。因此,indent-tabs-mode以及dos或unix的缓冲区编码并不重要。

whitespace-mode摆弄了buffer-display-table

修改后的buffer-display-table很容易导致move-to-column的意外结果。

如果执行以下代码(例如,使用 M - :),move-to-columnwhitespace-mode的效果可以在没有whitespace-mode的情况下重现:

(setq buffer-display-table (make-display-table))
(aset buffer-display-table ?\n [?$ ?\n])

您可以通过以下方式恢复此效果:

(aset buffer-display-table ?\n nil)

如果更改任何其他文本字符的显示字符数,您将获得move-to-column的类似意外效果。 E.g:

使用

(aset buffer-display-table ?\§ [?\§ ?\$])

和缓冲区内容

§

你得到了显示

§$

如果您呼叫(move-to-column 1 t)点移动到此显示字符串的末尾,即使这会显示两个字符。

您可以通过以下方式恢复此设置:

(aset buffer-display-table ?\§ nil)

另一个相当有趣的设置是:

(aset buffer-display-table ?\n [?1 ?2 ?3 ?\n])

使用此设置,换行符长度为三个显示字符(仅限换行符)。 一个换行符显示为:

123

如果当前点位于该行的开头,则命令(move-to-column 3 t)不会移动点但返回3.

请注意,此行为与正常设置的情况一致

(aset buffer-display-table ?\n nil)

如果有两个连续的换行符并且点位于介于两者之间,那么即使第0列上没有字符,(move-to-column 0 t)也会在换行符之前放置点。

也许,这与点位置在字符之间的解释有关。对于空缓冲区,其中(point) == (point-min) == (point-max)。这种解释也赋予(point-max) == (1+ (buffer-size))其含义。

我在此引用信息节点following-char(elisp) Near Point的说明:

“请记住,点始终在字符和光标之间    通常出现在角色跟随点之上。因此,    `following-char'返回的字符是字符    光标结束了。“


字符与move-to-column

之间的点位置

(注意,以下仅仅是我的解释。如果真正了解move-to-column功能意图的人能够承认,否认或纠正这些内容,那将是很好的。)

以下讨论说明move-to-column的字符之间的点位置的后果。 我们用pos0,pos1,...表示点位置,用char1,char2,......表示字符。 如果buffer-display-table中的字符char1的条目是长度为>的向量[char1a char1b ...],我们使用标记char1a,char1b,.... 1.在下文中,我们将此字符命名为 复合字符

正常情况(无复合字符):

pos0 char1 pos1 char2 pos2 nl

(move-to-column 2 t)表示将点放在nlchar之前。

buffer-display-table中复合字符char1 = [char1a char1b]的情况:

pos0 char1a pos1 char1b pos2 nl

move-to-column尊重复合字符的显示大小,但不能将点放在中间。 Point只能放在复合字符的边界上。

在这种情况下,(move-to-column 1 t)移动指向位置pos2。

现在,让新行字符为组合字符nl = [nla nlb]。

pos0 char1 pos1 char2 pos2 nla pos3 nlb

此处,(move-to-column 3 t)到达组合换行符的中间。

点还在这一行。因此将点放在nlb之后是没有意义的。 Emacs不能在pos3处放置点,因为它位于组合字符的中间。因此,定位点的唯一合理方法是pos2。