简体   繁体   中英

Turning off indent-tabs-mode in Emacs causes malfunction in move-to-column when point is at a newline character

I have problem making (move-to-column pos t) work correctly when the cursor is at newline character and I have turned off indent-tabs-mode , that is: (setq-default indent-tabs-mode nil) .

In that case, if for instance the point is at column 0, and there is a newline character at that point ( it is helpful to use (whitespace-mode) to see the newline characters ) and I issue the command (move-to-column 10 t) the point does not move to column 10. Instead the point moves to column 9.

Update

To give an illustration of the problem, consider first the following Emacs buffer

在此处输入图片说明

(the colors are due to (whitespace-mode) ). The cursor is position at column 0 at the second line of the buffer. There is a newline character just in front of the cursor. I now issue the command (move-to-column 10 t) and I get the follwing screen

在此处输入图片说明

Note that the cursor is positioned at column 9 (not at column 10, as it should). If the cursor is not positioned at a newline character and there are no newline characters at the next 10 buffer positions move-to-column works as expected. For instance, consider the following case

在此处输入图片说明

Notice that there now is no newline characters at the point (which is at the beginning of the third line in the buffer) and there is no newline characters in the following 10 buffer positions.. If I now issue (move-to-column 10 t) I get

在此处输入图片说明

and we see that the point has moved to column 10 as it should..

At least a partial answer for now:

I am using emacs 24.3.1 under Ubuntu 13.04. There, the effect is only reproducible with whitespace-mode . Thereby, indent-tabs-mode and also the buffer encoding as dos or unix do not really matter.

whitespace-mode fiddles with the buffer-display-table .

With a modified buffer-display-table one easily gets unexpected results for move-to-column .

The effect of move-to-column with whitespace-mode can already be reproduced without whitespace-mode if one executes the following code (use, eg, M-: ):

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

You can revert this effect by:

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

You get a similarly unexpected effect of move-to-column if you change the number of displayed characters for any other text character. Eg:

With

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

and the buffer content

§

you get the display

§$

If you call (move-to-column 1 t) point moves to the end of this displayed string even if this makes two displayed characters.

You can revert this setting by:

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

A further rather interesting setting is:

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

With this setting the newline character is three displayed characters long (exclusively the line break). One linebreak is shown as:

123

If the current point is at the beginning of that line the command (move-to-column 3 t) does not move point but returns 3.

Note, that this behaviour is consistent with the case of the normal setting

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

If there are two consecutive linebreaks and point is positioned in between then (move-to-column 0 t) does place point before the linebreak even if there is no character on column 0.

Maybe, this is connected to the interpretation of point positions as being between characters. For an empty buffer one has (point) == (point-min) == (point-max) . This interpretation also gives (point-max) == (1+ (buffer-size)) its meaning.

I cite here the description of following-char in the info-node (elisp) Near Point :

"Remember that point is always between characters, and the cursor normally appears over the character following point. Therefore, the character returned by `following-char' is the character the cursor is over."


Point positions between characters and move-to-column

(Note, the following is just my interpretation. It would be nice if someone who really knows the intentions in the features of move-to-column could acknowledge, deny, or correct this stuff.)

The following discussion illustrates the consequences of point positions between characters for move-to-column . We denote the point positions by pos0, pos1,... and the characters with char1, char2,.... We use the denotation char1a, char1b, ... if the entry of a character char1 in buffer-display-table is a vector [char1a char1b ...] of length > 1. In the following we name such an character as compound character .

Normal case (no compound characters):

pos0 char1 pos1 char2 pos2 nl

(move-to-column 2 t) means to position the point before the nlchar.

Case with a compound character char1 = [char1a char1b] in buffer-display-table :

pos0 char1a pos1 char1b pos2 nl

move-to-column respects the display size of the compound character but it cannot put point in the middle of it. Point can only be placed at the boundaries of the compound character.

In this case (move-to-column 1 t) moves point to position pos2.

Now, let the new-line character be a composed character nl = [nla nlb].

pos0 char1 pos1 char2 pos2 nla pos3 nlb

Here, (move-to-column 3 t) arrives in the middle of the composed newline character.

Point is still on this line. So it does not make sense to put point behind nlb. Emacs cannot place point at pos3 since this is in the middle of a composed character. Thus, the only sensible way to position point is pos2.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM