On Sat, Feb 09, 2013 at 02:10:36PM +0100, Bram Moolenaar wrote:

> I rather fix the problem than updating the documentation.

Sounds great; I mispredicted your response.

> You say you read the source code, can you pinpoint why the cursor is
> not restored when using :normal?

:normal commands update curwin->w_curswant and curwin->w_set_curswant,
which beginline() uses to set the cursor position. op_reindent calls
beginline() with the BL_SOL flag set, so this bug only appears when
'nostartofline' is set (which I didn't notice before).

Attached patch simply saves and restores both settings after the
'indentexpr' evaluation.

Thank you,
Sung Pae
From d3b2700ff6a115b1b90bab91188da24235c726ac Mon Sep 17 00:00:00 2001
From: guns <[email protected]>
Date: Sat, 9 Feb 2013 12:43:37 -0600
Subject: [PATCH] Restore curswant settings after indentexpr evaluation

get_expr_indent() attempts to restore cursor position after evaluating
'indentexpr', but the use of :normal commands like:

        normal! w

changes the values of curwin->w_curswant and curwin->w_set_curswant
either through update_curswant(), or directly (like :normal $).

This affects the cursor position when 'nostartofline' is set because the
= command calls beginline() with the BL_SOL flag.
---
 src/misc1.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/misc1.c b/src/misc1.c
index ab42f04..babcfe9 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -8810,12 +8810,16 @@ get_expr_indent()
 {
     int                indent;
     pos_T      pos;
+    colnr_T    old_curswant;
+    int                old_set_curswant;
     int                save_State;
     int                use_sandbox = was_set_insecurely((char_u *)"indentexpr",
                                                                   OPT_LOCAL);
 
     pos = curwin->w_cursor;
     set_vim_var_nr(VV_LNUM, curwin->w_cursor.lnum);
+    old_curswant = curwin->w_curswant;
+    old_set_curswant = curwin->w_set_curswant;
     if (use_sandbox)
        ++sandbox;
     ++textlock;
@@ -8833,6 +8837,10 @@ get_expr_indent()
     check_cursor();
     State = save_State;
 
+    /* Also restore curswant in case it was changed via :normal commands */
+    curwin->w_curswant = old_curswant;
+    curwin->w_set_curswant = old_set_curswant;
+
     /* If there is an error, just keep the current indent. */
     if (indent < 0)
        indent = get_indent();
-- 
1.8.1.3

Attachment: pgpTPMMar7zfe.pgp
Description: PGP signature

Raspunde prin e-mail lui