Skip to content
Snippets Groups Projects
Commit 20b750ba authored by dg's avatar dg
Browse files

Debug console: Cursor positioning (left/right arrows, home/end to move to beginning/end of line)

Debug console: Copy to system clipboard support, bound to Ctrl+C and matches Ctrl+V paste support
Debug console: Tab-autocompletion of table entries



git-svn-id: http://svn.net-core.org/repos/t-engine4@4826 51575b47-30f0-44d4-a5cc-537603b46e54
parent 37f46902
No related branches found
No related tags found
No related merge requests found
......@@ -26,6 +26,7 @@ module(..., package.seeall, class.inherit(engine.Dialog))
offset = 0
history = {}
line = ""
line_pos = 0
com_sel = 0
commands = {}
......@@ -57,12 +58,16 @@ function _M:init()
end
end
self.line = ""
self.line_pos = 0
self.offset = 0
self.changed = true
end,
_UP = function()
self.com_sel = util.bound(self.com_sel - 1, 1, #self.commands)
self.com_sel = util.bound(self.com_sel - 1, 0, #self.commands)
if self.commands[self.com_sel] then
if #self.line == 0 or self.line_pos == #self.line then
self.line_pos = #self.commands[self.com_sel]
end
self.line = self.commands[self.com_sel]
end
self.changed = true
......@@ -70,27 +75,160 @@ function _M:init()
_DOWN = function()
self.com_sel = util.bound(self.com_sel + 1, 1, #self.commands)
if self.commands[self.com_sel] then
if #self.line == 0 or self.line_pos == #self.line then
self.line_pos = #self.commands[self.com_sel]
end
self.line = self.commands[self.com_sel]
else
self.line = ""
self.line_pos = 0
end
self.changed = true
end,
_LEFT = function()
self.line_pos = util.bound(self.line_pos - 1, 0, #self.line)
self.changed = true
end,
_RIGHT = function()
self.line_pos = util.bound(self.line_pos + 1, 0, #self.line)
self.changed = true
end,
_HOME = function()
self.line_pos = 0
self.changed = true
end,
_END = function()
self.line_pos = #self.line
self.changed = true
end,
_ESCAPE = function()
game:unregisterDialog(self)
end,
_BACKSPACE = function()
self.line = self.line:sub(1, self.line:len() - 1) self.changed = true
self.line = self.line:sub(1, self.line_pos - 1) .. self.line:sub(self.line_pos + 1)
self.line_pos = util.bound(self.line_pos - 1, 0, #self.line)
self.changed = true
end,
__TEXTINPUT = function(c)
self.line = self.line .. c
self.line = self.line:sub(1, self.line_pos) .. c .. self.line:sub(self.line_pos + 1)
self.line_pos = util.bound(self.line_pos + 1, 0, #self.line)
self.changed = true
end,
[{"_v", "ctrl"}] = function(c)
local s = core.key.getClipboard()
if s then
self.line = self.line .. s
self.line = self.line:sub(1, self.line_pos) .. s .. self.line:sub(self.line_pos + 1)
self.line_pos = util.bound(self.line_pos + #s, 0, #self.line)
self.changed = true
end
end,
[{"_c", "ctrl"}] = function(c)
core.key.setClipboard(self.line)
end,
_TAB = function()
local find_base
find_base = function(remaining)
-- Don't try to auto-complete strings, check by counting quotation marks
local _, nsinglequote = remaining:gsub("\'", "")
local _, ndoublequote = remaining:gsub("\"", "")
if (nsinglequote % 2 ~= 0) or (ndoublequote % 2 ~= 0) then
return nil, "Cannot auto-complete strings."
end
-- Work from the back of the line to the front
local string_to_complete = remaining:match("[%d%w_%[%]%.:\'\"]+$") or ""
-- Find the trailing tail
local tail = string_to_complete:match("[%d%w_]+$") or ""
local linking_char = string_to_complete:sub(#string_to_complete - #tail, #string_to_complete - #tail)
-- Only handle numerical keys to auto-complete
if linking_char == "[" and not tonumber(tail) then
return find_base(tail)
end
-- Drop the linking character
local head = string_to_complete:sub(1, util.bound(#string_to_complete - #tail - 1, 0))
if #head > 0 then
local f, err = loadstring("return " .. head)
if err then
return nil, err
else
local res = {pcall(f)}
if res[1] and res[2] then
return res[2], tail
else
return nil, ([[%s does not exist.]]):format(head)
end
end
-- Global namespace if there is no head
else
return _G, tail
end
end
local base, to_complete = find_base(self.line)
if not base then
if to_complete then
table.insert(self.history, ([[----- %s -----]]):format(to_complete))
self.changed = true
end
return
end
local set = {}
local recurs_bases
recurs_bases = function(base)
for k, v in pairs(base) do
-- Need to handle numbers, too
if type(k) == "number" and tonumber(to_complete) then
if tostring(k):match("^" .. to_complete) then
set[tostring(k)] = true
end
elseif type(k) == "string" then
if k:match("^" .. to_complete) then
set[k] = true
end
end
end
-- Check the metatable __index
local mt = getmetatable(base)
if mt and mt.__index and type(mt.__index) == "table" then
recurs_bases(mt.__index)
end
end
recurs_bases(base)
-- Convert to a sorted array
local array = {}
for k, _ in pairs(set) do
array[#array+1] = k
end
table.sort(array, function(a, b) return a < b end)
-- If there is one possibility, complete it
if #array == 1 then
self.line = self.line:sub(1, #self.line - #to_complete) .. array[1]
self.line_pos = self.line_pos - #to_complete + #array[1]
elseif #array > 1 then
table.insert(self.history, "----- Auto-complete possibilities: -----")
for i, k in ipairs(array) do
table.insert(self.history, k)
end
-- Find the longest common substring and complete it
local substring = array[1]:sub(#to_complete+1)
for i=2,#array do
local min_len = math.min(#array[i], #substring)
for j=#to_complete,min_len do
if substring:sub(j, j) ~= array[i]:sub(j, j) then
substring = substring:sub(#to_complete+1, util.bound(j-1, 0))
break
end
end
if #substring == 0 then break end
end
-- Complete to the longest common substring
if #substring > 0 then
self.line = self.line .. substring
self.line_pos = self.line_pos + #substring
end
else
table.insert(self.history, "----- No auto-complete possibilities. -----")
end
self.changed = true
end,
}
-- Scroll message log
self:mouseZones{
......@@ -107,7 +245,7 @@ function _M:drawDialog(s, w, h)
local i, dh = #self.history - self.offset, self.ih - buffer - self.font:lineSkip()
-- Start at the bottom and work up
-- Draw the current command
s:drawStringBlended(self.font, self.line, 0, dh, 255, 255, 255)
s:drawStringBlended(self.font, self.line:sub(1, self.line_pos) .. "|" .. self.line:sub(self.line_pos+1), 0, dh, 255, 255, 255)
dh = dh - self.font:lineSkip()
-- Now draw the history with any offset
while dh > buffer do
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment