Re: [code] [textadept] Key Modes

From: Qwerky <mr.qwerky.att.gmail.com>
Date: Wed, 10 Jul 2019 15:20:27 -0600

Hi,

On 2019-07-10 12:22, Mitchell wrote:
> Hi,
>
> On Wed, 10 Jul 2019, Qwerky wrote:
>
>> Hi,
>>
>> On 2019-07-10 10:13, Qwerky wrote:
>>>
>>> Hello,
>>>
>>> On 2019-07-09 18:51, Mitchell wrote:
>>>> Hi,
>>>>
>>>> On Tue, 9 Jul 2019, Qwerky wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> On 2019-07-09 17:11, Mitchell wrote:
>>>>>> Hi,
>>>>>>
>>>>>> On Tue, 9 Jul 2019, Qwerky wrote:
>>>>>>
>>>>>>> Hello,
>>>>>>>
>>>>>>> On 2019-07-09 09:43, Mitchell wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> On Mon, 8 Jul 2019, Qwerky wrote:
>>>>>>>>
>>>>>>>>> Hello.  Key bindings provide for key modes which, according to
>>>>>>>>> the
>>>>>>>>> documentation, provide a set of key bindings which are
>>>>>>>>> executed when
>>>>>>>>> that
>>>>>>>>> mode is active, to the exclusion of all other key bindings.
>>>>>>>>>
>>>>>>>>> Is it possible to have a mode, whose key bindings simply
>>>>>>>>> replace the
>>>>>>>>> same-named bindings while that mode is active, without
>>>>>>>>> blocking all
>>>>>>>>> other
>>>>>>>>> bindings[1]?
>>>>>>>>>
>>>>>>>>> An example would be a rectangular-select mode which, when active,
>>>>>>>>> would
>>>>>>>>> replace bindings such as caret-left-extend with
>>>>>>>>> caret-left-rectangular-extend, and so forth; but would not block
>>>>>>>>> other
>>>>>>>>> bindings, such as caret-left, line-down, etc. This would be
>>>>>>>>> extremely
>>>>>>>>> useful,
>>>>>>>>> in the given example, for making selection easier by not
>>>>>>>>> having to
>>>>>>>>> hold
>>>>>>>>> down
>>>>>>>>> the Alt key, and would also free up Alt key combinations for
>>>>>>>>> other
>>>>>>>>> functions.
>>>>>>>>>
>>>>>>>>> [1] The mode may also provide new bindings which do not exist
>>>>>>>>> outside
>>>>>>>>> the
>>>>>>>>> mode.
>>>>>>>>
>>>>>>>> Yes, I'm pretty sure this is possible. In your
>>>>>>>> *~/.textadept/init.lua*:
>>>>>>>>
>>>>>>>>   keys.my_mode = setmetatable({
>>>>>>>>     esc = function() keys.MODE = nil end, -- exit mode
>>>>>>>>     -- keys to handle specially go here
>>>>>>>>   }, {__index = function()
>>>>>>>>     return false -- propagate everything else
>>>>>>>>   end})
>>>>>>>>
>>>>>>>> Then set `keys.MODE = 'my_mode'` to initialize it (e.g. via a
>>>>>>>> function
>>>>>>>> bound to a key). Escape key, or whatever else you set, will go
>>>>>>>> back to
>>>>>>>> "normal" mode.
>>>>>>>>
>>>>>>>> Cheers,
>>>>>>>> Mitchell
>>>>>>>
>>>>>>> Thanks a lot for the example code, but unfortunately I can't get
>>>>>>> it to
>>>>>>> work.
>>>>>>> I copied your code to my init.lua, and then added two keys:
>>>>>>> 'sright' to
>>>>>>> extend rectangular selection to the right, and 'sdown' to extend
>>>>>>> rectangular
>>>>>>> selection down; and in my keys.lua added 'cl' to set keys.MODE to
>>>>>>> my_mode.
>>>>>>> When I press Control-L, the status bar becomes blank (presumably
>>>>>>> because I
>>>>>>> have the buffer status written to statusbar, and have bufstatusbar
>>>>>>> cleared);
>>>>>>> but when I press Shift-Right or Shift-Down (or any other key), it
>>>>>>> simply
>>>>>>> performs its normal function, and the status bar info returns.
>>>>>>> Here's
>>>>>>> what
>>>>>>> I
>>>>>>> now have:
>>>>>>>
>>>>>>> keys.my_mode = setmetatable({
>>>>>>>   esc = function() keys.MODE = nil end, -- exit mode
>>>>>>>   -- keys to handle specially go here
>>>>>>>   sdown = buffer.line_down_rect_extend,
>>>>>>>   sright = buffer.char_right_rect_extend
>>>>>>> }, {__index = function()
>>>>>>>   return false -- propagate everything else
>>>>>>> end})
>>>>>>>
>>>>>>> And have also tried ['sdown'] and ['sright'] with the same results.
>>>>>>> (Also
>>>>>>> tried keys['sdown'], but that gave an error.) Where is the problem?
>>>>>>
>>>>>> Please post your 'cl' keybinding.
>>>>>>
>>>>>> Cheers,
>>>>>> Mitchell
>>>>>
>>>>> This is what I have now:
>>>>>
>>>>> keys.cl = function()
>>>>>   keys.MODE = my_mode
>>>>>   ui.bufstatusbar_text = 'MY MODE'
>>>>> end
>>>>>
>>>>> Before that, it was just:
>>>>>
>>>>> keys.cl = function() keys.MODE = my_mode end
>>>>
>>>> You need 'my_mode' to be a string. When used as an identifier, its
>>>> value
>>>> is `nil`, so `keys.MODE` is being set to `nil`, which means default
>>>> behavior.
>>>>
>>>>   keys.cl = function() keys.MODE = 'my_mode' end
>>>>
>>>> Cheers,
>>>> Mitchell
>>>
>>> Duh!  After correcting my dumb mistake, it now works as intended. 
>>> Thanks!
>>>
>>> But after a little investigation, I'm not sure if this is the right
>>> path.
>>> Although there are rectangular selection functions such as
>>> buffer.char_left_rect_extend, etc., I can't find any .lua module which
>>> contains references to them, apart from /core/iface.lua, which
>>> references
>>> leave me baffled. Additionally, although I see keys like 'sleft'
>>> bound to a
>>> selection function, I can't find where any Alt keys such as 'asleft'
>>> are
>>> bound to functions.
>>>
>>> So I suppose that somewhere there is code that says "if alt and
>>> shift are
>>> both down, change selection mode from stream to rectangular." If
>>> that is
>>> the case, then even though my special mode would allow using
>>> 'sright' for
>>> rectangular selection, it may still not allow 'asright' to be bound
>>> to some
>>> other function without interference between that other function, and
>>> the
>>> "alt+shift" code mentioned?
>>>
>>> qwerky
>>>
>> It seems that after correcting my mistake, the mode-defined keys are now
>> working as I reported, but some other keys no longer function while
>> the mode
>> is active; eg. Control-Tab does move to the next tab, Control-Z does not
>> undo, and so forth, although most navigation keys still function. 
>> When the
>> mode is exited, the other keys resume functioning.  Thoughts?
>
> My bad. For your `__index` metatable function, try:
>
>   __index = function(t, k)
>     if keys[k] then return keys[k] end
>     return false
>   end
>
> That code prefers to return a global keybinding for the key typed.
> Otherwise, it falls back on Scintilla's default handling (e.g.
> character insertion, arrow keys, etc.).
>
> Cheers,
> Mitchell

