diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/textadept/init.lua | 1 | ||||
-rw-r--r-- | modules/textadept/run.lua | 191 |
2 files changed, 192 insertions, 0 deletions
diff --git a/modules/textadept/init.lua b/modules/textadept/init.lua index 54ef25aa..4a4b279a 100644 --- a/modules/textadept/init.lua +++ b/modules/textadept/init.lua @@ -10,3 +10,4 @@ require 'textadept.editing' require 'textadept.lsnippets' require 'textadept.macros' require 'textadept.mlines' +require 'textadept.run' diff --git a/modules/textadept/run.lua b/modules/textadept/run.lua new file mode 100644 index 00000000..822ecb03 --- /dev/null +++ b/modules/textadept/run.lua @@ -0,0 +1,191 @@ +-- Copyright 2007-2009 Mitchell mitchell<att>caladbolg.net. See LICENSE. + +local textadept = _G.textadept + +--- +-- Module for running/executing source files. +module('_m.textadept.run', package.seeall) + +--- [Local function] Prints a command to Textadept. +local function print_command(cmd, output) + textadept.print('> '..cmd..'\n'..output) + buffer:goto_pos(buffer.length) +end + +--- +-- Passes the current file to a specified compiler to run with the given flags +-- and prints the output to Textadept. +-- @param compiler The system's compiler for the file. +-- @param flags A string of flags to pass to the interpreter. +-- @param args Table of arguments key keys as follows: +-- * filename_noext_with_flag The value of this flag passed to the compiler +-- is the filename without its extension. +function compiler(compiler, cflags, args) + if type(cflags) ~= 'string' then cflags = '' end + if not args then args = {} end + local file = buffer.filename + if args.filename_noext_with_flag then + local filename_noext = file:match('^(.+)%.') + local flag = args.filename_noext_with_flag + cflags = string.format('%s %s"%s"', cflags, flag, filename_noext) + end + local command = string.format('%s %s "%s" 2>&1', compiler, cflags, file) + local p = io.popen(command) + local out = p:read('*all') + p:close() + print_command(command, out) +end + +--- +-- Passes the current file to a specified interpreter to run with the given +-- flags and prints the output to Textadept. +-- @param interpreter The system's interpreter for the file. +-- @param flags A string of flags to pass to the interpreter. +-- @param args Table of arguments with keys as follows: +-- * noext Do not include the filename's extension when passing to the +-- interpreter. +-- * nopath Do not include the full filepath, only the file's name. +-- * nopath_path_with_flag Same as nopath, but use the path as the value of +-- a flag passed to the interpreter. +function interpreter(interpreter, flags, args) + if type(flags) ~= 'string' then flags = '' end + if not args then args = {} end + local file = buffer.filename + if args.noext then file = file:match('^(.+)%.') end + if args.nopath then file = file:match('[^/\\]+$') end + if args.nopath_path_with_flag then + local path = file:match('^.+/') + local flag = args.nopath_path_with_flag + flags = string.format('%s %s"%s"', flags, flag, path) + file = file:match('[^/\\]+$') + end + local command = string.format('%s %s "%s" 2>&1', interpreter, flags, file) + local p = io.popen(command) + local out = p:read('*all') + p:close() + print_command(command, out) +end + +-- TODO: makefile +-- TODO: etc. + +--- +-- [Local table] File extensions and their associated 'compile' actions. +-- Each key is a file extension whose value is a table with the compile function +-- and parameters given as an ordered list. +-- @class table +-- @name compile_for_ext +local compile_for_ext = { + c = { compiler, 'gcc', '-pedantic -Os', + { filename_noext_with_flag = '-o ' } }, + cpp = { compiler, 'g++', '-pedantic -Os', + { filename_noext_with_flag = '-o ' } }, + java = { compiler, 'javac' }, +} + +--- +-- Compiles the file as specified by its extension in the compile_for_ext table. +-- @see compile_for_ext +function compile() + local ext = buffer.filename:match('[^.]+$') + local action = compile_for_ext[ext] + if not action then return end + local f, args = action[1], { unpack(action) } + table.remove(args, 1) -- function + f(unpack(args)) +end + +--- +-- [Local table] File extensions and their associated 'go' actions. +-- Each key is a file extension whose value is a table with the run function +-- and parameters given as an ordered list. +-- @class table +-- @name go_for_ext +local go_for_ext = { + c = { interpreter, '', '', { noext = true } }, + cpp = { interpreter, '', '', { noext = true } }, + java = { interpreter, 'java', '', + { noext = true, nopath_path_with_flag = '-cp ' } }, + lua = { interpreter, 'lua' }, + pl = { interpreter, 'perl' }, + php = { interpreter, 'php', '-f' }, + py = { interpreter, 'python' }, + rb = { interpreter, 'ruby' }, +} + +--- +-- Runs/executes the file as specified by its extension in the go_for_ext table. +-- @see go_for_ext +function go() + local ext = buffer.filename:match('[^.]+$') + local action = go_for_ext[ext] + if not action then return end + local f, args = action[1], { unpack(action) } + table.remove(args, 1) -- function + f(unpack(args)) +end + +--- +-- [Local table] A table of error string details. +-- Each entry is a table with the following fields: +-- pattern: the Lua pattern that matches a specific error string. +-- filename: the index of the Lua capture that contains the filename the error +-- occured in. +-- line: the index of the Lua capture that contains the line number the error +-- occured on. +-- message: [Optional] the index of the Lua capture that contains the error's +-- message. A call tip will be displayed if a message was captured. +-- When an error message is double-clicked, the user is taken to the point of +-- error. +-- @class table +-- @name error_details +local error_details = { + -- c, c++, and java errors and warnings have the same format as ruby ones + lua = { + pattern = '^lua: (.-):(%d+): (.+)$', + filename = 1, line = 2, message = 3 + }, + perl = { + pattern = '^(.+) at (.-) line (%d+)', + message = 1, filename = 2, line = 3 + }, + php_error = { + pattern = '^Parse error: (.+) in (.-) on line (%d+)', + message = 1, filename = 2, line = 3 + }, + php_warning = { + pattern = '^Warning: (.+) in (.-) on line (%d+)', + message = 1, filename = 2, line = 3 + }, + python = { + pattern = '^%s*File "([^"]+)", line (%d+)', + filename = 1, line = 2 + }, + ruby = { + pattern = '^(.-):(%d+): (.+)$', + filename = 1, line = 2, message = 3 + }, +} + +--- +-- When the user double-clicks an error message, go to the line in the file +-- the error occured at and display a calltip with the error message. +-- @param pos The position of the caret. +-- @param line_num The line double-clicked. +-- @see error_details +function goto_error(pos, line_num) + if buffer.shows_errors then + line = buffer:get_line(line_num) + for _, error_detail in pairs(error_details) do + local captures = { line:match(error_detail.pattern) } + if #captures > 0 then + textadept.io.open(captures[error_detail.filename]) + _m.textadept.editing.goto_line(captures[error_detail.line]) + local msg = captures[error_detail.message] + if msg then buffer:call_tip_show(buffer.current_pos, msg) end + break + end + end + end +end +textadept.events.add_handler('double_click', goto_error) |