better text entry

This commit is contained in:
kepler155c@gmail.com 2019-03-29 09:56:56 -04:00
parent 30bad69417
commit c9ef150605
7 changed files with 405 additions and 296 deletions

View File

@ -8,246 +8,379 @@ function Entry:init(args)
self.pos = 0
self.scroll = 0
self.value = ''
self.width = args.width
self.limit = 1024
self.width = args.width or 256
self.limit = args.limit or 1024
self.mark = { }
self.offset = args.offset or 1
end
function Entry:reset()
self.pos = 0
self.scroll = 0
self.value = ''
self.mark = { }
end
local function nextWord(line, cx)
local result = { line:find("(%w+)", cx) }
if #result > 1 and result[2] > cx then
return result[2] + 1
elseif #result > 0 and result[1] == cx then
result = { line:find("(%w+)", result[2] + 1) }
if #result > 0 then
return result[1]
end
end
function Entry:nextWord()
return select(2, self.value:find("[%s%p]?%w[%s%p]", self.pos + 1)) or #self.value
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
function Entry:prevWord()
local x = #self.value - (self.pos - 1)
local _, n = self.value:reverse():find("[%s%p]?%w[%s%p]", x)
return n and #self.value - n + 1 or 0
end
function Entry:updateScroll()
local ps = self.scroll
if self.pos > #self.value then
self.pos = #self.value
self.scroll = 0 -- ??
end
if self.pos - self.scroll > self.width then
self.scroll = self.pos - (self.width)
self.scroll = self.pos - self.width
elseif self.pos < self.scroll then
self.scroll = self.pos
end
if ps ~= self.scroll then
self.textChanged = true
end
end
local function moveLeft(entry)
if entry.pos > 0 then
entry.pos = math.max(entry.pos - 1, 0)
function Entry:copyText(cx, ex)
return self.value:sub(cx + 1, ex)
end
function Entry:insertText(x, text)
if #self.value + #text > self.limit then
text = text:sub(1, self.limit-#self.value)
end
self.value = self.value:sub(1, x) .. text .. self.value:sub(x + 1)
self.pos = self.pos + #text
end
function Entry:deleteText(sx, ex)
local front = self.value:sub(1, sx)
local back = self.value:sub(ex + 1, #self.value)
self.value = front .. back
self.pos = sx
end
function Entry:moveLeft()
if self.pos > 0 then
self.pos = self.pos - 1
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)
function Entry:moveRight()
if self.pos < #self.value then
self.pos = self.pos + 1
return true
end
end
local function moveStart(entry)
if entry.pos ~= 0 then
entry.pos = 0
function Entry:moveHome()
if self.pos ~= 0 then
self.pos = 0
return true
end
end
local function moveEnd(entry)
if entry.pos ~= #tostring(entry.value) then
entry.pos = #tostring(entry.value)
function Entry:moveEnd()
if self.pos ~= #self.value then
self.pos = #self.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
function Entry:moveTo(ie)
self.pos = math.max(0, math.min(ie.x + self.scroll - self.offset, #self.value))
end
function Entry:backspace()
if self.mark.active then
self:delete()
elseif self:moveLeft() then
self:delete()
end
end
function Entry:moveWordRight()
if self.pos < #self.value then
self.pos = self:nextWord(self.value, self.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
function Entry:moveWordLeft()
if self.pos > 0 then
self.pos = self:prevWord(self.value, self.pos - 1) or 0
return true
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
function Entry:delete()
if self.mark.active then
self:deleteText(self.mark.x, self.mark.ex)
elseif self.pos < #self.value then
self:deleteText(self.pos, self.pos + 1)
end
end
function Entry:cutFromStart()
if self.pos > 0 then
local text = self:copyText(1, self.pos)
self:deleteText(1, self.pos)
os.queueEvent('clipboard_copy', text)
end
end
function Entry:cutToEnd()
if self.pos < #self.value then
local text = self:copyText(self.pos, #self.value)
self:deleteText(self.pos, #self.value)
os.queueEvent('clipboard_copy', text)
end
end
function Entry:cutNextWord()
if self.pos < #self.value then
local ex = self:nextWord(self.value, self.pos)
local text = self:copyText(self.pos, ex)
self:deleteText(self.pos, ex)
os.queueEvent('clipboard_copy', text)
end
end
function Entry:cutPrevWord()
if self.pos > 0 then
local sx = self:prevWord(self.value, self.pos)
local text = self:copyText(sx, self.pos)
self:deleteText(sx, self.pos)
os.queueEvent('clipboard_copy', text)
end
end
function Entry:insertChar(ie)
if self.mark.active then
self:delete()
end
self:insertText(self.pos, ie.ch)
end
function Entry:copy()
if #self.value > 0 then
self.mark.continue = true
if self.mark.active then
self:copyMarked()
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
os.queueEvent('clipboard_copy', self.value)
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
function Entry:cut()
if self.mark.active then
self:copyMarked()
self:delete()
end
end
function Entry:copyMarked()
local text = self:copyText(self.mark.x, self.mark.ex)
os.queueEvent('clipboard_copy', text)
end
function Entry:paste(ie)
if #ie.text > 0 then
if self.mark.active then
self:delete()
end
self:insertText(self.pos, ie.text)
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
function Entry:clearLine()
if #self.value > 0 then
self:reset()
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)
function Entry:markBegin()
if not self.mark.active then
self.mark.active = true
self.mark.anchor = { x = self.pos }
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
function Entry:markFinish()
if self.pos == self.mark.anchor.x then
self.mark.active = false
else
self.mark.x = math.min(self.mark.anchor.x, self.pos)
self.mark.ex = math.max(self.mark.anchor.x, self.pos)
end
self.textChanged = true
self.mark.continue = self.mark.active
end
function Entry:unmark()
if self.mark.active then
self.textChanged = true
self.mark.active = false
end
end
function Entry:markAnchor(ie)
self:unmark()
self:moveTo(ie)
self:markBegin()
self:markFinish()
end
function Entry:markLeft()
self:markBegin()
if self:moveLeft() then
self:markFinish()
end
end
function Entry:markRight()
self:markBegin()
if self:moveRight() then
self:markFinish()
end
end
function Entry:markWord(ie)
local index = 1
self:moveTo(ie)
while true do
local s, e = self.value:find('%w+', index)
if not s or s - 1 > self.pos then
break
end
if self.pos >= s - 1 and self.pos < e then
self.pos = s - 1
self:markBegin()
self.pos = e
self:markFinish()
self:moveTo(ie)
break
end
index = e + 1
end
end
function Entry:markNextWord()
self:markBegin()
if self:moveWordRight() then
self:markFinish()
end
end
function Entry:markPrevWord()
self:markBegin()
if self:moveWordLeft() then
self:markFinish()
end
end
function Entry:markAll()
if #self.value > 0 then
self.mark.anchor = { x = 1 }
self.mark.active = true
self.mark.continue = true
self.mark.x = 0
self.mark.ex = #self.value
self.textChanged = true
end
end
function Entry:markHome()
self:markBegin()
if self:moveHome() then
self:markFinish()
end
end
function Entry:markEnd()
self:markBegin()
if self:moveEnd() then
self:markFinish()
end
end
function Entry:markTo(ie)
self:markBegin()
self:moveTo(ie)
self:markFinish()
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,
[ 'left' ] = Entry.moveLeft,
[ 'control-b' ] = Entry.moveLeft,
[ 'right' ] = Entry.moveRight,
[ 'control-f' ] = Entry.moveRight,
[ 'home' ] = Entry.moveHome,
[ 'end' ] = Entry.moveEnd,
[ 'control-e' ] = Entry.moveEnd,
[ 'mouse_click' ] = Entry.moveTo,
[ 'backspace' ] = Entry.backspace,
[ 'control-right' ] = Entry.moveWordRight,
[ 'alt-f' ] = Entry.moveWordRight,
[ 'control-left' ] = Entry.moveWordLeft,
[ 'alt-b' ] = Entry.moveWordLeft,
[ 'mouse_doubleclick' ] = Entry.markWord,
[ 'delete' ] = Entry.delete,
[ 'control-u' ] = Entry.cutFromStart,
[ 'control-k' ] = Entry.cutToEnd,
--[ 'control-d' ] = Entry.cutNextWord,
[ 'control-w' ] = Entry.cutPrevWord,
[ 'char' ] = Entry.insertChar,
[ 'control-c' ] = Entry.copy,
[ 'control-x' ] = Entry.cut,
[ 'paste' ] = Entry.paste,
[ 'control-y' ] = Entry.paste,
[ 'mouse_rightclick' ] = Entry.clearLine,
[ 'shift-left' ] = Entry.markLeft,
[ 'shift-right' ] = Entry.markRight,
[ 'mouse_down' ] = Entry.markAnchor,
[ 'mouse_drag' ] = Entry.markTo,
[ 'shift-mouse_click' ] = Entry.markTo,
[ 'control-a' ] = Entry.markAll,
[ 'control-shift-right' ] = Entry.markNextWord,
[ 'control-shift-left' ] = Entry.markPrevWord,
[ 'shift-end' ] = Entry.markEnd,
[ 'shift-home' ] = Entry.markHome,
}
function Entry:process(ie)
local action = mappings[ie.code]
local updated
self.textChanged = false
if action then
updated = action(self, ie)
local pos = self.pos
local line = self.value
local wasMarking = self.mark.continue
self.mark.continue = false
action(self, ie)
self.textChanged = self.textChanged or self.value ~= line
self.posChanged = pos ~= self.pos
self:updateScroll()
if not self.mark.continue and wasMarking then
self:unmark()
end
return true
end
self:updateScroll()
return updated
end
return Entry

View File

@ -119,6 +119,12 @@ function input:translate(event, code, p1, p2)
local buttons = { 'mouse_click', 'mouse_rightclick' }
self.mch = buttons[code]
self.mfired = nil
return {
code = input:toCode('mouse_down', 255),
button = code,
x = p1,
y = p2,
}
elseif event == 'mouse_drag' then
self.mfired = true

View File

@ -45,7 +45,7 @@ function Manager:init()
if ie and currentPage then
local target = currentPage.focused or currentPage
self:inputEvent(target,
{ type = 'key', key = ie.code == 'char' and ie.ch or ie.code, element = target })
{ type = 'key', key = ie.code == 'char' and ie.ch or ie.code, element = target, ie = ie })
currentPage:sync()
end
end
@ -97,7 +97,7 @@ function Manager:init()
end,
mouse_click = function(_, button, x, y)
Input:translate('mouse_click', button, x, y)
local ie = Input:translate('mouse_click', button, x, y)
local currentPage = self:getActivePage()
if currentPage then
@ -107,6 +107,7 @@ function Manager:init()
currentPage:setFocus(event.element)
currentPage:sync()
end
self:click(currentPage, ie.code, button, x, y)
end
end
end,
@ -136,14 +137,15 @@ function Manager:init()
if ie and currentPage then
local event = currentPage:pointToChild(x, y)
event.type = ie.code
event.ie = ie
self:inputEvent(event.element, event)
currentPage:sync()
end
end,
paste = function(_, text)
Input:translate('paste')
self:emitEvent({ type = 'paste', text = text })
local ie = Input:translate('paste', text)
self:emitEvent({ type = 'paste', text = text, ie = ie })
self:getActivePage():sync()
end,
}
@ -259,6 +261,7 @@ function Manager:click(target, code, button, x, y)
clickEvent.button = button
clickEvent.type = code
clickEvent.key = code
clickEvent.ie = { code = code, x = x, y = y }
if clickEvent.element.focus then
target:setFocus(clickEvent.element)

View File

@ -1,9 +1,9 @@
local class = require('class')
local entry = require('entry')
local UI = require('ui')
local Util = require('util')
local colors = _G.colors
local os = _G.os
local _rep = string.rep
UI.TextEntry = class(UI.Window)
@ -18,41 +18,31 @@ UI.TextEntry.defaults = {
backgroundFocusColor = colors.black, --lightGray,
height = 1,
limit = 6,
pos = 0,
accelerators = {
[ 'control-c' ] = 'copy',
}
}
function UI.TextEntry:postInit()
self.value = tostring(self.value)
self.entry = entry({ limit = self.limit, offset = 2 })
end
function UI.TextEntry:layout()
UI.Window.layout(self)
self.entry.width = self.width - 2
end
function UI.TextEntry:setValue(value)
self.value = value
self.entry:unmark()
self.entry.value = value
self.entry:updateScroll()
end
function UI.TextEntry:setPosition(pos)
self.pos = pos
end
function UI.TextEntry:updateScroll()
if not self.scroll then
self.scroll = 0
end
if not self.pos then
self.pos = #tostring(self.value)
self.scroll = 0
elseif self.pos > #tostring(self.value) then
self.pos = #tostring(self.value)
self.scroll = 0
end
if self.pos - self.scroll > self.width - 2 then
self.scroll = self.pos - (self.width - 2)
elseif self.pos < self.scroll then
self.scroll = self.pos
end
self.entry.pos = pos
self.entry.value = self.value
self.entry:updateScroll()
end
function UI.TextEntry:draw()
@ -62,11 +52,10 @@ function UI.TextEntry:draw()
bg = self.backgroundFocusColor
end
self:updateScroll()
local text = tostring(self.value)
if #text > 0 then
if self.scroll and self.scroll > 0 then
text = text:sub(1 + self.scroll)
if self.entry.scroll > 0 then
text = text:sub(1 + self.entry.scroll)
end
if self.mask then
text = _rep('*', #text)
@ -77,21 +66,32 @@ function UI.TextEntry:draw()
end
self:write(1, 1, ' ' .. Util.widthify(text, self.width - 2) .. ' ', bg, tc)
if self.entry.mark.active then
local tx = math.max(self.entry.mark.x - self.entry.scroll, 0)
local tex = self.entry.mark.ex - self.entry.scroll
if tex > self.width - 2 then -- unsure about this
tex = self.width - 2 - tx
end
if tx ~= tex then
self:write(tx + 2, 1, text:sub(tx + 1, tex), colors.gray, tc)
end
end
if self.focused then
self:setCursorPos(self.pos-self.scroll+2, 1)
self:setCursorPos(self.entry.pos - self.entry.scroll + 2, 1)
end
end
function UI.TextEntry:reset()
self.pos = 0
self.value = ''
self.entry:reset()
self:draw()
self:updateCursor()
end
function UI.TextEntry:updateCursor()
self:updateScroll()
self:setCursorPos(self.pos-self.scroll+2, 1)
self:setCursorPos(self.entry.pos - self.entry.scroll + 2, 1)
end
function UI.TextEntry:focus()
@ -103,86 +103,20 @@ function UI.TextEntry:focus()
end
end
--[[
A few lines below from theoriginalbit
http://www.computercraft.info/forums2/index.php?/topic/16070-read-and-limit-length-of-the-input-field/
--]]
function UI.TextEntry:eventHandler(event)
if event.type == 'key' then
local ch = event.key
if ch == 'left' then
if self.pos > 0 then
self.pos = math.max(self.pos-1, 0)
self:draw()
end
elseif ch == 'right' then
local input = tostring(self.value)
if self.pos < #input then
self.pos = math.min(self.pos+1, #input)
self:draw()
end
elseif ch == 'home' then
self.pos = 0
local text = self.value
self.entry.value = text
if event.ie and self.entry:process(event.ie) then
if self.entry.textChanged then
self.value = self.entry.value
self:draw()
elseif ch == 'end' then
self.pos = #tostring(self.value)
self:draw()
elseif ch == '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
self:draw()
if text ~= self.value then
self:emit({ type = 'text_change', text = self.value, element = self })
end
elseif ch == '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:draw()
self:emit({ type = 'text_change', text = self.value, element = self })
end
elseif #ch == 1 then
local input = tostring(self.value)
if #input < self.limit then
self.value = input:sub(1, self.pos) .. ch .. input:sub(self.pos+1)
self.pos = self.pos + 1
self:draw()
self:emit({ type = 'text_change', text = self.value, element = self })
end
else
return false
end
return true
elseif event.type == 'copy' then
os.queueEvent('clipboard_copy', self.value)
elseif event.type == 'paste' then
local input = tostring(self.value)
local text = event.text
if #input + #text > self.limit then
text = text:sub(1, self.limit-#input)
end
self.value = input:sub(1, self.pos) .. text .. input:sub(self.pos+1)
self.pos = self.pos + #text
self:draw()
self:updateCursor()
self:emit({ type = 'text_change', text = self.value, element = self })
return true
elseif event.type == 'mouse_click' then
if self.focused and event.x > 1 then
self.pos = event.x + self.scroll - 2
elseif self.entry.posChanged then
self:updateCursor()
return true
end
elseif event.type == 'mouse_rightclick' then
local input = tostring(self.value)
if #input > 0 then
self:reset()
self:emit({ type = 'text_change', text = self.value, element = self })
end
return true
end
return false

View File

@ -34,7 +34,7 @@ local page = UI.Page {
prompt = UI.TextEntry {
y = 2,
shadowText = 'enter command',
limit = 256,
limit = 1024,
accelerators = {
enter = 'command_enter',
up = 'history_back',
@ -72,12 +72,11 @@ page.output = page.tabs[2].output
function page:setPrompt(value, focus)
self.prompt:setValue(value)
self.prompt.scroll = 0
self.prompt:setPosition(#value)
self.prompt:updateScroll()
if value:sub(-1) == ')' then
self.prompt:setPosition(#value - 1)
else
self.prompt:setPosition(#value)
end
self.prompt:draw()
@ -155,8 +154,8 @@ function page:eventHandler(event)
elseif event.type == 'autocomplete' then
local sz = #self.prompt.value
local pos = self.prompt.pos
self:setPrompt(autocomplete(sandboxEnv, self.prompt.value, self.prompt.pos))
local pos = self.prompt.entry.pos
self:setPrompt(autocomplete(sandboxEnv, self.prompt.value, self.prompt.entry.pos))
self.prompt:setPosition(pos + #self.prompt.value - sz)
self.prompt:updateCursor()

View File

@ -370,7 +370,9 @@ local term = _G.term
local textutils = _G.textutils
local oldTerm
local terminal = term.current()
local terminal = term.current()
local _rep = string.rep
local _sub = string.sub
if not terminal.scrollUp then
terminal = Terminal.window(term.current())
@ -402,11 +404,19 @@ if not _colors.backgroundColor then
_colors.fileColor = colors.white
end
local palette = { }
for n = 1, 16 do
palette[2 ^ (n - 1)] = _sub("0123456789abcdef", n, n)
end
if not term.isColor() then
_colors = { }
for k, v in pairs(config.color) do
_colors[k] = Terminal.colorToGrayscale(v)
end
for n = 1, 16 do
palette[2 ^ (n - 1)] = _sub("088888878877787f", n, n)
end
end
local function autocompleteArgument(program, words)
@ -556,12 +566,17 @@ end
local function shellRead(history)
local lastLen = 0
local entry = Entry({
width = term.getSize() - 3
width = term.getSize() - 3,
offset = 3,
})
history:reset()
term.setCursorBlink(true)
local function updateCursor()
term.setCursorPos(3 + entry.pos - entry.scroll, select(2, term.getCursorPos()))
end
local function redraw()
if terminal.scrollBottom then
terminal.scrollBottom()
@ -571,9 +586,18 @@ local function shellRead(history)
local filler = #entry.value < lastLen
and string.rep(' ', lastLen - #entry.value)
or ''
local str = string.sub(entry.value, entry.scroll + 1)
term.write(string.sub(str, 1, entry.width) .. filler)
term.setCursorPos(3 + entry.pos - entry.scroll, cy)
local str = string.sub(entry.value, entry.scroll + 1, entry.width + entry.scroll) .. filler
local fg = _rep(palette[_colors.commandTextColor], #str)
local bg = _rep(palette[_colors.backgroundColor], #str)
if entry.mark.active then
local sx = entry.mark.x - entry.scroll + 1
local ex = entry.mark.ex - entry.scroll + 1
bg = string.rep('f', sx - 1) ..
string.rep('7', ex - sx) ..
string.rep('f', #str - ex + 1)
end
term.blit(str, fg, bg)
updateCursor()
lastLen = #entry.value
end
@ -597,13 +621,13 @@ local function shellRead(history)
elseif ie.code == 'up' or ie.code == 'control-p' or
ie.code == 'down' or ie.code == 'control-n' then
entry:reset()
if ie.code == 'up' or ie.code == 'control-p' then
entry.value = history:back() or ''
else
entry.value = history:forward() or ''
end
entry.pos = string.len(entry.value)
entry.scroll = 0
entry.pos = #entry.value
entry:updateScroll()
redraw()
@ -613,17 +637,24 @@ local function shellRead(history)
if cline then
entry.value = cline
entry.pos = #entry.value
entry:unmark()
entry:updateScroll()
redraw()
end
end
elseif entry:process(ie) then
redraw()
else
entry:process(ie)
if entry.textChanged then
redraw()
elseif entry.posChanged then
updateCursor()
end
end
elseif event == "term_resize" then
entry.width = term.getSize() - 3
entry:updateScroll()
redraw()
end
end

View File

@ -57,6 +57,9 @@ end
function tab:eventHandler(event)
if event.type == 'choice_change' then
self.custom.enabled = event.value == 'custom'
if self.custom.enabled then
self.custom.value = config.launcher
end
self:draw()
elseif event.type == 'update' then