Pretend app-flash exists already, get rid of keymap module, make textedit usable without having to worry about keymap

This commit is contained in:
20kdc 2018-03-23 15:35:43 +00:00
parent 1802ec6464
commit 36afa760c4
5 changed files with 195 additions and 286 deletions

9
code/apps/app-flash.lua Normal file
View File

@ -0,0 +1,9 @@
-- This is released into the public domain.
-- No warranty is provided, implied or otherwise.
local event = require("event")(neo)
local neoux = require("neoux")(event, neo)
-- label
-- [ ]
-- <read><write>

View File

@ -5,24 +5,16 @@
-- This was textedit (femto) from KittenOS 'ported' to NEO.
-- It also has fixes for bugs involving wide text, and runs faster due to the chars -> lines change.
local mapping, _ = unicode.keymap("ASQCVDJK")
local mappingFinal = {}
for i = 1, #mapping do
mappingFinal[i] = unicode.sub(mapping, i, i)
end
local lines = {
"Neolithic: Text Editor",
"Keymap " .. unicode.getKeymap() .. ", to correct, type",
" the alphabet in capitals.",
"Then, restart the text editor.",
"^" .. mappingFinal[1] .. ", ^" .. mappingFinal[2] .. ", ^" .. mappingFinal[3] .. ": Load, Save, New",
"^" .. mappingFinal[4] .. ", ^" .. mappingFinal[5] .. ", ^" .. mappingFinal[6] .. ": Copy, Paste, Delete Line",
"F3, F4, F1: Load, Save, New",
"F5, F6, ^←: Copy, Paste, Delete Line",
-- These two are meant to replace similar functionality in GNU Nano
-- (which I consider the best console text editor out there - Neolithic is an *imitation* and a poor one at that),
-- except fixing a UI flaw by instead making J responsible for resetting the append flag,
-- so the user can more or less arbitrarily mash together lines
"^" .. mappingFinal[7] .. ": Reset 'append' flag for Cut Lines",
"^" .. mappingFinal[8] .. ": Cut Line(s)",
"F7: Reset 'append' flag for Cut Lines",
"F8: Cut Line(s)",
"^<arrows>: Resize Win",
"'^' is Control.",
"Wide text & clipboard supported.",
@ -35,14 +27,7 @@ local lines = {
-- The way I have things setup is that you perform J then K(repeat) *instead*, which means you have to explicitly say "destroy current clipboard".
local event = require("event")(neo)
local clipboard = neo.requestAccess("x.neo.pub.clip.text")
if not clipboard then
local clipboardData = ""
clipboard = {
copy = function (text) clipboardData = text end,
paste = function () return clipboardData end
}
end
local clipsrc = neo.requireAccess("x.neo.pub.globals", "clipboard")
local cursorX = 1
local cursorY = math.ceil(#lines / 2)
@ -207,8 +192,10 @@ local function ev_key(ka, kc, down)
ctrlFlag = down
return false
end
-- Action keys
if not down then return false end
if ctrlFlag then
if not down then return false end
-- Control Action Keys
if kc == 200 then -- Up
sH = sH - 1
if sH == 0 then
@ -231,40 +218,87 @@ local function ev_key(ka, kc, down)
sW = sW + 1
sW, sH = window.setSize(sW, sH)
end
if kc == 31 then -- S
startSave()
if kc == 14 then -- ^Backspace
delLine()
return true
end
if kc == 30 then -- A
startLoad()
else
-- Non-Control Action Keys
-- Basic Action Keys
if kc == 200 or kc == 201 then -- Go up one - go up page
local moveAmount = 1
if kc == 201 then
moveAmount = math.floor(sH / 2)
end
cursorY = cursorY - moveAmount
if cursorY < 1 then
cursorY = 1
end
clampCursorX()
return true
end
if kc == 16 then -- Q
if kc == 208 or kc == 209 then -- Go down one - go down page
local moveAmount = 1
if kc == 209 then
moveAmount = math.floor(sH / 2)
end
cursorY = cursorY + moveAmount
if cursorY > #lines then
cursorY = #lines
end
clampCursorX()
return true
end
if kc == 203 then
if cursorX > 1 then
cursorX = cursorX - 1
else
if cursorY > 1 then
cursorY = cursorY - 1
cursorX = unicode.len(lines[cursorY]) + 1
else
return false
end
end
return true
end
if kc == 205 then
cursorX = cursorX + 1
if clampCursorX() then
if cursorY < #lines then
cursorY = cursorY + 1
cursorX = 1
end
end
return true
end
-- Extra Non-Control Keys
if kc == 199 then
cursorX = 1
return true
end
if kc == 207 then
cursorX = unicode.len(lines[cursorY]) + 1
return true
end
-- Major Actions
if kc == 59 then -- F1
lines = {""}
cursorX = 1
cursorY = 1
return true
end
if kc == 32 then -- D
delLine()
return true
if kc == 61 then -- F3
startLoad()
end
if kc == 46 then -- C
clipboard.copy(lines[cursorY])
if kc == 62 then -- F4
startSave()
end
if kc == 36 then -- J
appendFlag = false
if kc == 63 then -- F5
clipsrc.setSetting("clipboard", lines[cursorY])
end
if kc == 37 then -- K
if appendFlag then
local base = clipboard.paste()
clipboard.copy(base .. "\n" .. delLine())
else
clipboard.copy(delLine())
end
appendFlag = true
return true
end
if kc == 47 then -- V
local tx = clipboard.paste()
if kc == 64 then -- F6
local tx = clipsrc.getSetting("clipboard") or ""
local txi = tx:find("\n")
local nt = {}
while txi do
@ -278,85 +312,39 @@ local function ev_key(ka, kc, down)
end
return true
end
return false
end
-- action keys
if not down then
return false
end
if kc == 200 or kc == 201 then -- Go up one - go up page
local moveAmount = 1
if kc == 201 then
moveAmount = math.floor(sH / 2)
if kc == 65 then -- F7
appendFlag = false
end
cursorY = cursorY - moveAmount
if cursorY < 1 then
cursorY = 1
if kc == 66 then -- F8
if appendFlag then
local base = clipsrc.getSetting("clipboard")
clipsrc.setSetting("clipboard", base .. "\n" .. delLine())
else
clipsrc.setSetting("clipboard", delLine())
end
appendFlag = true
return true
end
clampCursorX()
return true
end
if kc == 208 or kc == 209 then -- Go down one - go down page
local moveAmount = 1
if kc == 209 then
moveAmount = math.floor(sH / 2)
end
cursorY = cursorY + moveAmount
if cursorY > #lines then
cursorY = #lines
end
clampCursorX()
return true
end
if kc == 203 then
if cursorX > 1 then
cursorX = cursorX - 1
else
if cursorY > 1 then
-- Letters
if ka ~= 0 then
if ka == 8 then
if cursorX == 1 then
if cursorY == 1 then
return false
end
local l = table.remove(lines, cursorY)
cursorY = cursorY - 1
cursorX = unicode.len(lines[cursorY]) + 1
lines[cursorY] = lines[cursorY] .. l
else
return false
local a, b = splitCur()
a = unicode.sub(a, 1, unicode.len(a) - 1)
lines[cursorY] = a.. b
cursorX = cursorX - 1
end
return true
end
return true
end
if kc == 205 then
cursorX = cursorX + 1
if clampCursorX() then
if cursorY < #lines then
cursorY = cursorY + 1
cursorX = 1
end
end
return true
end
if kc == 199 then
cursorX = 1
return true
end
if kc == 207 then
cursorX = unicode.len(lines[cursorY]) + 1
return true
end
if ka == 8 then
if cursorX == 1 then
if cursorY == 1 then
return false
end
local l = table.remove(lines, cursorY)
cursorY = cursorY - 1
cursorX = unicode.len(lines[cursorY]) + 1
lines[cursorY] = lines[cursorY] .. l
else
local a, b = splitCur()
a = unicode.sub(a, 1, unicode.len(a) - 1)
lines[cursorY] = a.. b
cursorX = cursorX - 1
end
return true
end
if ka ~= 0 then
putLetter(unicode.char(ka))
return true
end

View File

@ -6,7 +6,7 @@
local donkonitSPProvider = neo.requireAccess("r.neo.sys.manage", "creating NEO core APIs") -- Restrict to s-
-- Doesn't matter what calls this service, because there's a mutex here.
local donkonitRDProvider = neo.requireAccess("r.neo.sys.screens", "creating NEO core APIs")
local glacierDCProvider = neo.requireAccess("r.neo.sys.randr", "creating NEO core APIs")
local glacierDCProvider = neo.requireAccess("r.neo.pub.globals", "creating NEO core APIs")
local computer = neo.requireAccess("k.computer", "shutting down")
local fs = neo.requireAccess("c.filesystem", "settings I/O")
@ -14,6 +14,7 @@ local gpus = neo.requireAccess("c.gpu", "screen control")
local screens = neo.requireAccess("c.screen", "screen control")
neo.requireAccess("s.h.component_added", "HW management")
neo.requireAccess("s.h.component_removed", "HW management")
neo.requireAccess("s.h.key_down", "Keymap guesswork")
local function shutdownFin(reboot)
-- any final actions donkonit needs to take here
@ -39,6 +40,7 @@ local settings = {
-- The list of settings is here:
-- password
password = "",
["pub.clipboard"] = "",
["sys-init.shell"] = "sys-everest",
["run.sys-icecap"] = "yes",
-- scr.w/h/d.<uuid>
@ -115,7 +117,7 @@ local function sRattle(name, val)
for _, v in pairs(targs) do
v("set_setting", name, val)
end
if name:sub(1, 4) == "scr." then
if name:sub(1, 4) == "scr." or name:sub(1, 4) == "pub." then
for k, v in pairs(targsDC) do
if not targs[k] then
v("set_setting", name, val)
@ -160,6 +162,7 @@ donkonitSPProvider(function (pkg, pid, sendSig)
end
return s
end,
-- NOTE: REPLICATED IN GB
getSetting = function (name)
if type(name) ~= "string" then error("Setting name must be string") end
return settings[name]
@ -167,7 +170,7 @@ donkonitSPProvider(function (pkg, pid, sendSig)
delSetting = function (name)
if type(name) ~= "string" then error("Setting name must be string") end
local val = nil
if name == "password" then val = "" end
if name == "password" or name == "pub.clipboard" then val = "" end
settings[name] = val
sRattle(name, val)
pcall(saveSettings)
@ -181,8 +184,8 @@ donkonitSPProvider(function (pkg, pid, sendSig)
-- Monitor settings are applied on the transition to control.
sRattle(name, val)
pcall(saveSettings)
--saveSettings()
end,
--
registerForShutdownEvent = function ()
targsSD[pid] = sendSig
end,
@ -338,7 +341,27 @@ glacierDCProvider(function (pkg, pid, sendSig)
sRattle("scr.d." .. ma, d)
pcall(saveSettings)
end,
forceRescan = rescanDevs
forceRescan = rescanDevs,
-- NOTE: "pub." prefixed version of functions in sys.manage
getSetting = function (name)
if type(name) ~= "string" then error("Setting name must be string") end
return settings["pub." .. name]
end,
delSetting = function (name)
if type(name) ~= "string" then error("Setting name must be string") end
local val = nil
if name == "clipboard" then val = "" end
settings["pub." .. name] = val
sRattle("pub." .. name, val)
pcall(saveSettings)
end,
setSetting = function (name, val)
if type(name) ~= "string" then error("Setting name must be string") end
if type(val) ~= "string" then error("Setting value must be string") end
settings["pub." .. name] = val
sRattle("pub." .. name, val)
pcall(saveSettings)
end
}
end)

View File

@ -109,6 +109,20 @@ return {
"apps/app-textedit.lua"
},
},
["app-flash"] = {
desc = "KittenOS NEO EEPROM Flasher",
v = 0,
app = "app-flash",
deps = {
"neo"
},
dirs = {
"apps"
},
files = {
"apps/app-flash.lua"
},
},
["app-pass"] = {
desc = "KittenOS NEO Password Setter & Logout",
v = 0,

View File

@ -88,127 +88,6 @@ function unicode.undoSafeTextFormat(s)
return res
end
-- Yes, this is what I used the freed up SR space for.
-- Think of this as my apology for refusing translation support on NEO.
keymaps = {
-- 'synth' keymap
["unknown"] = {
},
["??-qwerty"] = {
{16, "QWERTYUIOP"},
{16, "qwertyuiop"},
{30, "ASDFGHJKL"},
{30, "asdfghjkl"},
{44, "ZXCVBNM"},
{44, "zxcvbnm"},
},
["??-qwertz"] = {
{16, "QWERTZUIOP"},
{16, "qwertzuiop"},
{30, "ASDFGHJKL"},
{30, "asdfghjkl"},
{44, "YXCVBNM"},
{44, "yxcvbnm"},
},
["??-dvorak"] = {
{19, "PYFGCRL"},
{19, "pyfgcrl"},
{30, "AOEUIDHTNS"},
{30, "aoeuidhtns"},
{45, "QJKXBMWVZ"},
{45, "qjkxbmwvz"},
},
}
for k, v in pairs(keymaps) do
for k2, v2 in ipairs(v) do
for i = 1, unicode.len(v2[2]) do
v[unicode.sub(v2[2], i, i)] = i + v2[1] - 1
end
v2[k2] = nil
end
end
currentKeymap = "unknown"
-- Not really part of this package, but...
unicode.getKeymap = function ()
return currentKeymap
end
-- raw info functions, they return nil if they don't know
-- Due to a fantastic oversight, unicode.byte or such doesn't exist in OCEmu,
-- so things are managed via "Ch" internally.
unicode.getKCByCh = function (ch, km)
return keymaps[km][ch]
end
unicode.getChByKC = function (kc, km)
for ach, akc in pairs(keymaps[km]) do
if akc == kc then
return ach
end
end
end
local function keymapDetect(ka, kc)
if ka == 0 then return end
if kc == 0 then return end
-- simple algorithm, does the job
-- emergencyFunction("KD: " .. unicode.char(signal[3]) .. " " .. signal[4])
ka = unicode.char(ka)
if keymaps["unknown"][ka] ~= kc then
keymaps["unknown"][ka] = kc
else
return
end
-- 25% of used keys must be known to pass
local bestRatio = 0.25
local bestName = "unknown"
for k, _ in pairs(keymaps) do
if k ~= "unknown" then
local count = 0
local total = 0
for kCh, kc in pairs(keymaps["unknown"]) do
if unicode.getKCByCh(kCh, k) == kc then
count = count + 1
end
total = total + 1
end
local r = count / math.max(1, total)
if r > bestRatio then
bestRatio = r
bestName = k
end
end
end
if currentKeymap ~= bestName then emergencyFunction("Switching to Keymap " .. bestName) end
currentKeymap = bestName
end
-- rtext, codes (codes can end up nil)
-- rtext is text's letters switched over
-- (for code that will still use the same keycodes,
-- but wants to display correct text)
-- codes is the keycodes mapped based on the letters
unicode.keymap = function (text)
local km = unicode.getKeymap()
local rtext = ""
local codes = {}
local notQ = false
for i = 1, unicode.len(text) do
local ch = unicode.sub(text, i, i)
local okc = unicode.getKCByCh(ch, "??-qwerty") or 0
local ch2 = unicode.getChByKC(okc, currentKeymap) or unicode.getChByKC(okc, "unknown")
if not ch2 then
ch2 = "?"
else
notQ = true
end
rtext = rtext .. ch2
codes[i] = unicode.getKCByCh(ch, currentKeymap) or unicode.getKCByCh(ch, "unknown")
end
if not notQ then
rtext = text
end
return rtext, codes
end
local function loadfile(s, e)
local h = primaryDisk.open(s)
if h then
@ -714,52 +593,48 @@ end
if not start("sys-init") then error("Could not start sys-init") end
while true do
local tmr = nil
for i = 1, 16 do
tmr = nil
local now = computer.uptime()
local breaking = false -- Used when a process dies - in this case it's assumed OC just did something drastic
local didAnything = false
local k = 1
while timers[k] do
local v = timers[k]
if v[1] <= now then
if v[2](table.unpack(v, 3)) then
breaking = true
tmr = 0.05
break
end
didAnything = true
v = nil
else
if not tmr then
tmr = v[1]
local ok, r = pcall(function()
local tmr = nil
for i = 1, 16 do
tmr = nil
local now = computer.uptime()
local breaking = false -- Used when a process dies - in this case it's assumed OC just did something drastic
local didAnything = false
local k = 1
while timers[k] do
local v = timers[k]
if v[1] <= now then
table.remove(timers, k)
if v[2](table.unpack(v, 3)) then
breaking = true
tmr = 0.05
break
end
didAnything = true
else
tmr = math.min(tmr, v[1])
if not tmr then
tmr = v[1]
else
tmr = math.min(tmr, v[1])
end
k = k + 1
end
end
if v then
k = k + 1
else
table.remove(timers, k)
end
if breaking then break end
-- If the system didn't make any progress, then we're waiting for a signal (this includes timers)
if not didAnything then break end
end
if breaking then break end
-- If the system didn't make any progress, then we're waiting for a signal (this includes timers)
if not didAnything then break end
end
now = computer.uptime() -- the above probably took a while
local dist = nil
if tmr then
dist = tmr - now
if dist < 0.05 then dist = 0.05 end
end
local signal = {computer.pullSignal(dist)}
if signal[1] == "key_down" then
keymapDetect(signal[3], signal[4])
end
idleTime = idleTime + (computer.uptime() - now)
if signal[1] then
distEvent(nil, "h." .. signal[1], select(2, table.unpack(signal)))
end
now = computer.uptime() -- the above probably took a while
local dist = nil
if tmr then
dist = tmr - now
if dist < 0.05 then dist = 0.05 end
end
local signal = {computer.pullSignal(dist)}
idleTime = idleTime + (computer.uptime() - now)
if signal[1] then
distEvent(nil, "h." .. signal[1], select(2, table.unpack(signal)))
end
end)
if not ok then emergencyFunction("K-WARN " .. tostring(r)) end
end