aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/ext/menu.lua10
-rw-r--r--core/init.lua19
-rw-r--r--modules/textadept/macros.lua70
-rw-r--r--src/lua_interface.c21
4 files changed, 75 insertions, 45 deletions
diff --git a/core/ext/menu.lua b/core/ext/menu.lua
index 2b3209e6..78d706bc 100644
--- a/core/ext/menu.lua
+++ b/core/ext/menu.lua
@@ -111,6 +111,11 @@ t.menubar = {
'_Update Multiple Lines',
'_Finished Editing',
},
+ { title = 'M_acros',
+ '_Start Recording',
+ 'S_top Recording',
+ '_Play Macro'
+ },
},
gtkmenu {
title = '_Buffers',
@@ -165,6 +170,7 @@ local b, v = 'buffer', 'view'
local m_snippets = _m.textadept.lsnippets
local m_editing = _m.textadept.editing
local m_mlines = _m.textadept.mlines
+local m_macros = _m.textadept.macros
local function pm_activate(text) t.pm.entry_text = text t.pm.activate() end
local function toggle_setting(setting)
@@ -267,6 +273,10 @@ local actions = {
['Remove Multiple Lines'] = { m_mlines.remove_multiple },
['Update Multiple Lines'] = { m_mlines.update },
['Finished Editing'] = { m_mlines.clear },
+ -- Tools -> Macros
+ ['Start Recording'] = { m_macros.start_recording },
+ ['Stop Recording'] = { m_macros.stop_recording },
+ ['Play Macro'] = { m_macros.play },
-- Buffers
['Next Buffer'] = { 'goto_buffer', v, 1, false },
['Prev Buffer'] = { 'goto_buffer', v, -1, false },
diff --git a/core/init.lua b/core/init.lua
index 84c0d4d6..7a25169b 100644
--- a/core/init.lua
+++ b/core/init.lua
@@ -38,21 +38,24 @@ end
-- used.
-- @return string CocoaDialog result.
function cocoa_dialog(kind, opts)
- local args = not MAC and { kind } or ''
+ local args = { kind }
for k, v in pairs(opts) do
- if not MAC then
- args[#args + 1] = '--'..k
- if type(v) == 'string' then args[#args + 1] = v end
- else
- args = args..' --'..k
- if type(v) == 'string' then args = args..' "'..v..'"' end
+ args[#args + 1] = '--'..k
+ if k == 'items' and kind:match('dropdown') then
+ if not MAC then
+ for item in v:gmatch('"(.-)"%s+') do args[#args + 1] = item end
+ else
+ args[#args + 1] = v
+ end
+ elseif type(v) == 'string' then
+ args[#args + 1] = not MAC and v or '"'..v..'"'
end
end
if not MAC then
return lua_dialog.run(args)
else
local cocoa_dialog = '/CocoaDialog.app/Contents/MacOS/CocoaDialog '
- local p = io.popen(_HOME..cocoa_dialog..kind..args)
+ local p = io.popen( _HOME..cocoa_dialog..table.concat(args, ' ') )
local out = p:read('*all')
p:close()
return out
diff --git a/modules/textadept/macros.lua b/modules/textadept/macros.lua
index 67709a02..8b51fd13 100644
--- a/modules/textadept/macros.lua
+++ b/modules/textadept/macros.lua
@@ -14,9 +14,9 @@ local MACRO_FILE = _HOME..'/saved_macros'
-- The list of available macros.
-- Each key is the macro name, and the value is a numerically indexed table of
-- commands. Each command is a table with a structure as follows:
--- { command, wParam, lParam, type = 'function' or 'property' }
--- where command is the buffer function or property name (depending on type)
--- and wParam and lParam are the arguments for it.
+-- { command, wParam, lParam }
+-- where command is the buffer function and wParam and lParam are the arguments
+-- for it.
-- @class table
-- @name list
list = {}
@@ -38,7 +38,7 @@ local recording = false
-- @param msg The Scintilla message ID.
local function macro_notification(msg, wParam, lParam)
if recording then
- current[#current + 1] = { msg, wParam or '', lParam or '' }
+ current[#current + 1] = { msg, wParam or 0, lParam or 0 }
textadept.statusbar_text = 'Macro recording'
end
end
@@ -57,36 +57,27 @@ end
---
-- Stops recording a macro.
-- Each command's msg in the recorded macro is changed to the name of the
--- message and the type of the command is changed appropriately (function or
--- property). Then the user is prompted for a macro name and the macro is saved
--- to the current macro list and macro file.
+-- message Then the user is prompted for a macro name and the macro is saved to
+-- the current macro list and macro file.
function stop_recording()
if not recording then return end
buffer:stop_record()
recording = false
local textadept = textadept
- local bf, bp = textadept.buffer_functions, textadept.buffer_properties
- local macro_name = cocoa_dialog( 'standard-inputbox', {
- title = 'Save Macro',
- text = 'Macro name:',
+ local ret, macro_name = cocoa_dialog( 'standard-inputbox', {
+ ['informative-text'] = 'Macro name?',
+ text = 'Macro name',
['no-newline'] = true
- } )
+ } ):match('^(%d)\n([^\n]+)$')
- if #macro_name > 0 then
+ if ret == '1' and macro_name and #macro_name > 0 then
for _, command in ipairs(current) do
- command.type = 'function'
local msg = command[1]
- for f, t in pairs(bf) do
+ for f, t in pairs(textadept.buffer_functions) do
if t[1] == msg then command[1] = f break end
end
- if type( command[1] ) ~= 'string' then
- command.type = 'property'
- for p, t in pairs(bp) do
- if t[1] == msg or t[2] == msg then command[1] = p break end
- end
- end
end
- list[ macro_name:match('[^\n]+') ] = current
+ list[macro_name] = current
save()
textadept.statusbar_text = 'Macro saved'
textadept.events.handle('macro_saved')
@@ -109,22 +100,26 @@ function play(macro_name)
if not macro_name then
local macro_list = ''
for name in pairs(list) do macro_list = macro_list..'"'..name..'"'..' ' end
- macro_name = cocoa_dialog( 'standard-dropdown', {
+ local ret
+ ret, macro_name = cocoa_dialog( 'standard-dropdown', {
title = 'Select a Macro',
text = 'Macro name:',
items = macro_list,
+ ['string-output'] = true,
['no-newline'] = true
- } )
+ } ):match('^([^\n]+)\n([^\n]+)$')
+ if ret == 'Cancel' then return end
end
local macro = list[macro_name]
if not macro then return end
- local buffer = buffer
+ local buffer, bf = buffer, textadept.buffer_functions
for _, command in ipairs(macro) do
local cmd, wParam, lParam = unpack(command)
- if command.type == 'function' then
- buffer[cmd](buffer, wParam, lParam)
+ local _, _, p1_type, p2_type = unpack( bf[cmd] )
+ if p2_type == 7 and p1_type == 0 or p1_type == 2 then -- single string param
+ buffer[cmd](buffer, lParam)
else
- buffer[cmd] = #wParam > 0 and wParam or lParam
+ buffer[cmd](buffer, wParam, lParam)
end
end
end
@@ -149,7 +144,12 @@ function save(filename)
for name, macro in pairs(list) do
f:write(name, '\n')
for _, command in ipairs(macro) do
- f:write( ("%s\t%s\t%s\t%s\n"):format( command.type, unpack(command) ) )
+ local msg, wParam, lParam = unpack(command)
+ if type(lParam) == 'string' then
+ lParam = lParam:gsub( '[\t\n\r\f]',
+ { ['\t'] = '\\t', ['\n'] = '\\n', ['\r'] = '\\r', ['\f'] = '\\f' } )
+ end
+ f:write( ("%s\t%s\t%s\n"):format(msg, wParam, lParam) )
end
f:write('\n')
end
@@ -173,11 +173,15 @@ function load(filename)
list[name] = current_macro
name = nil
else
- local type, cmd, wParam, lParam =
- line:match('^([^\t]+)\t([^\t]+)\t?([^\t]*)\t?(.*)$')
- if type and cmd then
+ local cmd, wParam, lParam = line:match('^([^\t]+)\t([^\t]+)\t(.*)$')
+ if cmd and wParam and lParam then
+ lParam = lParam:gsub( '\\[tnrf]',
+ { ['\\t'] = '\t', ['\\n'] = '\n', ['\\r'] = '\r', ['\\f'] = '\f' } )
+ local num = wParam:match('^-?%d+$')
+ if num then wParam = tonumber(num) end
+ num = lParam:match('^-?%d+$')
+ if num then lParam = tonumber(num) end
local command = { cmd, wParam, lParam }
- command.type = type
current_macro[#current_macro + 1] = command
end
end
diff --git a/src/lua_interface.c b/src/lua_interface.c
index 3baef912..179d963c 100644
--- a/src/lua_interface.c
+++ b/src/lua_interface.c
@@ -678,8 +678,8 @@ bool l_handle_keypress(int keyval, bool shift, bool control, bool alt) {
return l_call_function(4, 1);
}
-#define l_scn_int(i, n) { lua_pushinteger(lua, i); lua_setfield(lua, -2, n); }
-#define l_scn_str(s, n) { lua_pushstring(lua, s); lua_setfield(lua, -2, n); }
+#define l_scn_int(i, n) { lua_pushinteger(lua, i); lua_setfield(lua, idx, n); }
+#define l_scn_str(s, n) { lua_pushstring(lua, s); lua_setfield(lua, idx, n); }
/**
* Handles a Scintilla notification.
@@ -688,6 +688,7 @@ bool l_handle_keypress(int keyval, bool shift, bool control, bool alt) {
void l_handle_scnnotification(SCNotification *n) {
if (!l_is_ta_table_function("events", "notification")) return;
lua_newtable(lua);
+ int idx = lua_gettop(lua);
l_scn_int(n->nmhdr.code, "code");
l_scn_int(n->position, "position");
l_scn_int(n->ch, "ch");
@@ -698,8 +699,20 @@ void l_handle_scnnotification(SCNotification *n) {
l_scn_int(n->linesAdded, "lines_added");
l_scn_int(n->message, "message");
if (n->nmhdr.code == SCN_MACRORECORD) {
- l_scn_str(reinterpret_cast<char*>(n->wParam), "wParam");
- l_scn_str(reinterpret_cast<char*>(n->lParam), "lParam");
+ l_ta_get(lua, "buffer_functions");
+ lua_pushnil(lua);
+ while (lua_next(lua, -2))
+ if (l_rawgeti_int(lua, -1, 1) == n->message) {
+ if (l_rawgeti_int(lua, -1, 3) == tSTRING) {
+ l_scn_str(reinterpret_cast<char*>(n->wParam), "wParam");
+ } else { l_scn_int(static_cast<int>(n->wParam), "wParam"); }
+ if (l_rawgeti_int(lua, -1, 4) == tSTRING) {
+ l_scn_str(reinterpret_cast<char*>(n->lParam), "lParam");
+ } else { l_scn_int(static_cast<int>(n->lParam), "lParam"); }
+ lua_pop(lua, 2); // key and value
+ break;
+ } else lua_pop(lua, 1); // value
+ lua_pop(lua, 1); // textadept.buffer_functions
} else {
l_scn_int(static_cast<int>(n->wParam), "wParam");
l_scn_int(static_cast<int>(n->lParam), "lParam");