diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/textadept/init.lua | 1 | ||||
-rw-r--r-- | modules/textadept/key_commands.lua | 11 | ||||
-rw-r--r-- | modules/textadept/macros.lua | 176 |
3 files changed, 185 insertions, 3 deletions
diff --git a/modules/textadept/init.lua b/modules/textadept/init.lua index ee985df3..ea744c75 100644 --- a/modules/textadept/init.lua +++ b/modules/textadept/init.lua @@ -7,6 +7,7 @@ module('_m.textadept', package.seeall) require 'textadept.editing' require 'textadept.keys' +require 'textadept.macros' require 'textadept.mlines' require 'textadept.snippets' require 'textadept.key_commands' -- last diff --git a/modules/textadept/key_commands.lua b/modules/textadept/key_commands.lua index 55f038e4..c7239c7c 100644 --- a/modules/textadept/key_commands.lua +++ b/modules/textadept/key_commands.lua @@ -6,11 +6,11 @@ module('_m.textadept.key_commands', package.seeall) --[[ C: G Q - A: A C G J K L M O Q R W X Z + A: A C G J K L O Q R W X Z CS: C D G J L Q R S T U W SA: A C D E G H I J K L M O Q R S T W X Z - CA: A C G H J K L M O Q R S T V W X Y Z - CSA: C D G H J K L M O Q R S T U W X Z + CA: A C G H J K L O Q R S T V W X Y Z + CSA: C D G H J K L O Q R S T U W X Z ]]-- --- @@ -126,6 +126,10 @@ keys.am = { c = { m_mlines.clear }, } +local m_macro = _m.textadept.macros +keys.cam = { m_macro.toggle_record } +keys.csam = { m_macro.play } + keys.cr = { textadept.io.open } keys.co = { 'save', b } keys.cso = { 'save_as', b } @@ -161,6 +165,7 @@ keys.ct.ss = { 'split', v } -- vertical keys.ct.n = { textadept.new_buffer } keys.ct.b = { pm_activate, 'buffers' } keys.ct.c = { pm_activate, 'ctags' } +keys.ct.m = { pm_activate, 'macros' } keys.ct.x = { function() view:unsplit() return true end } keys.ct.sx = { function() while view:unsplit() do end end } keys.ct.f = { function() diff --git a/modules/textadept/macros.lua b/modules/textadept/macros.lua new file mode 100644 index 00000000..0ba966c6 --- /dev/null +++ b/modules/textadept/macros.lua @@ -0,0 +1,176 @@ +-- Copyright 2007 Mitchell mitchell<att>caladbolg.net. See LICENSE. + +--- +-- Support for recording, saving, and playing macros for the textadept module. +module('_m.textadept.macros', package.seeall) + +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. +-- @class table +-- @name list +list = {} + +--- +-- [Local table] The currently recording macro. +-- It is a numerically indexed table of commands with each command having the +-- same structure as described in list. +-- @class table +-- @name current +-- @see list +local current = {} + +local recording = false + +--- +-- [Local function] Handles a Scintilla macro notification. +-- If a macro is being recorded, add this command to 'current'. +-- @param msg The Scintilla message ID. +local function macro_notification(msg, wParam, lParam) + if recording then + current[#current + 1] = { msg, wParam or '', lParam or '' } + textadept.statusbar_text = 'Macro recording' + end +end +textadept.handlers.add_function_to_handler('macro_record', macro_notification) + +--- +-- Starts recording a macro. +function start_recording() + if recording then return end + buffer:start_record() + current = {} + recording = true + textadept.statusbar_text = 'Macro recording' +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. +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 = + io.popen('zenity --entry --text "Macro name:"'):read('*all'):sub(1, -2) + if #macro_name > 0 then + for _, command in ipairs(current) do + command.type = 'function' + local msg = command[1] + for f, t in pairs(bf) 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] = current + save() + textadept.statusbar_text = 'Macro saved' + textadept.handlers.handle('macro_saved') + else + textadept.statusbar_text = 'Macro not saved' + end +end + +--- +-- Toggles between recording a macro and not recording one. +function toggle_record() + (not recording and start_recording or stop_recording)() +end + +--- +-- Plays a specified macro. +-- @param macro_name The name of the macro to play. If none specified, the user +-- is prompted to choose one from a list of available macros. +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 = io.popen('zenity --list --text "Select a Macro" '.. + '--column Name '..macro_list):read('*all'):sub(1, -2) + end + local macro = list[macro_name] + if not macro then return end + local buffer = buffer + for _, command in ipairs(macro) do + local cmd, wParam, lParam = unpack(command) + if command.type == 'function' then + buffer[cmd](buffer, wParam, lParam) + else + buffer[cmd] = #wParam > 0 and wParam or lParam + end + end +end + +--- +-- Deletes a specified macro. +-- @param macro_name The name of the macro to delete. +function delete(macro_name) + if list[macro_name] then + list[macro_name] = nil + save() + textadept.handlers.handle('macro_deleted') + end +end + +--- +-- Saves the current list of macros to a specified file. +-- @param filename The absolute path to the file to save the macros to. +function save(filename) + if not filename then filename = MACRO_FILE end + local f = assert( io.open(filename, 'w') ) + 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) ) ) + end + f:write('\n') + end + f:close() +end + +--- +-- Loads macros from a specified file. +-- @param filename The absolute path to the file to load the macros from. +function load(filename) + if not filename then filename = MACRO_FILE end + local f = io.open(filename) + if not f then return end + local name, current_macro + for line in f:lines() do + if not name then -- new macro + name = line + current_macro = {} + else + if line == '' then -- finished; save current macro + 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 command = { cmd, wParam, lParam } + command.type = type + current_macro[#current_macro + 1] = command + end + end + end + end +end + +load() -- load saved macros on startup |