autorun overhaul + shell input readline commands + launcher option + shell colors
This commit is contained in:
@@ -30,6 +30,19 @@ local function nextWord(line, cx)
|
||||
end
|
||||
end
|
||||
|
||||
local function prevWord(line, cx)
|
||||
local nOffset = 1
|
||||
while nOffset <= #line do
|
||||
local nNext = line:find("%W%w", nOffset)
|
||||
if nNext and nNext < cx then
|
||||
nOffset = nNext + 1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
return nOffset - 1 < cx and nOffset - 1
|
||||
end
|
||||
|
||||
function Entry:updateScroll()
|
||||
if self.pos - self.scroll > self.width then
|
||||
self.scroll = self.pos - (self.width)
|
||||
@@ -38,109 +51,198 @@ function Entry:updateScroll()
|
||||
end
|
||||
end
|
||||
|
||||
local function moveLeft(entry)
|
||||
if entry.pos > 0 then
|
||||
entry.pos = math.max(entry.pos - 1, 0)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function moveRight(entry)
|
||||
local input = tostring(entry.value)
|
||||
if entry.pos < #input then
|
||||
entry.pos = math.min(entry.pos + 1, #input)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function moveStart(entry)
|
||||
if entry.pos ~= 0 then
|
||||
entry.pos = 0
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function moveEnd(entry)
|
||||
if entry.pos ~= #tostring(entry.value) then
|
||||
entry.pos = #tostring(entry.value)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function backspace(entry)
|
||||
if entry.pos > 0 then
|
||||
local input = tostring(entry.value)
|
||||
entry.value = input:sub(1, entry.pos - 1) .. input:sub(entry.pos + 1)
|
||||
entry.pos = entry.pos - 1
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function moveWordRight(entry)
|
||||
local nx = nextWord(entry.value, entry.pos + 1)
|
||||
if nx then
|
||||
entry.pos = math.min(nx - 1, #entry.value)
|
||||
elseif entry.pos < #entry.value then
|
||||
entry.pos = #entry.value
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function moveWordLeft(entry)
|
||||
if entry.pos ~= 0 then
|
||||
local lx = 1
|
||||
while true do
|
||||
local nx = nextWord(entry.value, lx)
|
||||
if not nx or nx >= entry.pos then
|
||||
break
|
||||
end
|
||||
lx = nx
|
||||
end
|
||||
if not lx then
|
||||
entry.pos = 0
|
||||
else
|
||||
entry.pos = lx - 1
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function delete(entry)
|
||||
local input = tostring(entry.value)
|
||||
if entry.pos < #input then
|
||||
entry.value = input:sub(1, entry.pos) .. input:sub(entry.pos + 2)
|
||||
entry.update = true
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- credit for cut functions to: https://github.com/SquidDev-CC/mbs/blob/master/lib/readline.lua
|
||||
local function cutFromStart(entry)
|
||||
if entry.pos > 0 then
|
||||
local input = tostring(entry.value)
|
||||
os.queueEvent('clipboard_copy', input:sub(1, entry.pos))
|
||||
entry.value = input:sub(entry.pos + 1)
|
||||
entry.pos = 0
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function cutToEnd(entry)
|
||||
local input = tostring(entry.value)
|
||||
if entry.pos < #input then
|
||||
os.queueEvent('clipboard_copy', input:sub(entry.pos + 1))
|
||||
entry.value = input:sub(1, entry.pos)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function cutNextWord(entry)
|
||||
local input = tostring(entry.value)
|
||||
if entry.pos < #input then
|
||||
local ex = nextWord(entry.value, entry.pos)
|
||||
if ex then
|
||||
os.queueEvent('clipboard_copy', input:sub(entry.pos + 1, ex))
|
||||
entry.value = input:sub(1, entry.pos) .. input:sub(ex + 1)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function cutPrevWord(entry)
|
||||
if entry.pos > 0 then
|
||||
local sx = prevWord(entry.value, entry.pos)
|
||||
if sx then
|
||||
local input = tostring(entry.value)
|
||||
os.queueEvent('clipboard_copy', input:sub(sx + 1, entry.pos))
|
||||
entry.value = input:sub(1, sx) .. input:sub(entry.pos + 1)
|
||||
entry.pos = sx
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function insertChar(entry, ie)
|
||||
local input = tostring(entry.value)
|
||||
if #input < entry.limit then
|
||||
entry.value = input:sub(1, entry.pos) .. ie.ch .. input:sub(entry.pos + 1)
|
||||
entry.pos = entry.pos + 1
|
||||
entry.update = true
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function copy(entry)
|
||||
os.queueEvent('clipboard_copy', entry.value)
|
||||
end
|
||||
|
||||
local function paste(entry, ie)
|
||||
local input = tostring(entry.value)
|
||||
if #input + #ie.text > entry.limit then
|
||||
ie.text = ie.text:sub(1, entry.limit-#input)
|
||||
end
|
||||
entry.value = input:sub(1, entry.pos) .. ie.text .. input:sub(entry.pos + 1)
|
||||
entry.pos = entry.pos + #ie.text
|
||||
return true
|
||||
end
|
||||
|
||||
local function moveCursor(entry, ie)
|
||||
-- need starting x passed in instead of hardcoding 3
|
||||
entry.pos = math.max(0, math.min(ie.x - 3 + entry.scroll, #entry.value))
|
||||
return true
|
||||
end
|
||||
|
||||
local function clearLine(entry)
|
||||
local input = tostring(entry.value)
|
||||
if #input > 0 then
|
||||
entry:reset()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local mappings = {
|
||||
[ 'left' ] = moveLeft,
|
||||
[ 'control-b' ] = moveLeft,
|
||||
[ 'right' ] = moveRight,
|
||||
[ 'control-f' ] = moveRight,
|
||||
[ 'home' ] = moveStart,
|
||||
[ 'control-a' ] = moveStart,
|
||||
[ 'end' ] = moveEnd,
|
||||
[ 'control-e' ] = moveEnd,
|
||||
[ 'backspace' ] = backspace,
|
||||
[ 'control-right' ] = moveWordRight,
|
||||
[ 'alt-f' ] = moveWordRight,
|
||||
[ 'control-left' ] = moveWordLeft,
|
||||
[ 'alt-b' ] = moveWordLeft,
|
||||
[ 'delete' ] = delete,
|
||||
[ 'control-u' ] = cutFromStart,
|
||||
[ 'control-k' ] = cutToEnd,
|
||||
[ 'control-d' ] = cutNextWord,
|
||||
[ 'control-w' ] = cutPrevWord,
|
||||
[ 'char' ] = insertChar,
|
||||
[ 'copy' ] = copy,
|
||||
[ 'paste' ] = paste,
|
||||
[ 'control-y' ] = paste,
|
||||
[ 'mouse_click' ] = moveCursor,
|
||||
[ 'mouse_rightclick' ] = clearLine,
|
||||
}
|
||||
|
||||
function Entry:process(ie)
|
||||
local updated = false
|
||||
local action = mappings[ie.code]
|
||||
local updated
|
||||
|
||||
if ie.code == 'left' then
|
||||
if self.pos > 0 then
|
||||
self.pos = math.max(self.pos - 1, 0)
|
||||
updated = true
|
||||
end
|
||||
|
||||
elseif ie.code == 'right' then
|
||||
local input = tostring(self.value)
|
||||
if self.pos < #input then
|
||||
self.pos = math.min(self.pos + 1, #input)
|
||||
updated = true
|
||||
end
|
||||
|
||||
elseif ie.code == 'home' then
|
||||
if self.pos ~= 0 then
|
||||
self.pos = 0
|
||||
updated = true
|
||||
end
|
||||
|
||||
elseif ie.code == 'end' then
|
||||
if self.pos ~= #tostring(self.value) then
|
||||
self.pos = #tostring(self.value)
|
||||
updated = true
|
||||
end
|
||||
|
||||
elseif ie.code == 'backspace' then
|
||||
if self.pos > 0 then
|
||||
local input = tostring(self.value)
|
||||
self.value = input:sub(1, self.pos - 1) .. input:sub(self.pos + 1)
|
||||
self.pos = self.pos - 1
|
||||
updated = true
|
||||
end
|
||||
|
||||
elseif ie.code == 'control-right' then
|
||||
local nx = nextWord(self.value, self.pos + 1)
|
||||
if nx then
|
||||
self.pos = math.min(nx - 1, #self.value)
|
||||
elseif self.pos < #self.value then
|
||||
self.pos = #self.value
|
||||
end
|
||||
updated = true
|
||||
|
||||
elseif ie.code == 'control-left' then
|
||||
if self.pos ~= 0 then
|
||||
local lx = 1
|
||||
while true do
|
||||
local nx = nextWord(self.value, lx)
|
||||
if not nx or nx >= self.pos then
|
||||
break
|
||||
end
|
||||
lx = nx
|
||||
end
|
||||
if not lx then
|
||||
self.pos = 0
|
||||
else
|
||||
self.pos = lx - 1
|
||||
end
|
||||
updated = true
|
||||
end
|
||||
|
||||
elseif ie.code == 'delete' then
|
||||
local input = tostring(self.value)
|
||||
if self.pos < #input then
|
||||
self.value = input:sub(1, self.pos) .. input:sub(self.pos + 2)
|
||||
self.update = true
|
||||
updated = true
|
||||
end
|
||||
|
||||
elseif ie.code == 'char' then
|
||||
local input = tostring(self.value)
|
||||
if #input < self.limit then
|
||||
self.value = input:sub(1, self.pos) .. ie.ch .. input:sub(self.pos + 1)
|
||||
self.pos = self.pos + 1
|
||||
self.update = true
|
||||
updated = true
|
||||
end
|
||||
|
||||
elseif ie.code == 'copy' then
|
||||
os.queueEvent('clipboard_copy', self.value)
|
||||
|
||||
elseif ie.code == 'paste' then
|
||||
local input = tostring(self.value)
|
||||
if #input + #ie.text > self.limit then
|
||||
ie.text = ie.text:sub(1, self.limit-#input)
|
||||
end
|
||||
self.value = input:sub(1, self.pos) .. ie.text .. input:sub(self.pos + 1)
|
||||
self.pos = self.pos + #ie.text
|
||||
updated = true
|
||||
|
||||
elseif ie.code == 'mouse_click' then
|
||||
-- need starting x passed in instead of hardcoding 3
|
||||
self.pos = math.max(0, math.min(ie.x - 3 + self.scroll, #self.value))
|
||||
updated = true
|
||||
|
||||
elseif ie.code == 'mouse_rightclick' then
|
||||
local input = tostring(self.value)
|
||||
if #input > 0 then
|
||||
self:reset()
|
||||
updated = true
|
||||
end
|
||||
if action then
|
||||
updated = action(self, ie)
|
||||
end
|
||||
|
||||
self:updateScroll()
|
||||
|
||||
@@ -6,6 +6,25 @@ local _gsub = string.gsub
|
||||
|
||||
local Terminal = { }
|
||||
|
||||
local mapColorToGray = {
|
||||
[ colors.white ] = colors.white,
|
||||
[ colors.orange ] = colors.lightGray,
|
||||
[ colors.magenta ] = colors.lightGray,
|
||||
[ colors.lightBlue ] = colors.lightGray,
|
||||
[ colors.yellow ] = colors.lightGray,
|
||||
[ colors.lime ] = colors.lightGray,
|
||||
[ colors.pink ] = colors.lightGray,
|
||||
[ colors.gray ] = colors.gray,
|
||||
[ colors.lightGray ] = colors.lightGray,
|
||||
[ colors.cyan ] = colors.lightGray,
|
||||
[ colors.purple ] = colors.gray,
|
||||
[ colors.blue ] = colors.gray,
|
||||
[ colors.brown ] = colors.gray,
|
||||
[ colors.green ] = colors.lightGray,
|
||||
[ colors.red ] = colors.gray,
|
||||
[ colors.black ] = colors.black,
|
||||
}
|
||||
|
||||
-- Replacement for window api with scrolling and buffering
|
||||
function Terminal.window(parent, sx, sy, w, h, isVisible)
|
||||
isVisible = isVisible ~= false
|
||||
@@ -243,32 +262,17 @@ function Terminal.getContents(win, parent)
|
||||
return lines
|
||||
end
|
||||
|
||||
function Terminal.toGrayscale(ct)
|
||||
local scolors = {
|
||||
[ colors.white ] = colors.white,
|
||||
[ colors.orange ] = colors.lightGray,
|
||||
[ colors.magenta ] = colors.lightGray,
|
||||
[ colors.lightBlue ] = colors.lightGray,
|
||||
[ colors.yellow ] = colors.lightGray,
|
||||
[ colors.lime ] = colors.lightGray,
|
||||
[ colors.pink ] = colors.lightGray,
|
||||
[ colors.gray ] = colors.gray,
|
||||
[ colors.lightGray ] = colors.lightGray,
|
||||
[ colors.cyan ] = colors.lightGray,
|
||||
[ colors.purple ] = colors.gray,
|
||||
[ colors.blue ] = colors.gray,
|
||||
[ colors.brown ] = colors.gray,
|
||||
[ colors.green ] = colors.lightGray,
|
||||
[ colors.red ] = colors.gray,
|
||||
[ colors.black ] = colors.black,
|
||||
}
|
||||
function Terminal.colorToGrayscale(c)
|
||||
return mapColorToGray[c]
|
||||
end
|
||||
|
||||
function Terminal.toGrayscale(ct)
|
||||
local methods = { 'setBackgroundColor', 'setBackgroundColour',
|
||||
'setTextColor', 'setTextColour' }
|
||||
for _,v in pairs(methods) do
|
||||
local fn = ct[v]
|
||||
ct[v] = function(c)
|
||||
fn(scolors[c])
|
||||
fn(mapColorToGray[c])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user