Adding simple macros to Textadept
DRY
Textadept is a very programmable text editor. It's as programmable as vim or emacs. Ok, maybe not. But it's much much smaller and simpler than they so even editing some of its less than 2,000 lines of C code is not a big deal. But mostly it's in Lua. The Lua code wraps much of internals of the editor and adds capabilities to build GUI, compose lexers and themes and — following vim/emacs tradition — to write configurations and plugins.
In this article we'll write a module for Textadept for simple macro recording and playback.
Keyboard events
In Textadept we can connect Lua function to any event using the code
events.connect(events.EVENT_NAME, function)
There're KEYPRESS
and CHAR_ADDED
events. KEYPRESS
is fired on any key and receives key code and its modifiers (ctrl,alt,shift,meta), CHAR_ADDED
fired only if KEYPRESS
wasn't handled (no shortcut). In this case the key is passed to Scincilla. This behavior looks ok, but by default Textadpt dont create shortcuts for all of its actions, for example there're no shortcuts for navigation keys and they are handled directly by Scincilla. This complicates recording of macros so we'll fix this:
-- assign navigation keys to commands for proper recording
keys.left = buffer.char_left
keys.left = buffer.char_left
keys.sleft = buffer.char_left_extend
keys.cleft = buffer.word_left
keys.csleft = buffer.word_left_extend
keys.right = buffer.char_right
keys.sright = buffer.char_right_extend
keys.cright = buffer.word_right
keys.csright = buffer.word_right_extend
keys.up = buffer.line_up
keys.sup = buffer.line_up_extend
keys.down = buffer.line_down
keys.sdown = buffer.line_down_extend
keys.home = buffer.home
keys.shome = buffer.home_extend
keys['end'] = buffer.line_end
keys.send = buffer.line_end_extend
keys['\b'] = buffer.delete_back
keys['c\b'] = buffer.del_word_left
keys.del = buffer.clear
keys.cdel = buffer.del_word_right
Now all action keys have associated Lua functions, and we can easily record a macro.
Recording
To do this we need a couple of variables
local recording_macro = false
local macro = {}
and event handler for KEYPRESS event
events.connect(events.KEYPRESS,
function(code, shift, control, alt, meta)
if recording_macro then
table.insert(macro, {events.emit, {events.KEYPRESS, code, shift, control, alt, meta}})
end
end, 1)
This handler just saves event arguments in table macro
if we are recording_macro
. This allows as to replay any actions executed by shortcuts.
Also, we add a similar CHAR_ADDED
event handler to record letters typed by user too:
events.connect(events.CHAR_ADDED, function(byte)
if recording_macro then
table.insert(macro, {buffer.add_text, {string.char(byte)}})
end
end)
Notice how flexible is Lua here: we can easily save the function to call and its parameters in one table. And later we'll call these functions in universal way too.
Module
To use our new code we would wrap it in module macro
.
An module in Textadept is just a Lua file which is placed in ~/.textadept/modules and looks like:
local M = {}
--- body of the module --
return M
Later, we can load this module by local macro = require('macro')
.
What is the M
returned by the module? It is API that we expose to editor. In our module we'll export three functions:
function M.record()
macro = {}
recording_macro = true
ui.statusbar_text = 'recording macro'
end
function M.finish()
if recording_macro then
recording_macro = false
ui.statusbar_text = 'macro recorded'
end
end
function M.replay()
events.emit(events.KEYPRESS, 27, nil, nil, nil, nil)
for k,cmd in pairs(macro) do
cmd[1](unpack(cmd[2]))
end
end
Notice that events.emit
line in replay
function. This is my workaround without which Textadept for some reason don't handle next commands. (27
is code of Esc button.)
Declared functions can now be accessed through names macro.record
, macro.finish
and macro.replay
. We can link them to some shortcuts using the code like
keys.cr = macro.record
keys.cR = macro.finish
keys.ar = macro.replay
Ctrl+R, Ctrl+Shift+R, Alt+R.
Demonstration
Convert some list of numbers to array:
Links
ta-macro — the module on git.
Textadept home page http://foicica.com/textadept, where you can find a manual, full API reference, wiki and subscribe to the mailing list.
Lua home page www.lua.org, and there's a good text book "Programming in Lua".
Scincilla home page www.scintilla.org.
DRY, DRY, DRY]
shitpoet@gmail.com