Mitchell, thanks so much for your help!  This is what I have so far:

In keys.lua:

-- Rectangular Selection Mode.
keys.cl = function()
   keys.MODE = 'rectangular_mode'
   ui.bufstatusbar_text = 'Column Selection Mode'
   events.emit(events.UPDATE_UI) -- for updating statusbar
end

In my additions module:

-- Rectangular Selection Mode.
keys.rectangular_mode = setmetatable({
   cl = function()
     keys.MODE = nil -- exit mode
     ui.bufstatusbar_text = 'Stream Selection Mode'
     events.emit(events.UPDATE_UI) -- for updating statusbar
   end,
   sup = buffer.line_up_rect_extend,
   sdown = buffer.line_down_rect_extend,
   sleft = buffer.char_left_rect_extend,
   sright = buffer.char_right_rect_extend,
   shome = buffer.vc_home_rect_extend,
   send = buffer.line_end_rect_extend,
   spgup = buffer.page_up_rect_extend,
   spgdn = buffer.page_down_rect_extend,
}, {__index = function(t, k)
   if keys[k] then return keys[k] end -- propagate other global keybindings
   return false -- propagate everything else
end})

This works well.  Control-L (the binding I'm used to, from ConTEXT)
toggles rectangular selection mode on/off, which status is also
reflected on the ui.statusbar (would normally be the ui.bufstatusbar)
via my updated event handler--in addition to the message displayed. 
When on, Shift-Arrow, etc. perform rectangular selection without the
need to add the Alt key; other keys perform their usual function.

The remaining issue is with the use of Shift-Alt key combinations, as
I'll discuss in my other e-mail dealing with that.

qwerky

-- 
You are subscribed to code.att.foicica.com.
To change subscription settings, send an e-mail to code+help.att.foicica.com.
To unsubscribe, send an e-mail to code+unsubscribe.att.foicica.com.
Received on Wed 10 Jul 2019 - 17:20:27 EDT

This archive was generated by hypermail 2.2.0 : Thu 11 Jul 2019 - 06:35:03 EDT