Re: [code] [textadept] Caret horizontal position jumps after buffer switch -- FIXED

From: Qwerky <>
Date: Fri, 20 Sep 2019 19:05:29 -0600

Hi Mitchell,

On 2019-09-20 16:25, Mitchell wrote:
> Hi Qwerky,
> On Thu, 19 Sep 2019, Qwerky wrote:
>> Hi Mitchell,
>> On 2019-09-19 12:20, Mitchell wrote:
>>> Hi Qwerky,
>>> On Wed, 18 Sep 2019, Qwerky wrote:
>>>> Hi Mitchell,
>>>> On 2019-08-07 17:48, Qwerky wrote:
>>>>> On 2019-08-07 09:07, Mitchell wrote:
>>>>>> Hi,
>>>>>> On Tue, 6 Aug 2019, Qwerky wrote:
>>>>>>> On 2019-08-06 15:47, Qwerky wrote:
>>>>>>>> On 2019-08-06 13:42, Mitchell wrote:
>>>>>>>>> Hi,
>>>>>>>>> On Tue, 6 Aug 2019, Qwerky wrote:
>>>>>>>>>> Hi.  In my /USERHOME/init.lua, I have buffer.caret_sticky set to
>>>>>>>>>> buffer.CARETSTICKY_OFF (the default, confirmed to be '0'); I
>>>>>>>>>> have
>>>>>>>>>> also
>>>>>>>>>> tried
>>>>>>>>>> the other sticky options.  Regardless, the caret's horizontal
>>>>>>>>>> position
>>>>>>>>>> changes from what it was previously in a buffer, to a different
>>>>>>>>>> position
>>>>>>>>>> when
>>>>>>>>>> switching back to that buffer (happens for all buffers).
>>>>>>>>>> With two (or more) buffers open, place caret in buffer one at
>>>>>>>>>> known
>>>>>>>>>> column,
>>>>>>>>>> eg. 10, and place caret in buffer two at different known
>>>>>>>>>> column, eg.
>>>>>>>>>> 20.
>>>>>>>>>> From
>>>>>>>>>> buffer one, switch to buffer two.  Move caret up a line and back
>>>>>>>>>> down
>>>>>>>>>> again.
>>>>>>>>>> Switch back to buffer one, and move caret up (or down) a line.
>>>>>>>>>> Caret
>>>>>>>>>> jumps
>>>>>>>>>> from column 10 to column 20.
>>>>>>>>>> Is there some other setting that is responsible for this (I have
>>>>>>>>>> searched!)?
>>>>>>>>> I think the simplest explanation is that caret sticky is not a
>>>>>>>>> per-buffer
>>>>>>>>> setting, but a per-view one.
>>>>>>>>> Textadept does its best to try and differentiate between
>>>>>>>>> buffers and
>>>>>>>>> views
>>>>>>>>> as we know them, but Scintilla doesn't always make this easy.
>>>>>>>>> Cheers,
>>>>>>>>> Mitchell
>>>>>>>> Hi Mitchell,
>>>>>>>> Thanks.  I can't say I fully understand, but accept your word
>>>>>>>> on it.
>>>>>>>> When
>>>>>>>> I look at the code in /core/ui.lua for switching between
>>>>>>>> buffers, it
>>>>>>>> seems
>>>>>>>> to be saving/restoring the the caret location (which I believe
>>>>>>>> includes
>>>>>>>> both line and column), so I don't really understand why the caret
>>>>>>>> jumps
>>>>>>>> that way.  And I'm unsure what code modifications would correct
>>>>>>>> the
>>>>>>>> issue.
>>>>>>>> However, if someone saw a way to do so, I would not be averse to
>>>>>>>> modifying
>>>>>>>> the (Lua) code, as long as it doesn't mean recompiling. :-)
>>>>>>>> qwerky
>>>>>>> Hi Mitchell,
>>>>>>> This is just a hack, but it seems to correct the issue: In the
>>>>>>> 'events_connect(events.BUFFER_AFTER_SWITCH)' function of
>>>>>>> /core/ui.lua,
>>>>>>> just
>>>>>>> before the end of the function (immediately following the line
>>>>>>> 'buffer.x_offset = buffer._x_offset or 0'), I placed the two lines
>>>>>>> 'buffer.char_right()' and 'buffer.char_left()'.
>>>>>>> It seems that after the switch, the caret position is restored,
>>>>>>> but not
>>>>>>> somehow anchored to where it should be, so it looses track when the
>>>>>>> caret
>>>>>>> is
>>>>>>> moved to a new line (up or down).  The above hack just moves the
>>>>>>> caret
>>>>>>> right/left to anchor that position, before the user can move the
>>>>>>> caret
>>>>>>> to
>>>>>>> a
>>>>>>> new line, and is invisible to the user.  But I'm sure that you will
>>>>>>> know
>>>>>>> the
>>>>>>> correct way to fix it.
>>>>>> I have committed a proper fix[1]. Thanks for looking into this!
>>>>>> Cheers,
>>>>>> Mitchell
>>>>>> [1]:
>>>>> Hi Mitchell,
>>>>> Thanks.  Your fix is working well for me.  I even tried it with
>>>>> 'sticky'
>>>>> on, and it seemed to work well still.  :-)
>>>>> qwerky
>>>> While this fix works in the general case, I'm sorry to report that
>>>> it does
>>>> not work when virtual space is involved.  I've implemented a fix in
>>>> ui.lua
>>>> as
>>>> follows:
>>>> In events_connect(events.BUFFER_BEFORE_SWITCH, function(), saved the
>>>> virtual
>>>> column with the line:
>>>>   buffer._virtual_column =
>>>> buffer.selection_n_caret_virtual_space[buffer.main_selection]
>>>> and in events_connect(events.BUFFER_AFTER_SWITCH, function(),
>>>> cursor-right
>>>> to
>>>> the saved virtual column by addition of the lines:
>>>>   local i = buffer._virtual_column
>>>>   while i > 0 do
>>>>     buffer.char_right()
>>>>     i = i - 1
>>>>   end
>>>> While this does fix the issue, it is a kludge, and I'm sure you
>>>> will be
>>>> able
>>>> to implement a proper fix.
>>>> Even from my earliest postings, I'm sure you know that I am likely
>>>> your
>>>> most
>>>> ardent virtual-space/unbound-cursor/free-cursor user!  :-)
>>> Try this[1].
>>> Cheers,
>>> Mitchell
>>> [1]:
>> Thanks for the fast response.  The fix works well in the general
>> case, and
>> even in the general virtual-space case--excellent!  And the code is much
>> nicer than mine.
>> The only issue I see, has to do with rectangular selections--and I am
>> referring now even to rectangular selections made in the usual way
>> (that is
>> to say, with <shift-alt> or with the mouse), without reference to my
>> Rectangular Selections module.
>> If you make a stream selection in each of several buffers, with each
>> selection ending at a different column but in virtual space, and move
>> back
>> and forth among the buffers, the caret returns to the correct
>> column.  Very
>> good.
>> But, if one of the selections is a rectangular selection, and still
>> ending in
>> virtual space, then when you return to that buffer, the caret is in a
>> different column.
>> In your fix, in each of the lines with
>> buffer.selection_n_XXX_virtual_space[0], I changed the '0' to
>> 'buffer.main_selection':
>> buffer.selection_n_XXX_virtual_space[buffer.main_selection], and this
>> seemed
>> to correct the issue.
>> Please try, and you can tell me if I'm way off base here, or whether
>> it does
>> indeed correct.
> Okay, I committed what I think is the fix[1].
> Cheers,
> Mitchell
> [1]:

In my testing, this perfectly fixes the problem of the caret not
restoring to the correct column!

However, there is an issue with selections.  With stream selection,
leaving and returning to the buffer restores the caret position, and the
selection is intact; the user can continue to modify the selection
exactly where he left off.  Excellent!

But with rectangular selections, when returning to the buffer, while the
caret position is correct (the issue being addressed in this thread),
the rectangular selection changes its width and horizontal position. 
This is true both with, and without, the line `if buffer._sel_rectangle
then buffer.selection_mode = buffer.SEL_RECTANGLE end` in the last fix.

But there is a difference:  when `buffer.selection_mode` is set (as with
that line), whether to RECTANGLE or to STREAM, from that point on
selection is in effect, so that moving the caret with the arrow keys, or
indeed any other navigation, *even without any modifiers*, extends the
selection!  The user must press <ESC> to stop selection.

In my opinion, this goes back to what we were discussing in another
thread, re:  how does Scintilla track whether or not a selection is
rectangular.  And, again in my opinion, I believe it is by (the
Scintilla counterpart of) `buffer.selection_is_rectangle` which, being
read-only, one cannot restore--at least not directly.

So, I would recommend removing that line which sets
`buffer.selection_mode`.  The only remaining issue then is, can a
rectangular selection be resumed after returning to a buffer.  If no
solution to that is found, though not ideal, it is something I can live
with; though of course a solution would be welcomed.  But if there is no
solution, then I would recommend cancelling any rectangular selection
(but not stream selection) when returning to a buffer.


You are subscribed to
To change subscription settings, send an e-mail to
To unsubscribe, send an e-mail to
Received on Fri 20 Sep 2019 - 21:05:29 EDT

This archive was generated by hypermail 2.2.0 : Sat 21 Sep 2019 - 06:49:49 EDT