Skip to content

Instantly share code, notes, and snippets.

@stevedonovan
Created March 28, 2011 07:04
Show Gist options
  • Save stevedonovan/890099 to your computer and use it in GitHub Desktop.
Save stevedonovan/890099 to your computer and use it in GitHub Desktop.
An interactive Lua prompt for the Textadept editor
-- makes interactive prompt dodgy.
-- (In an ideal world, should be able to switch this off only for
-- the message buffer)
_m.textadept.editing.AUTOPAIR = false
-- useful function which can safely handle argument lists containing nil;
-- the resulting table has n set to the real length.
local function pack (...)
local args = {...}
args.n = select('#',...)
return args
end
local function eval_lua(code)
local status,res,val,f,err,rcnt
code,rcnt = code:gsub('^%s*=','return ')
f,err = loadstring(code,'TMP')
if f then
res = pack(pcall(f)) -- capture all the results
local n = res.n
if not res[1] then
err = res[2]
elseif n > 1 and not (n==2 and res[2]==nil) then
-- all results except the status; ignore functions returning nil
print(unpack(res,2,n))
end
end
if err then -- either run-time or compile error
err = 'error: '..tostring(err):gsub('^%[string "TMP"%]:1:','')
print(err) -- 2DO: format as distinctive style
end
end
-- the message buffer does not have a filename field; we grab the last line
-- after \n and evaluate as Lua code.
local function handle_char (ch)
if ch == 10 and not buffer.filename then
local line_pos = buffer.current_pos
local lineno = buffer:line_from_position(line_pos)-1
local line = buffer:get_line(lineno)
eval_lua(line:gsub('^> ','')) -- strip prompt
gui.write '> '
end
end
function lua()
gui.write 'Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio\n> '
print = gui.print
events.connect('char_added',handle_char)
end
-- finding the message buffer: factored out
local function find_buffer_of_type(buffer_type)
-- Try to find a message buffer to print to. Otherwise create one.
local message_buffer, message_buffer_index
local message_view, message_view_index
for i, buffer in ipairs(_BUFFERS) do
if buffer._type == buffer_type then
message_buffer, message_buffer_index = buffer, i
for j, view in ipairs(_VIEWS) do
if view.doc_pointer == message_buffer.doc_pointer then
message_view, message_view_index = view, j
break
end
end
break
end
end
if not message_view then
local _, message_view = view:split(false) -- horizontal split
if not message_buffer then
message_buffer = new_buffer()
message_buffer._type = buffer_type
events.emit('file_opened')
else
message_view:goto_buffer(message_buffer_index, true)
end
else
gui.goto_view(message_view_index, true)
end
end
-- append text to a buffer of given type, and position the caret at the end.
function gui._write(buffer_type,text)
local function safe_write(text)
if buffer._type ~= buffer_type then
find_buffer_of_type(buffer_type)
end
buffer:append_text(text)
buffer:goto_pos(buffer.length)
end
pcall(safe_write, text) -- prevent endless loops on error
end
-- gui._print is here redefined, to use _write.
-- It also uses pack() to ensure that it can handle arg lists with nils
-- and other values which are not numbers or strings (table.concat
-- will choke on these)
function gui._print(buffer_type, ...)
local args = pack(...)
for i = 1,args.n do
args[i] = tostring(args[i])
end
gui._write(buffer_type,table.concat(args, '\t'))
gui._write(buffer_type,'\n')
buffer:set_save_point()
end
function gui.write(text)
gui._write("[Message Buffer]",text)
buffer:set_save_point()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment