aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/textadept/macros.lua39
-rw-r--r--test/test.lua33
2 files changed, 54 insertions, 18 deletions
diff --git a/modules/textadept/macros.lua b/modules/textadept/macros.lua
index a965b254..b8fe7f63 100644
--- a/modules/textadept/macros.lua
+++ b/modules/textadept/macros.lua
@@ -30,12 +30,14 @@ local function event_recorder(event)
end
local event_recorders = {
[events.KEYPRESS] = function(code, shift, control, alt, meta)
+ -- Not every keypress should be recorded (e.g. toggling macro recording).
+ -- Use very basic key handling to try to identify key commands to ignore.
local key = code < 256 and string.char(code) or keys.KEYSYMS[code]
if key then
- -- Note: this is a simplified version of key handling.
- shift = shift and (code >= 256 or code == 9)
- local key_seq = (control and 'c' or '')..(alt and 'a' or '')..
- (meta and OSX and 'm' or '')..(shift and 's' or '')..key
+ if shift and code >= 32 and code < 256 then shift = false end
+ local key_seq = string.format(
+ '%s%s%s%s%s', control and 'c' or '', alt and 'a' or '',
+ meta and OSX and 'm' or '', shift and 's' or '', key)
for i = 1, #ignore do if keys[key_seq] == ignore[i] then return end end
end
macro[#macro + 1] = {events.KEYPRESS, code, shift, control, alt, meta}
@@ -70,13 +72,16 @@ end
-- @name play
function M.play()
if recording or not macro then return end
- events.emit(events.KEYPRESS, 27) -- needed to initialize for some reason
- for i = 1, #macro do
- if macro[i][1] == events.CHAR_ADDED then
- local f = buffer[buffer.selection_empty and 'add_text' or 'replace_sel']
- f(buffer, utf8.char(macro[i][2]))
+ -- If this function is run as a key command, `keys.keychain` cannot be cleared
+ -- until this function returns. Emit 'esc' to forcibly clear it so subsequent
+ -- keypress events can be properly handled.
+ events.emit(events.KEYPRESS, not CURSES and 0xFF1B or 7) -- 'esc'
+ for _, event in ipairs(macro) do
+ if event[1] == events.CHAR_ADDED then
+ local f = buffer.selection_empty and buffer.add_text or buffer.replace_sel
+ f(buffer, utf8.char(event[2]))
end
- events.emit(table.unpack(macro[i]))
+ events.emit(table.unpack(event))
end
end
@@ -95,17 +100,15 @@ function M.save(filename)
end
local f = assert(io.open(filename, 'w'))
f:write('return {\n')
- for i = 1, #macro do
- f:write('{"', macro[i][1], '",')
- for j = 2, #macro[i] do
- if type(macro[i][j]) == 'string' then f:write('"') end
- f:write(tostring(macro[i][j]))
- f:write(type(macro[i][j]) == 'string' and '",' or ',')
+ for _, event in ipairs(macro) do
+ f:write(string.format('{%q,', event[1]))
+ for i = 2, #event do
+ f:write(string.format(
+ type(event[i]) == 'string' and '%q,' or '%s,', event[i]))
end
f:write('},\n')
end
- f:write('}\n')
- f:close()
+ f:write('}\n'):close()
end
---
diff --git a/test/test.lua b/test/test.lua
index 80ec31c4..b0d035b5 100644
--- a/test/test.lua
+++ b/test/test.lua
@@ -2059,6 +2059,39 @@ function test_macro_record_play_save_load()
assert_raises(function() textadept.macros.load(1) end, 'string/nil expected, got number')
end
+function test_macro_record_play_with_keys_only()
+ if keys.f9 ~= textadept.macros.record then
+ print('Note: not running since F9 does not toggle macro recording')
+ return
+ end
+ buffer.new()
+ buffer:append_text('foo\nbar\nbaz\n')
+ events.emit(events.KEYPRESS, 0xFFC6) -- f9; start recording
+ events.emit(events.KEYPRESS, not CURSES and 0xFF57 or 305) -- end
+ events.emit(events.KEYPRESS, not CURSES and 0xFF0D or 13) -- \n
+ buffer:new_line()
+ events.emit(events.KEYPRESS, not CURSES and 0xFF54 or 300) -- down
+ events.emit(events.KEYPRESS, 0xFFC6) -- f9; stop recording
+ assert_equal(buffer:get_text(), 'foo\n\nbar\nbaz\n');
+ assert_equal(buffer.current_pos, buffer:position_from_line(LINE(3)))
+ if not CURSES then
+ events.emit(events.KEYPRESS, 0xFFC6, true) -- sf9; play
+ else
+ events.emit(events.KEYPRESS, 0xFFC7) -- f10; play
+ end
+ assert_equal(buffer:get_text(), 'foo\n\nbar\n\nbaz\n');
+ assert_equal(buffer.current_pos, buffer:position_from_line(LINE(5)))
+ if not CURSES then
+ events.emit(events.KEYPRESS, 0xFFC6, true) -- sf9; play
+ else
+ events.emit(events.KEYPRESS, 0xFFC7) -- f10; play
+ end
+ assert_equal(buffer:get_text(), 'foo\n\nbar\n\nbaz\n\n');
+ assert_equal(buffer.current_pos, buffer:position_from_line(LINE(7)))
+ buffer:set_save_point()
+ io.close_buffer()
+end
+
function test_menu_menu_functions()
buffer.new()
textadept.menu.menubar[_L['Buffer']][_L['Indentation']][_L['Tab width: 8']][2]()