SHOW:
|
|
- or go back to the newest paste.
| 1 | - | local component = require("component") |
| 1 | + | local component = require("component")
|
| 2 | - | local event = require("event") |
| 2 | + | local event = require("event")
|
| 3 | - | local fs = require("filesystem") |
| 3 | + | local fs = require("filesystem")
|
| 4 | - | local keyboard = require("keyboard") |
| 4 | + | local keyboard = require("keyboard")
|
| 5 | - | local shell = require("shell") |
| 5 | + | local shell = require("shell")
|
| 6 | - | local term = require("term") |
| 6 | + | local term = require("term")
|
| 7 | - | local text = require("text") |
| 7 | + | local text = require("text")
|
| 8 | - | local unicode = require("unicode") |
| 8 | + | local unicode = require("unicode")
|
| 9 | - | |
| 9 | + | |
| 10 | - | if not term.isAvailable() then |
| 10 | + | if not term.isAvailable() then |
| 11 | - | return |
| 11 | + | return |
| 12 | - | end |
| 12 | + | end |
| 13 | - | |
| 13 | + | |
| 14 | - | local args, options = shell.parse(...) |
| 14 | + | local args, options = shell.parse(...) |
| 15 | - | if #args == 0 then |
| 15 | + | if #args == 0 then |
| 16 | - | io.write("Usage: edit <filename>") |
| 16 | + | io.write("Usage: edit <filename>")
|
| 17 | - | return |
| 17 | + | return |
| 18 | - | end |
| 18 | + | end |
| 19 | - | |
| 19 | + | |
| 20 | - | local filename = shell.resolve(args[1]) |
| 20 | + | local filename = shell.resolve(args[1]) |
| 21 | - | |
| 21 | + | |
| 22 | - | local readonly = options.r or fs.get(filename) == nil or fs.get(filename).isReadOnly() |
| 22 | + | local readonly = options.r or fs.get(filename) == nil or fs.get(filename).isReadOnly() |
| 23 | - | |
| 23 | + | |
| 24 | - | if not fs.exists(filename) then |
| 24 | + | if not fs.exists(filename) then |
| 25 | - | if fs.isDirectory(filename) then |
| 25 | + | if fs.isDirectory(filename) then |
| 26 | - | io.stderr:write("file is a directory") |
| 26 | + | io.stderr:write("file is a directory")
|
| 27 | - | return |
| 27 | + | return |
| 28 | - | elseif readonly then |
| 28 | + | elseif readonly then |
| 29 | - | io.stderr:write("file system is read only") |
| 29 | + | io.stderr:write("file system is read only")
|
| 30 | - | return |
| 30 | + | return |
| 31 | - | end |
| 31 | + | end |
| 32 | - | end |
| 32 | + | end |
| 33 | - | |
| 33 | + | |
| 34 | - | local function loadConfig() |
| 34 | + | local function loadConfig() |
| 35 | - | -- Try to load user settings. |
| 35 | + | -- Try to load user settings. |
| 36 | - | local env = {} |
| 36 | + | local env = {}
|
| 37 | - | local config = loadfile("/etc/edit.cfg", nil, env) |
| 37 | + | local config = loadfile("/etc/edit.cfg", nil, env)
|
| 38 | - | if config then |
| 38 | + | if config then |
| 39 | - | pcall(config) |
| 39 | + | pcall(config) |
| 40 | - | end |
| 40 | + | end |
| 41 | - | -- Fill in defaults. |
| 41 | + | -- Fill in defaults. |
| 42 | - | env.keybinds = env.keybinds or { |
| 42 | + | env.keybinds = env.keybinds or {
|
| 43 | - | left = {{"left"}}, |
| 43 | + | left = {{"left"}},
|
| 44 | - | right = {{"right"}}, |
| 44 | + | right = {{"right"}},
|
| 45 | - | up = {{"up"}}, |
| 45 | + | up = {{"up"}},
|
| 46 | - | down = {{"down"}}, |
| 46 | + | down = {{"down"}},
|
| 47 | - | home = {{"home"}}, |
| 47 | + | home = {{"home"}},
|
| 48 | - | eol = {{"end"}}, |
| 48 | + | eol = {{"end"}},
|
| 49 | - | pageUp = {{"pageUp"}}, |
| 49 | + | pageUp = {{"pageUp"}},
|
| 50 | - | pageDown = {{"pageDown"}}, |
| 50 | + | pageDown = {{"pageDown"}},
|
| 51 | - | |
| 51 | + | |
| 52 | - | backspace = {{"back"}}, |
| 52 | + | backspace = {{"back"}},
|
| 53 | - | delete = {{"delete"}}, |
| 53 | + | delete = {{"delete"}},
|
| 54 | - | deleteLine = {{"control", "delete"}, {"shift", "delete"}}, |
| 54 | + | deleteLine = {{"control", "delete"}, {"shift", "delete"}},
|
| 55 | - | newline = {{"enter"}}, |
| 55 | + | newline = {{"enter"}},
|
| 56 | - | |
| 56 | + | |
| 57 | - | save = {{"control", "s"}}, |
| 57 | + | save = {{"control", "s"}},
|
| 58 | - | close = {{"control", "w"}}, |
| 58 | + | close = {{"control", "w"}},
|
| 59 | - | find = {{"control", "f"}}, |
| 59 | + | find = {{"control", "f"}},
|
| 60 | - | findnext = {{"control", "g"}, {"control", "n"}, {"f3"}} |
| 60 | + | findnext = {{"control", "g"}, {"control", "n"}, {"f3"}}
|
| 61 | - | } |
| 61 | + | } |
| 62 | - | -- Generate config file if it didn't exist. |
| 62 | + | -- Generate config file if it didn't exist. |
| 63 | - | if not config then |
| 63 | + | if not config then |
| 64 | - | local root = fs.get("/") |
| 64 | + | local root = fs.get("/")
|
| 65 | - | if root and not root.isReadOnly() then |
| 65 | + | if root and not root.isReadOnly() then |
| 66 | - | fs.makeDirectory("/etc") |
| 66 | + | fs.makeDirectory("/etc")
|
| 67 | - | local f = io.open("/etc/edit.cfg", "w") |
| 67 | + | local f = io.open("/etc/edit.cfg", "w")
|
| 68 | - | if f then |
| 68 | + | if f then |
| 69 | - | local serialization = require("serialization") |
| 69 | + | local serialization = require("serialization")
|
| 70 | - | for k, v in pairs(env) do |
| 70 | + | for k, v in pairs(env) do |
| 71 | - | f:write(k.."="..tostring(serialization.serialize(v, math.huge)).."\n") |
| 71 | + | f:write(k.."="..tostring(serialization.serialize(v, math.huge)).."\n") |
| 72 | - | end |
| 72 | + | end |
| 73 | - | f:close() |
| 73 | + | f:close() |
| 74 | - | end |
| 74 | + | end |
| 75 | - | end |
| 75 | + | end |
| 76 | - | end |
| 76 | + | end |
| 77 | - | return env |
| 77 | + | return env |
| 78 | - | end |
| 78 | + | end |
| 79 | - | |
| 79 | + | |
| 80 | - | term.clear() |
| 80 | + | term.clear() |
| 81 | - | term.setCursorBlink(true) |
| 81 | + | term.setCursorBlink(true) |
| 82 | - | |
| 82 | + | |
| 83 | - | local running = true |
| 83 | + | local running = true |
| 84 | - | local buffer = {} |
| 84 | + | local buffer = {}
|
| 85 | - | local scrollX, scrollY = 0, 0 |
| 85 | + | local scrollX, scrollY = 0, 0 |
| 86 | - | local config = loadConfig() |
| 86 | + | local config = loadConfig() |
| 87 | - | |
| 87 | + | |
| 88 | - | local getKeyBindHandler -- forward declaration for refind() |
| 88 | + | local getKeyBindHandler -- forward declaration for refind() |
| 89 | - | |
| 89 | + | |
| 90 | - | local function helpStatusText() |
| 90 | + | local function helpStatusText() |
| 91 | - | local function prettifyKeybind(label, command) |
| 91 | + | local function prettifyKeybind(label, command) |
| 92 | - | local keybind = type(config.keybinds) == "table" and config.keybinds[command] |
| 92 | + | local keybind = type(config.keybinds) == "table" and config.keybinds[command] |
| 93 | - | if type(keybind) ~= "table" or type(keybind[1]) ~= "table" then return "" end |
| 93 | + | if type(keybind) ~= "table" or type(keybind[1]) ~= "table" then return "" end |
| 94 | - | local alt, control, shift, key |
| 94 | + | local alt, control, shift, key |
| 95 | - | for _, value in ipairs(keybind[1]) do |
| 95 | + | for _, value in ipairs(keybind[1]) do |
| 96 | - | if value == "alt" then alt = true |
| 96 | + | if value == "alt" then alt = true |
| 97 | - | elseif value == "control" then control = true |
| 97 | + | elseif value == "control" then control = true |
| 98 | - | elseif value == "shift" then shift = true |
| 98 | + | elseif value == "shift" then shift = true |
| 99 | - | else key = value end |
| 99 | + | else key = value end |
| 100 | - | end |
| 100 | + | end |
| 101 | - | if not key then return "" end |
| 101 | + | if not key then return "" end |
| 102 | - | return label .. ": [" .. |
| 102 | + | return label .. ": [" .. |
| 103 | - | (control and "Ctrl+" or "") .. |
| 103 | + | (control and "Ctrl+" or "") .. |
| 104 | - | (alt and "Alt+" or "") .. |
| 104 | + | (alt and "Alt+" or "") .. |
| 105 | - | (shift and "Shift+" or "") .. |
| 105 | + | (shift and "Shift+" or "") .. |
| 106 | - | unicode.upper(key) .. |
| 106 | + | unicode.upper(key) .. |
| 107 | - | "] " |
| 107 | + | "] " |
| 108 | - | end |
| 108 | + | end |
| 109 | - | return prettifyKeybind("Save", "save") .. |
| 109 | + | return prettifyKeybind("Save", "save") ..
|
| 110 | - | prettifyKeybind("Close", "close") .. |
| 110 | + | prettifyKeybind("Close", "close") ..
|
| 111 | - | prettifyKeybind("Find", "find") |
| 111 | + | prettifyKeybind("Find", "find")
|
| 112 | - | end |
| 112 | + | end |
| 113 | - | |
| 113 | + | |
| 114 | - | ------------------------------------------------------------------------------- |
| 114 | + | ------------------------------------------------------------------------------- |
| 115 | - | |
| 115 | + | |
| 116 | - | local function setStatus(value) |
| 116 | + | local function setStatus(value) |
| 117 | - | local w, h = component.gpu.getResolution() |
| 117 | + | local w, h = component.gpu.getResolution() |
| 118 | - | component.gpu.set(1, h, text.padRight(unicode.sub(value, 1, w - 10), w - 10)) |
| 118 | + | component.gpu.set(1, h, text.padRight(unicode.sub(value, 1, w - 10), w - 10)) |
| 119 | - | end |
| 119 | + | end |
| 120 | - | |
| 120 | + | |
| 121 | - | local function getSize() |
| 121 | + | local function getSize() |
| 122 | - | local w, h = component.gpu.getResolution() |
| 122 | + | local w, h = component.gpu.getResolution() |
| 123 | - | return w, h - 1 |
| 123 | + | return w, h - 1 |
| 124 | - | end |
| 124 | + | end |
| 125 | - | |
| 125 | + | |
| 126 | - | local function getCursor() |
| 126 | + | local function getCursor() |
| 127 | - | local cx, cy = term.getCursor() |
| 127 | + | local cx, cy = term.getCursor() |
| 128 | - | return cx + scrollX, cy + scrollY |
| 128 | + | return cx + scrollX, cy + scrollY |
| 129 | - | end |
| 129 | + | end |
| 130 | - | |
| 130 | + | |
| 131 | - | local function line() |
| 131 | + | local function line() |
| 132 | - | local cbx, cby = getCursor() |
| 132 | + | local cbx, cby = getCursor() |
| 133 | - | return buffer[cby] |
| 133 | + | return buffer[cby] |
| 134 | - | end |
| 134 | + | end |
| 135 | - | |
| 135 | + | |
| 136 | - | local function setCursor(nbx, nby) |
| 136 | + | local function setCursor(nbx, nby) |
| 137 | - | local w, h = getSize() |
| 137 | + | local w, h = getSize() |
| 138 | - | nby = math.max(1, math.min(#buffer, nby)) |
| 138 | + | nby = math.max(1, math.min(#buffer, nby)) |
| 139 | - | |
| 139 | + | |
| 140 | - | local ncy = nby - scrollY |
| 140 | + | local ncy = nby - scrollY |
| 141 | - | if ncy > h then |
| 141 | + | if ncy > h then |
| 142 | - | term.setCursorBlink(false) |
| 142 | + | term.setCursorBlink(false) |
| 143 | - | local sy = nby - h |
| 143 | + | local sy = nby - h |
| 144 | - | local dy = math.abs(scrollY - sy) |
| 144 | + | local dy = math.abs(scrollY - sy) |
| 145 | - | scrollY = sy |
| 145 | + | scrollY = sy |
| 146 | - | component.gpu.copy(1, 1 + dy, w, h - dy, 0, -dy) |
| 146 | + | component.gpu.copy(1, 1 + dy, w, h - dy, 0, -dy) |
| 147 | - | for by = nby - (dy - 1), nby do |
| 147 | + | for by = nby - (dy - 1), nby do |
| 148 | - | local str = text.padRight(unicode.sub(buffer[by], 1 + scrollX), w) |
| 148 | + | local str = text.padRight(unicode.sub(buffer[by], 1 + scrollX), w) |
| 149 | - | component.gpu.set(1, by - scrollY, str) |
| 149 | + | component.gpu.set(1, by - scrollY, str) |
| 150 | - | end |
| 150 | + | end |
| 151 | - | elseif ncy < 1 then |
| 151 | + | elseif ncy < 1 then |
| 152 | - | term.setCursorBlink(false) |
| 152 | + | term.setCursorBlink(false) |
| 153 | - | local sy = nby - 1 |
| 153 | + | local sy = nby - 1 |
| 154 | - | local dy = math.abs(scrollY - sy) |
| 154 | + | local dy = math.abs(scrollY - sy) |
| 155 | - | scrollY = sy |
| 155 | + | scrollY = sy |
| 156 | - | component.gpu.copy(1, 1, w, h - dy, 0, dy) |
| 156 | + | component.gpu.copy(1, 1, w, h - dy, 0, dy) |
| 157 | - | for by = nby, nby + (dy - 1) do |
| 157 | + | for by = nby, nby + (dy - 1) do |
| 158 | - | local str = text.padRight(unicode.sub(buffer[by], 1 + scrollX), w) |
| 158 | + | local str = text.padRight(unicode.sub(buffer[by], 1 + scrollX), w) |
| 159 | - | component.gpu.set(1, by - scrollY, str) |
| 159 | + | component.gpu.set(1, by - scrollY, str) |
| 160 | - | end |
| 160 | + | end |
| 161 | - | end |
| 161 | + | end |
| 162 | - | term.setCursor(term.getCursor(), nby - scrollY) |
| 162 | + | term.setCursor(term.getCursor(), nby - scrollY) |
| 163 | - | |
| 163 | + | |
| 164 | - | nbx = math.max(1, math.min(unicode.len(line()) + 1, nbx)) |
| 164 | + | nbx = math.max(1, math.min(unicode.len(line()) + 1, nbx)) |
| 165 | - | local ncx = nbx - scrollX |
| 165 | + | local ncx = nbx - scrollX |
| 166 | - | if ncx > w then |
| 166 | + | if ncx > w then |
| 167 | - | term.setCursorBlink(false) |
| 167 | + | term.setCursorBlink(false) |
| 168 | - | local sx = nbx - w |
| 168 | + | local sx = nbx - w |
| 169 | - | local dx = math.abs(scrollX - sx) |
| 169 | + | local dx = math.abs(scrollX - sx) |
| 170 | - | scrollX = sx |
| 170 | + | scrollX = sx |
| 171 | - | component.gpu.copy(1 + dx, 1, w - dx, h, -dx, 0) |
| 171 | + | component.gpu.copy(1 + dx, 1, w - dx, h, -dx, 0) |
| 172 | - | for by = 1 + scrollY, math.min(h + scrollY, #buffer) do |
| 172 | + | for by = 1 + scrollY, math.min(h + scrollY, #buffer) do |
| 173 | - | local str = unicode.sub(buffer[by], nbx - (dx - 1), nbx) |
| 173 | + | local str = unicode.sub(buffer[by], nbx - (dx - 1), nbx) |
| 174 | - | str = text.padRight(str, dx) |
| 174 | + | str = text.padRight(str, dx) |
| 175 | - | component.gpu.set(1 + (w - dx), by - scrollY, str) |
| 175 | + | component.gpu.set(1 + (w - dx), by - scrollY, str) |
| 176 | - | end |
| 176 | + | end |
| 177 | - | elseif ncx < 1 then |
| 177 | + | elseif ncx < 1 then |
| 178 | - | term.setCursorBlink(false) |
| 178 | + | term.setCursorBlink(false) |
| 179 | - | local sx = nbx - 1 |
| 179 | + | local sx = nbx - 1 |
| 180 | - | local dx = math.abs(scrollX - sx) |
| 180 | + | local dx = math.abs(scrollX - sx) |
| 181 | - | scrollX = sx |
| 181 | + | scrollX = sx |
| 182 | - | component.gpu.copy(1, 1, w - dx, h, dx, 0) |
| 182 | + | component.gpu.copy(1, 1, w - dx, h, dx, 0) |
| 183 | - | for by = 1 + scrollY, math.min(h + scrollY, #buffer) do |
| 183 | + | for by = 1 + scrollY, math.min(h + scrollY, #buffer) do |
| 184 | - | local str = unicode.sub(buffer[by], nbx, nbx + dx) |
| 184 | + | local str = unicode.sub(buffer[by], nbx, nbx + dx) |
| 185 | - | --str = text.padRight(str, dx) |
| 185 | + | --str = text.padRight(str, dx) |
| 186 | - | component.gpu.set(1, by - scrollY, str) |
| 186 | + | component.gpu.set(1, by - scrollY, str) |
| 187 | - | end |
| 187 | + | end |
| 188 | - | end |
| 188 | + | end |
| 189 | - | term.setCursor(nbx - scrollX, nby - scrollY) |
| 189 | + | term.setCursor(nbx - scrollX, nby - scrollY) |
| 190 | - | |
| 190 | + | |
| 191 | - | component.gpu.set(w - 9, h + 1, text.padLeft(string.format("%d,%d", nby, nbx), 10)) |
| 191 | + | component.gpu.set(w - 9, h + 1, text.padLeft(string.format("%d,%d", nby, nbx), 10))
|
| 192 | - | end |
| 192 | + | end |
| 193 | - | |
| 193 | + | |
| 194 | - | local function highlight(bx, by, length, enabled) |
| 194 | + | local function highlight(bx, by, length, enabled) |
| 195 | - | local w, h = getSize() |
| 195 | + | local w, h = getSize() |
| 196 | - | local cx, cy = bx - scrollX, by - scrollY |
| 196 | + | local cx, cy = bx - scrollX, by - scrollY |
| 197 | - | cx = math.max(1, math.min(w, cx)) |
| 197 | + | cx = math.max(1, math.min(w, cx)) |
| 198 | - | cy = math.max(1, math.min(h, cy)) |
| 198 | + | cy = math.max(1, math.min(h, cy)) |
| 199 | - | length = math.max(1, math.min(w - cx, length)) |
| 199 | + | length = math.max(1, math.min(w - cx, length)) |
| 200 | - | |
| 200 | + | |
| 201 | - | local fg, fgp = component.gpu.getForeground() |
| 201 | + | local fg, fgp = component.gpu.getForeground() |
| 202 | - | local bg, bgp = component.gpu.getBackground() |
| 202 | + | local bg, bgp = component.gpu.getBackground() |
| 203 | - | if enabled then |
| 203 | + | if enabled then |
| 204 | - | component.gpu.setForeground(bg, bgp) |
| 204 | + | component.gpu.setForeground(bg, bgp) |
| 205 | - | component.gpu.setBackground(fg, fgp) |
| 205 | + | component.gpu.setBackground(fg, fgp) |
| 206 | - | end |
| 206 | + | end |
| 207 | - | local value = "" |
| 207 | + | local value = "" |
| 208 | - | for x = cx, cx + length - 1 do |
| 208 | + | for x = cx, cx + length - 1 do |
| 209 | - | value = value .. component.gpu.get(x, cy) |
| 209 | + | value = value .. component.gpu.get(x, cy) |
| 210 | - | end |
| 210 | + | end |
| 211 | - | component.gpu.set(cx, cy, value) |
| 211 | + | component.gpu.set(cx, cy, value) |
| 212 | - | if enabled then |
| 212 | + | if enabled then |
| 213 | - | component.gpu.setForeground(fg, fgp) |
| 213 | + | component.gpu.setForeground(fg, fgp) |
| 214 | - | component.gpu.setBackground(bg, bgp) |
| 214 | + | component.gpu.setBackground(bg, bgp) |
| 215 | - | end |
| 215 | + | end |
| 216 | - | end |
| 216 | + | end |
| 217 | - | |
| 217 | + | |
| 218 | - | local function home() |
| 218 | + | local function home() |
| 219 | - | local cbx, cby = getCursor() |
| 219 | + | local cbx, cby = getCursor() |
| 220 | - | setCursor(1, cby) |
| 220 | + | setCursor(1, cby) |
| 221 | - | end |
| 221 | + | end |
| 222 | - | |
| 222 | + | |
| 223 | - | local function ende() |
| 223 | + | local function ende() |
| 224 | - | local cbx, cby = getCursor() |
| 224 | + | local cbx, cby = getCursor() |
| 225 | - | setCursor(unicode.len(line()) + 1, cby) |
| 225 | + | setCursor(unicode.len(line()) + 1, cby) |
| 226 | - | end |
| 226 | + | end |
| 227 | - | |
| 227 | + | |
| 228 | - | local function left() |
| 228 | + | local function left() |
| 229 | - | local cbx, cby = getCursor() |
| 229 | + | local cbx, cby = getCursor() |
| 230 | - | if cbx > 1 then |
| 230 | + | if cbx > 1 then |
| 231 | - | setCursor(cbx - 1, cby) |
| 231 | + | setCursor(cbx - 1, cby) |
| 232 | - | return true -- for backspace |
| 232 | + | return true -- for backspace |
| 233 | - | elseif cby > 1 then |
| 233 | + | elseif cby > 1 then |
| 234 | - | setCursor(cbx, cby - 1) |
| 234 | + | setCursor(cbx, cby - 1) |
| 235 | - | ende() |
| 235 | + | ende() |
| 236 | - | return true -- again, for backspace |
| 236 | + | return true -- again, for backspace |
| 237 | - | end |
| 237 | + | end |
| 238 | - | end |
| 238 | + | end |
| 239 | - | |
| 239 | + | |
| 240 | - | local function right(n) |
| 240 | + | local function right(n) |
| 241 | - | n = n or 1 |
| 241 | + | n = n or 1 |
| 242 | - | local cbx, cby = getCursor() |
| 242 | + | local cbx, cby = getCursor() |
| 243 | - | local be = unicode.len(line()) + 1 |
| 243 | + | local be = unicode.len(line()) + 1 |
| 244 | - | if cbx < be then |
| 244 | + | if cbx < be then |
| 245 | - | setCursor(cbx + n, cby) |
| 245 | + | setCursor(cbx + n, cby) |
| 246 | - | elseif cby < #buffer then |
| 246 | + | elseif cby < #buffer then |
| 247 | - | setCursor(1, cby + 1) |
| 247 | + | setCursor(1, cby + 1) |
| 248 | - | end |
| 248 | + | end |
| 249 | - | end |
| 249 | + | end |
| 250 | - | |
| 250 | + | |
| 251 | - | local function up(n) |
| 251 | + | local function up(n) |
| 252 | - | n = n or 1 |
| 252 | + | n = n or 1 |
| 253 | - | local cbx, cby = getCursor() |
| 253 | + | local cbx, cby = getCursor() |
| 254 | - | if cby > 1 then |
| 254 | + | if cby > 1 then |
| 255 | - | setCursor(cbx, cby - n) |
| 255 | + | setCursor(cbx, cby - n) |
| 256 | - | if getCursor() > unicode.len(line()) then |
| 256 | + | if getCursor() > unicode.len(line()) then |
| 257 | - | ende() |
| 257 | + | ende() |
| 258 | - | end |
| 258 | + | end |
| 259 | - | end |
| 259 | + | end |
| 260 | - | end |
| 260 | + | end |
| 261 | - | |
| 261 | + | |
| 262 | - | local function down(n) |
| 262 | + | local function down(n) |
| 263 | - | n = n or 1 |
| 263 | + | n = n or 1 |
| 264 | - | local cbx, cby = getCursor() |
| 264 | + | local cbx, cby = getCursor() |
| 265 | - | if cby < #buffer then |
| 265 | + | if cby < #buffer then |
| 266 | - | setCursor(cbx, cby + n) |
| 266 | + | setCursor(cbx, cby + n) |
| 267 | - | if getCursor() > unicode.len(line()) then |
| 267 | + | if getCursor() > unicode.len(line()) then |
| 268 | - | ende() |
| 268 | + | ende() |
| 269 | - | end |
| 269 | + | end |
| 270 | - | end |
| 270 | + | end |
| 271 | - | end |
| 271 | + | end |
| 272 | - | |
| 272 | + | |
| 273 | - | local function delete(fullRow) |
| 273 | + | local function delete(fullRow) |
| 274 | - | local cx, cy = term.getCursor() |
| 274 | + | local cx, cy = term.getCursor() |
| 275 | - | local cbx, cby = getCursor() |
| 275 | + | local cbx, cby = getCursor() |
| 276 | - | local w, h = getSize() |
| 276 | + | local w, h = getSize() |
| 277 | - | local function deleteRow(row) |
| 277 | + | local function deleteRow(row) |
| 278 | - | local content = table.remove(buffer, row) |
| 278 | + | local content = table.remove(buffer, row) |
| 279 | - | local rcy = cy + (row - cby) |
| 279 | + | local rcy = cy + (row - cby) |
| 280 | - | if rcy <= h then |
| 280 | + | if rcy <= h then |
| 281 | - | component.gpu.copy(1, rcy + 1, w, h - rcy, 0, -1) |
| 281 | + | component.gpu.copy(1, rcy + 1, w, h - rcy, 0, -1) |
| 282 | - | component.gpu.set(1, h, text.padRight(buffer[row + (h - rcy)], w)) |
| 282 | + | component.gpu.set(1, h, text.padRight(buffer[row + (h - rcy)], w)) |
| 283 | - | end |
| 283 | + | end |
| 284 | - | return content |
| 284 | + | return content |
| 285 | - | end |
| 285 | + | end |
| 286 | - | if fullRow then |
| 286 | + | if fullRow then |
| 287 | - | term.setCursorBlink(false) |
| 287 | + | term.setCursorBlink(false) |
| 288 | - | if #buffer > 1 then |
| 288 | + | if #buffer > 1 then |
| 289 | - | deleteRow(cby) |
| 289 | + | deleteRow(cby) |
| 290 | - | else |
| 290 | + | else |
| 291 | - | buffer[cby] = "" |
| 291 | + | buffer[cby] = "" |
| 292 | - | component.gpu.fill(1, cy, w, 1, " ") |
| 292 | + | component.gpu.fill(1, cy, w, 1, " ") |
| 293 | - | end |
| 293 | + | end |
| 294 | - | setCursor(1, cby) |
| 294 | + | setCursor(1, cby) |
| 295 | - | elseif cbx <= unicode.len(line()) then |
| 295 | + | elseif cbx <= unicode.len(line()) then |
| 296 | - | term.setCursorBlink(false) |
| 296 | + | term.setCursorBlink(false) |
| 297 | - | buffer[cby] = unicode.sub(line(), 1, cbx - 1) .. |
| 297 | + | buffer[cby] = unicode.sub(line(), 1, cbx - 1) .. |
| 298 | - | unicode.sub(line(), cbx + 1) |
| 298 | + | unicode.sub(line(), cbx + 1) |
| 299 | - | component.gpu.copy(cx + 1, cy, w - cx, 1, -1, 0) |
| 299 | + | component.gpu.copy(cx + 1, cy, w - cx, 1, -1, 0) |
| 300 | - | local br = cbx + (w - cx) |
| 300 | + | local br = cbx + (w - cx) |
| 301 | - | local char = unicode.sub(line(), br, br) |
| 301 | + | local char = unicode.sub(line(), br, br) |
| 302 | - | if not char or unicode.len(char) == 0 then |
| 302 | + | if not char or unicode.len(char) == 0 then |
| 303 | - | char = " " |
| 303 | + | char = " " |
| 304 | - | end |
| 304 | + | end |
| 305 | - | component.gpu.set(w, cy, char) |
| 305 | + | component.gpu.set(w, cy, char) |
| 306 | - | elseif cby < #buffer then |
| 306 | + | elseif cby < #buffer then |
| 307 | - | term.setCursorBlink(false) |
| 307 | + | term.setCursorBlink(false) |
| 308 | - | local append = deleteRow(cby + 1) |
| 308 | + | local append = deleteRow(cby + 1) |
| 309 | - | buffer[cby] = buffer[cby] .. append |
| 309 | + | buffer[cby] = buffer[cby] .. append |
| 310 | - | component.gpu.set(cx, cy, append) |
| 310 | + | component.gpu.set(cx, cy, append) |
| 311 | - | else |
| 311 | + | else |
| 312 | - | return |
| 312 | + | return |
| 313 | - | end |
| 313 | + | end |
| 314 | - | setStatus(helpStatusText()) |
| 314 | + | setStatus(helpStatusText()) |
| 315 | - | end |
| 315 | + | end |
| 316 | - | |
| 316 | + | |
| 317 | - | local function insert(value) |
| 317 | + | local function insert(value) |
| 318 | - | if not value or unicode.len(value) < 1 then |
| 318 | + | if not value or unicode.len(value) < 1 then |
| 319 | - | return |
| 319 | + | return |
| 320 | - | end |
| 320 | + | end |
| 321 | - | term.setCursorBlink(false) |
| 321 | + | term.setCursorBlink(false) |
| 322 | - | local cx, cy = term.getCursor() |
| 322 | + | local cx, cy = term.getCursor() |
| 323 | - | local cbx, cby = getCursor() |
| 323 | + | local cbx, cby = getCursor() |
| 324 | - | local w, h = getSize() |
| 324 | + | local w, h = getSize() |
| 325 | - | buffer[cby] = unicode.sub(line(), 1, cbx - 1) .. |
| 325 | + | buffer[cby] = unicode.sub(line(), 1, cbx - 1) .. |
| 326 | - | value .. |
| 326 | + | value .. |
| 327 | - | unicode.sub(line(), cbx) |
| 327 | + | unicode.sub(line(), cbx) |
| 328 | - | local len = unicode.len(value) |
| 328 | + | local len = unicode.len(value) |
| 329 | - | local n = w - (cx - 1) - len |
| 329 | + | local n = w - (cx - 1) - len |
| 330 | - | if n > 0 then |
| 330 | + | if n > 0 then |
| 331 | - | component.gpu.copy(cx, cy, n, 1, len, 0) |
| 331 | + | component.gpu.copy(cx, cy, n, 1, len, 0) |
| 332 | - | end |
| 332 | + | end |
| 333 | - | component.gpu.set(cx, cy, value) |
| 333 | + | component.gpu.set(cx, cy, value) |
| 334 | - | right(len) |
| 334 | + | right(len) |
| 335 | - | setStatus(helpStatusText()) |
| 335 | + | setStatus(helpStatusText()) |
| 336 | - | end |
| 336 | + | end |
| 337 | - | |
| 337 | + | |
| 338 | - | local function enter() |
| 338 | + | local function enter() |
| 339 | - | term.setCursorBlink(false) |
| 339 | + | term.setCursorBlink(false) |
| 340 | - | local cx, cy = term.getCursor() |
| 340 | + | local cx, cy = term.getCursor() |
| 341 | - | local cbx, cby = getCursor() |
| 341 | + | local cbx, cby = getCursor() |
| 342 | - | local w, h = getSize() |
| 342 | + | local w, h = getSize() |
| 343 | - | table.insert(buffer, cby + 1, unicode.sub(buffer[cby], cbx)) |
| 343 | + | table.insert(buffer, cby + 1, unicode.sub(buffer[cby], cbx)) |
| 344 | - | buffer[cby] = unicode.sub(buffer[cby], 1, cbx - 1) |
| 344 | + | buffer[cby] = unicode.sub(buffer[cby], 1, cbx - 1) |
| 345 | - | component.gpu.fill(cx, cy, w - (cx - 1), 1, " ") |
| 345 | + | component.gpu.fill(cx, cy, w - (cx - 1), 1, " ") |
| 346 | - | if cy < h then |
| 346 | + | if cy < h then |
| 347 | - | if cy < h - 1 then |
| 347 | + | if cy < h - 1 then |
| 348 | - | component.gpu.copy(1, cy + 1, w, h - (cy + 1), 0, 1) |
| 348 | + | component.gpu.copy(1, cy + 1, w, h - (cy + 1), 0, 1) |
| 349 | - | end |
| 349 | + | end |
| 350 | - | component.gpu.set(1, cy + 1, text.padRight(buffer[cby + 1], w)) |
| 350 | + | component.gpu.set(1, cy + 1, text.padRight(buffer[cby + 1], w)) |
| 351 | - | end |
| 351 | + | end |
| 352 | - | setCursor(1, cby + 1) |
| 352 | + | setCursor(1, cby + 1) |
| 353 | - | setStatus(helpStatusText()) |
| 353 | + | setStatus(helpStatusText()) |
| 354 | - | end |
| 354 | + | end |
| 355 | - | |
| 355 | + | |
| 356 | - | local findText = "" |
| 356 | + | local findText = "" |
| 357 | - | |
| 357 | + | |
| 358 | - | local function find() |
| 358 | + | local function find() |
| 359 | - | local w, h = getSize() |
| 359 | + | local w, h = getSize() |
| 360 | - | local cx, cy = term.getCursor() |
| 360 | + | local cx, cy = term.getCursor() |
| 361 | - | local cbx, cby = getCursor() |
| 361 | + | local cbx, cby = getCursor() |
| 362 | - | local ibx, iby = cbx, cby |
| 362 | + | local ibx, iby = cbx, cby |
| 363 | - | while running do |
| 363 | + | while running do |
| 364 | - | if unicode.len(findText) > 0 then |
| 364 | + | if unicode.len(findText) > 0 then |
| 365 | - | local sx, sy |
| 365 | + | local sx, sy |
| 366 | - | for syo = 1, #buffer do -- iterate lines with wraparound |
| 366 | + | for syo = 1, #buffer do -- iterate lines with wraparound |
| 367 | - | sy = (iby + syo - 1 + #buffer - 1) % #buffer + 1 |
| 367 | + | sy = (iby + syo - 1 + #buffer - 1) % #buffer + 1 |
| 368 | - | sx = string.find(buffer[sy], findText, syo == 1 and ibx or 1, true) |
| 368 | + | sx = string.find(buffer[sy], findText, syo == 1 and ibx or 1, true) |
| 369 | - | if sx and (sx >= ibx or syo > 1) then |
| 369 | + | if sx and (sx >= ibx or syo > 1) then |
| 370 | - | break |
| 370 | + | break |
| 371 | - | end |
| 371 | + | end |
| 372 | - | end |
| 372 | + | end |
| 373 | - | if not sx then -- special case for single matches |
| 373 | + | if not sx then -- special case for single matches |
| 374 | - | sy = iby |
| 374 | + | sy = iby |
| 375 | - | sx = string.find(buffer[sy], findText, nil, true) |
| 375 | + | sx = string.find(buffer[sy], findText, nil, true) |
| 376 | - | end |
| 376 | + | end |
| 377 | - | if sx then |
| 377 | + | if sx then |
| 378 | - | cbx, cby = sx, sy |
| 378 | + | cbx, cby = sx, sy |
| 379 | - | setCursor(cbx, cby) |
| 379 | + | setCursor(cbx, cby) |
| 380 | - | highlight(cbx, cby, unicode.len(findText), true) |
| 380 | + | highlight(cbx, cby, unicode.len(findText), true) |
| 381 | - | end |
| 381 | + | end |
| 382 | - | end |
| 382 | + | end |
| 383 | - | term.setCursor(7 + unicode.len(findText), h + 1) |
| 383 | + | term.setCursor(7 + unicode.len(findText), h + 1) |
| 384 | - | setStatus("Find: " .. findText) |
| 384 | + | setStatus("Find: " .. findText)
|
| 385 | - | |
| 385 | + | |
| 386 | - | local _, _, char, code = event.pull("key_down") |
| 386 | + | local _, _, char, code = event.pull("key_down")
|
| 387 | - | local handler, name = getKeyBindHandler(code) |
| 387 | + | local handler, name = getKeyBindHandler(code) |
| 388 | - | highlight(cbx, cby, unicode.len(findText), false) |
| 388 | + | highlight(cbx, cby, unicode.len(findText), false) |
| 389 | - | if name == "newline" then |
| 389 | + | if name == "newline" then |
| 390 | - | break |
| 390 | + | break |
| 391 | - | elseif name == "close" then |
| 391 | + | elseif name == "close" then |
| 392 | - | handler() |
| 392 | + | handler() |
| 393 | - | elseif name == "backspace" then |
| 393 | + | elseif name == "backspace" then |
| 394 | - | findText = unicode.sub(findText, 1, -2) |
| 394 | + | findText = unicode.sub(findText, 1, -2) |
| 395 | - | elseif name == "find" or name == "findnext" then |
| 395 | + | elseif name == "find" or name == "findnext" then |
| 396 | - | ibx = cbx + 1 |
| 396 | + | ibx = cbx + 1 |
| 397 | - | iby = cby |
| 397 | + | iby = cby |
| 398 | - | elseif not keyboard.isControl(char) then |
| 398 | + | elseif not keyboard.isControl(char) then |
| 399 | - | findText = findText .. unicode.char(char) |
| 399 | + | findText = findText .. unicode.char(char) |
| 400 | - | end |
| 400 | + | end |
| 401 | - | end |
| 401 | + | end |
| 402 | - | setCursor(cbx, cby) |
| 402 | + | setCursor(cbx, cby) |
| 403 | - | setStatus(helpStatusText()) |
| 403 | + | setStatus(helpStatusText()) |
| 404 | - | end |
| 404 | + | end |
| 405 | - | |
| 405 | + | |
| 406 | - | ------------------------------------------------------------------------------- |
| 406 | + | ------------------------------------------------------------------------------- |
| 407 | - | |
| 407 | + | |
| 408 | - | local keyBindHandlers = { |
| 408 | + | local keyBindHandlers = {
|
| 409 | - | left = left, |
| 409 | + | left = left, |
| 410 | - | right = right, |
| 410 | + | right = right, |
| 411 | - | up = up, |
| 411 | + | up = up, |
| 412 | - | down = down, |
| 412 | + | down = down, |
| 413 | - | home = home, |
| 413 | + | home = home, |
| 414 | - | eol = ende, |
| 414 | + | eol = ende, |
| 415 | - | pageUp = function() |
| 415 | + | pageUp = function() |
| 416 | - | local w, h = getSize() |
| 416 | + | local w, h = getSize() |
| 417 | - | up(h - 1) |
| 417 | + | up(h - 1) |
| 418 | - | end, |
| 418 | + | end, |
| 419 | - | pageDown = function() |
| 419 | + | pageDown = function() |
| 420 | - | local w, h = getSize() |
| 420 | + | local w, h = getSize() |
| 421 | - | down(h - 1) |
| 421 | + | down(h - 1) |
| 422 | - | end, |
| 422 | + | end, |
| 423 | - | |
| 423 | + | |
| 424 | - | backspace = function() |
| 424 | + | backspace = function() |
| 425 | - | if not readonly and left() then |
| 425 | + | if not readonly and left() then |
| 426 | - | delete() |
| 426 | + | delete() |
| 427 | - | end |
| 427 | + | end |
| 428 | - | end, |
| 428 | + | end, |
| 429 | - | delete = function() |
| 429 | + | delete = function() |
| 430 | - | if not readonly then |
| 430 | + | if not readonly then |
| 431 | - | delete() |
| 431 | + | delete() |
| 432 | - | end |
| 432 | + | end |
| 433 | - | end, |
| 433 | + | end, |
| 434 | - | deleteLine = function() |
| 434 | + | deleteLine = function() |
| 435 | - | if not readonly then |
| 435 | + | if not readonly then |
| 436 | - | delete(true) |
| 436 | + | delete(true) |
| 437 | - | end |
| 437 | + | end |
| 438 | - | end, |
| 438 | + | end, |
| 439 | - | newline = function() |
| 439 | + | newline = function() |
| 440 | - | if not readonly then |
| 440 | + | if not readonly then |
| 441 | - | enter() |
| 441 | + | enter() |
| 442 | - | end |
| 442 | + | end |
| 443 | - | end, |
| 443 | + | end, |
| 444 | - | |
| 444 | + | |
| 445 | - | save = function() |
| 445 | + | save = function() |
| 446 | - | if readonly then return end |
| 446 | + | if readonly then return end |
| 447 | - | local new = not fs.exists(filename) |
| 447 | + | local new = not fs.exists(filename) |
| 448 | - | local backup |
| 448 | + | local backup |
| 449 | - | if not new then |
| 449 | + | if not new then |
| 450 | - | backup = filename .. "~" |
| 450 | + | backup = filename .. "~" |
| 451 | - | for i = 1, math.huge do |
| 451 | + | for i = 1, math.huge do |
| 452 | - | if not fs.exists(backup) then |
| 452 | + | if not fs.exists(backup) then |
| 453 | - | break |
| 453 | + | break |
| 454 | - | end |
| 454 | + | end |
| 455 | - | backup = filename .. "~" .. i |
| 455 | + | backup = filename .. "~" .. i |
| 456 | - | end |
| 456 | + | end |
| 457 | - | fs.copy(filename, backup) |
| 457 | + | fs.copy(filename, backup) |
| 458 | - | end |
| 458 | + | end |
| 459 | - | local f, reason = io.open(filename, "w") |
| 459 | + | local f, reason = io.open(filename, "w") |
| 460 | - | if f then |
| 460 | + | if f then |
| 461 | - | local chars, firstLine = 0, true |
| 461 | + | local chars, firstLine = 0, true |
| 462 | - | for _, line in ipairs(buffer) do |
| 462 | + | for _, line in ipairs(buffer) do |
| 463 | - | if not firstLine then |
| 463 | + | if not firstLine then |
| 464 | - | line = "\n" .. line |
| 464 | + | line = "\n" .. line |
| 465 | - | end |
| 465 | + | end |
| 466 | - | firstLine = false |
| 466 | + | firstLine = false |
| 467 | - | f:write(line) |
| 467 | + | f:write(line) |
| 468 | - | chars = chars + unicode.len(line) |
| 468 | + | chars = chars + unicode.len(line) |
| 469 | - | end |
| 469 | + | end |
| 470 | - | f:close() |
| 470 | + | f:close() |
| 471 | - | local format |
| 471 | + | local format |
| 472 | - | if new then |
| 472 | + | if new then |
| 473 | - | format = [["%s" [New] %dL,%dC written]] |
| 473 | + | format = [["%s" [New] %dL,%dC written]] |
| 474 | - | else |
| 474 | + | else |
| 475 | - | format = [["%s" %dL,%dC written]] |
| 475 | + | format = [["%s" %dL,%dC written]] |
| 476 | - | end |
| 476 | + | end |
| 477 | - | setStatus(string.format(format, fs.name(filename), #buffer, chars)) |
| 477 | + | setStatus(string.format(format, fs.name(filename), #buffer, chars)) |
| 478 | - | else |
| 478 | + | else |
| 479 | - | setStatus(reason) |
| 479 | + | setStatus(reason) |
| 480 | - | end |
| 480 | + | end |
| 481 | - | if not new then |
| 481 | + | if not new then |
| 482 | - | fs.remove(backup) |
| 482 | + | fs.remove(backup) |
| 483 | - | end |
| 483 | + | end |
| 484 | - | end, |
| 484 | + | end, |
| 485 | - | close = function() |
| 485 | + | close = function() |
| 486 | - | -- TODO ask to save if changed |
| 486 | + | -- TODO ask to save if changed |
| 487 | - | running = false |
| 487 | + | running = false |
| 488 | - | end, |
| 488 | + | end, |
| 489 | - | find = function() |
| 489 | + | find = function() |
| 490 | - | findText = "" |
| 490 | + | findText = "" |
| 491 | - | find() |
| 491 | + | find() |
| 492 | - | end, |
| 492 | + | end, |
| 493 | - | findnext = find |
| 493 | + | findnext = find |
| 494 | - | } |
| 494 | + | } |
| 495 | - | |
| 495 | + | |
| 496 | - | getKeyBindHandler = function(code) |
| 496 | + | getKeyBindHandler = function(code) |
| 497 | - | if type(config.keybinds) ~= "table" then return end |
| 497 | + | if type(config.keybinds) ~= "table" then return end |
| 498 | - | -- Look for matches, prefer more 'precise' keybinds, e.g. prefer |
| 498 | + | -- Look for matches, prefer more 'precise' keybinds, e.g. prefer |
| 499 | - | -- ctrl+del over del. |
| 499 | + | -- ctrl+del over del. |
| 500 | - | local result, resultName, resultWeight = nil, nil, 0 |
| 500 | + | local result, resultName, resultWeight = nil, nil, 0 |
| 501 | - | for command, keybinds in pairs(config.keybinds) do |
| 501 | + | for command, keybinds in pairs(config.keybinds) do |
| 502 | - | if type(keybinds) == "table" and keyBindHandlers[command] then |
| 502 | + | if type(keybinds) == "table" and keyBindHandlers[command] then |
| 503 | - | for _, keybind in ipairs(keybinds) do |
| 503 | + | for _, keybind in ipairs(keybinds) do |
| 504 | - | if type(keybind) == "table" then |
| 504 | + | if type(keybind) == "table" then |
| 505 | - | local alt, control, shift, key |
| 505 | + | local alt, control, shift, key |
| 506 | - | for _, value in ipairs(keybind) do |
| 506 | + | for _, value in ipairs(keybind) do |
| 507 | - | if value == "alt" then alt = true |
| 507 | + | if value == "alt" then alt = true |
| 508 | - | elseif value == "control" then control = true |
| 508 | + | elseif value == "control" then control = true |
| 509 | - | elseif value == "shift" then shift = true |
| 509 | + | elseif value == "shift" then shift = true |
| 510 | - | else key = value end |
| 510 | + | else key = value end |
| 511 | - | end |
| 511 | + | end |
| 512 | - | if (not alt or keyboard.isAltDown()) and |
| 512 | + | if (not alt or keyboard.isAltDown()) and |
| 513 | - | (not control or keyboard.isControlDown()) and |
| 513 | + | (not control or keyboard.isControlDown()) and |
| 514 | - | (not shift or keyboard.isShiftDown()) and |
| 514 | + | (not shift or keyboard.isShiftDown()) and |
| 515 | - | code == keyboard.keys[key] and |
| 515 | + | code == keyboard.keys[key] and |
| 516 | - | #keybind > resultWeight |
| 516 | + | #keybind > resultWeight |
| 517 | - | then |
| 517 | + | then |
| 518 | - | resultWeight = #keybind |
| 518 | + | resultWeight = #keybind |
| 519 | - | resultName = command |
| 519 | + | resultName = command |
| 520 | - | result = keyBindHandlers[command] |
| 520 | + | result = keyBindHandlers[command] |
| 521 | - | end |
| 521 | + | end |
| 522 | - | end |
| 522 | + | end |
| 523 | - | end |
| 523 | + | end |
| 524 | - | end |
| 524 | + | end |
| 525 | - | end |
| 525 | + | end |
| 526 | - | return result, resultName |
| 526 | + | return result, resultName |
| 527 | - | end |
| 527 | + | end |
| 528 | - | |
| 528 | + | |
| 529 | - | ------------------------------------------------------------------------------- |
| 529 | + | ------------------------------------------------------------------------------- |
| 530 | - | |
| 530 | + | |
| 531 | - | local function onKeyDown(char, code) |
| 531 | + | local function onKeyDown(char, code) |
| 532 | - | local handler = getKeyBindHandler(code) |
| 532 | + | local handler = getKeyBindHandler(code) |
| 533 | - | if handler then |
| 533 | + | if handler then |
| 534 | - | handler() |
| 534 | + | handler() |
| 535 | - | elseif readonly and code == keyboard.keys.q then |
| 535 | + | elseif readonly and code == keyboard.keys.q then |
| 536 | - | running = false |
| 536 | + | running = false |
| 537 | - | elseif not readonly then |
| 537 | + | elseif not readonly then |
| 538 | - | if not keyboard.isControl(char) then |
| 538 | + | if not keyboard.isControl(char) then |
| 539 | - | insert(unicode.char(char)) |
| 539 | + | insert(unicode.char(char)) |
| 540 | - | elseif unicode.char(char) == "\t" then |
| 540 | + | elseif unicode.char(char) == "\t" then |
| 541 | - | insert(" ") |
| 541 | + | insert(" ")
|
| 542 | - | end |
| 542 | + | end |
| 543 | - | end |
| 543 | + | end |
| 544 | - | end |
| 544 | + | end |
| 545 | - | |
| 545 | + | |
| 546 | - | local function onClipboard(value) |
| 546 | + | local function onClipboard(value) |
| 547 | - | value = value:gsub("\r\n", "\n") |
| 547 | + | value = value:gsub("\r\n", "\n")
|
| 548 | - | local cbx, cby = getCursor() |
| 548 | + | local cbx, cby = getCursor() |
| 549 | - | local start = 1 |
| 549 | + | local start = 1 |
| 550 | - | local l = value:find("\n", 1, true) |
| 550 | + | local l = value:find("\n", 1, true)
|
| 551 | - | if l then |
| 551 | + | if l then |
| 552 | - | repeat |
| 552 | + | repeat |
| 553 | - | local line = string.sub(value, start, l - 1) |
| 553 | + | local line = string.sub(value, start, l - 1) |
| 554 | - | line = text.detab(line, 2) |
| 554 | + | line = text.detab(line, 2) |
| 555 | - | insert(line) |
| 555 | + | insert(line) |
| 556 | - | enter() |
| 556 | + | enter() |
| 557 | - | start = l + 1 |
| 557 | + | start = l + 1 |
| 558 | - | l = value:find("\n", start, true) |
| 558 | + | l = value:find("\n", start, true)
|
| 559 | - | until not l |
| 559 | + | until not l |
| 560 | - | end |
| 560 | + | end |
| 561 | - | insert(string.sub(value, start)) |
| 561 | + | insert(string.sub(value, start)) |
| 562 | - | end |
| 562 | + | end |
| 563 | - | |
| 563 | + | |
| 564 | - | local function onClick(x, y) |
| 564 | + | local function onClick(x, y) |
| 565 | - | setCursor(x + scrollX, y + scrollY) |
| 565 | + | setCursor(x + scrollX, y + scrollY) |
| 566 | - | end |
| 566 | + | end |
| 567 | - | |
| 567 | + | |
| 568 | - | local function onScroll(direction) |
| 568 | + | local function onScroll(direction) |
| 569 | - | local cbx, cby = getCursor() |
| 569 | + | local cbx, cby = getCursor() |
| 570 | - | setCursor(cbx, cby - direction * 12) |
| 570 | + | setCursor(cbx, cby - direction * 12) |
| 571 | - | end |
| 571 | + | end |
| 572 | - | |
| 572 | + | |
| 573 | - | ------------------------------------------------------------------------------- |
| 573 | + | ------------------------------------------------------------------------------- |
| 574 | - | |
| 574 | + | |
| 575 | - | do |
| 575 | + | do |
| 576 | - | local f = io.open(filename) |
| 576 | + | local f = io.open(filename) |
| 577 | - | if f then |
| 577 | + | if f then |
| 578 | - | local w, h = getSize() |
| 578 | + | local w, h = getSize() |
| 579 | - | local chars = 0 |
| 579 | + | local chars = 0 |
| 580 | - | for line in f:lines() do |
| 580 | + | for line in f:lines() do |
| 581 | - | if line:sub(-1) == "\r" then |
| 581 | + | if line:sub(-1) == "\r" then |
| 582 | - | line = line:sub(1, -2) |
| 582 | + | line = line:sub(1, -2) |
| 583 | - | end |
| 583 | + | end |
| 584 | - | table.insert(buffer, line) |
| 584 | + | table.insert(buffer, line) |
| 585 | - | chars = chars + unicode.len(line) |
| 585 | + | chars = chars + unicode.len(line) |
| 586 | - | if #buffer <= h then |
| 586 | + | if #buffer <= h then |
| 587 | - | component.gpu.set(1, #buffer, line) |
| 587 | + | component.gpu.set(1, #buffer, line) |
| 588 | - | end |
| 588 | + | end |
| 589 | - | end |
| 589 | + | end |
| 590 | - | f:close() |
| 590 | + | f:close() |
| 591 | - | if #buffer == 0 then |
| 591 | + | if #buffer == 0 then |
| 592 | - | table.insert(buffer, "") |
| 592 | + | table.insert(buffer, "") |
| 593 | - | end |
| 593 | + | end |
| 594 | - | local format |
| 594 | + | local format |
| 595 | - | if readonly then |
| 595 | + | if readonly then |
| 596 | - | format = [["%s" [readonly] %dL,%dC]] |
| 596 | + | format = [["%s" [readonly] %dL,%dC]] |
| 597 | - | else |
| 597 | + | else |
| 598 | - | format = [["%s" %dL,%dC]] |
| 598 | + | format = [["%s" %dL,%dC]] |
| 599 | - | end |
| 599 | + | end |
| 600 | - | setStatus(string.format(format, fs.name(filename), #buffer, chars)) |
| 600 | + | setStatus(string.format(format, fs.name(filename), #buffer, chars)) |
| 601 | - | else |
| 601 | + | else |
| 602 | - | table.insert(buffer, "") |
| 602 | + | table.insert(buffer, "") |
| 603 | - | setStatus(string.format([["%s" [New File] ]], fs.name(filename))) |
| 603 | + | setStatus(string.format([["%s" [New File] ]], fs.name(filename))) |
| 604 | - | end |
| 604 | + | end |
| 605 | - | setCursor(1, 1) |
| 605 | + | setCursor(1, 1) |
| 606 | - | end |
| 606 | + | end |
| 607 | - | |
| 607 | + | |
| 608 | - | while running do |
| 608 | + | while running do |
| 609 | - | local event, address, arg1, arg2, arg3 = event.pull() |
| 609 | + | local event, address, arg1, arg2, arg3 = event.pull() |
| 610 | - | if type(address) == "string" and component.isPrimary(address) then |
| 610 | + | if type(address) == "string" and component.isPrimary(address) then |
| 611 | - | local blink = true |
| 611 | + | local blink = true |
| 612 | - | if event == "key_down" then |
| 612 | + | if event == "key_down" then |
| 613 | - | onKeyDown(arg1, arg2) |
| 613 | + | onKeyDown(arg1, arg2) |
| 614 | - | elseif event == "clipboard" and not readonly then |
| 614 | + | elseif event == "clipboard" and not readonly then |
| 615 | - | onClipboard(arg1) |
| 615 | + | onClipboard(arg1) |
| 616 | - | elseif event == "touch" or event == "drag" then |
| 616 | + | elseif event == "touch" or event == "drag" then |
| 617 | - | onClick(arg1, arg2) |
| 617 | + | onClick(arg1, arg2) |
| 618 | - | elseif event == "scroll" then |
| 618 | + | elseif event == "scroll" then |
| 619 | - | onScroll(arg3) |
| 619 | + | onScroll(arg3) |
| 620 | - | else |
| 620 | + | else |
| 621 | - | blink = false |
| 621 | + | blink = false |
| 622 | - | end |
| 622 | + | end |
| 623 | - | if blink then |
| 623 | + | if blink then |
| 624 | - | term.setCursorBlink(true) |
| 624 | + | term.setCursorBlink(true) |
| 625 | - | term.setCursorBlink(true) -- force toggle to caret |
| 625 | + | term.setCursorBlink(true) -- force toggle to caret |
| 626 | - | end |
| 626 | + | end |
| 627 | - | end |
| 627 | + | end |
| 628 | - | end |
| 628 | + | end |
| 629 | - | |
| 629 | + | |
| 630 | - | term.clear() |
| 630 | + | term.clear() |
| 631 | term.setCursorBlink(false) |