local component = require "component" local event = require "event" local f = component.list("openprinter")() local printer = f and component.proxy(f) local _, unicode = pcall(require, "unicode") local _, printwidth = pcall(require, "printwidth") local tA = {...} local buffer = {} local cx, cy = 1, 1 local vx, vy = 1, 1 local lcx, lcy = 1, 1 local mx, my = 80, 25 local w, f = pcall(require, "mtmenu") if w then mx, my = t.getScreenSize() else mx, my = require("term").getViewport() end local mw = printer and printer.maxWidth() or 164 local width = (printwidth or {}).width or printer.width if #tA < 1 then print("Usage: wip ") os.exit() end local f = io.open(tA[1], "rb") if f then for line in f:lines() do buffer[#buffer+1] = line end else buffer[1] = "" end local function save(fn) fn=fn or tA[1] local f = io.open(fn, "wb") if f then for k,v in ipairs(buffer) do f:write(v.."\n") end f:close() end end local function fwrite(...) return io.write(string.format(...)) end local function printerFormat(s) s=s:gsub("^##","§n") s=s:gsub("^#","§l§n") s=s:gsub("%*(.-)%*","§o%1§r") s=s:gsub("$DATE",os.date("%Y-%m-%d")) return s end local function getOF(s, start) start=start or 1 local f, o = "", "" for i = start, #s do if width(printerFormat(s:sub(1,i))) >= mw then f, o = s:sub(1,i-1), s:sub(i) return f, o, i end end return s:sub(start), "", 80 end local function findLastPageBreak(n) for i = n, 1, -1 do if (buffer[i] or ""):sub(1,1) == "&" then return i end end return 0 end local function displayLine(n) for i = n, 1, -1 do if (buffer[i] or ""):sub(1,1) == "&" then return (n - i)%21 end end return n%21 end local function displayPage(n) local r,l = 0, 0 for i,v in ipairs(buffer) do if v:sub(1,1) == "&" or i > l+20 then r, l = r + 1, i end if i == n then break end end return r end local function draw(full) cx, cy = math.max(1, math.min(cx, #(buffer[cy] or "")+1)), math.max(1, math.min(cy, #buffer)) local dx=mx-4 while cy > (vy + my - (my/4)) do vy = vy + math.ceil(my/3) end while cy < (vy + (my/4)) do vy = vy - math.ceil(my/3) end while cx > (vx + dx - (dx/4)) do vx = vx + math.ceil(dx/3) end while cx < (vx + (dx/4)) do vx = vx - math.ceil(dx/3) end vx, vy=math.max(1, vx), math.max(1,vy) local start, finish = math.max(1,cy-1), math.min(cy+1, #buffer) if cy ~= lcy or full then start, finish = vy, vy + (my-2) end local tcx, tcy = cx - vx + 5, cy - vy + 1 for i = start, finish do local ti = i - vy + 1 local line = buffer[i] or "" local fit, overflow, ofi = getOF(line, vx) fit=fit:sub(vx) local lc = line:sub(1,1) == "#" and 32 or line:sub(1,1) == "&" and 7 or 0 fwrite("\27[%i;1H\27[36m%3i \27[%im%s\27[31m%s\27[0m%s", ti, displayLine(i), lc, fit:gsub("%*(.-)%*","\27[7m*%1*\27[0m"), overflow:sub(1,mx-#fit-4), (" "):rep(mx-#fit-#overflow-4)) end if cy ~= lcy or cx ~= lcx or full then local lst = string.format("🗑^W 🖬^S 🖨^P 🗎%s",tA[1]) local rst = string.format("🗐%i/%i%+4i,%-3i", displayPage(cy),displayPage(#buffer), cx, cy) fwrite("\27[%i;1H%s%"..tostring(mx-unicode.wlen(lst)).."s",my,lst,rst) end local cc = buffer[cy]:sub(cx, cx) cc = #cc > 0 and cc or " " fwrite("\27[%i;%iH\27[7m%s\27[0m",tcy, tcx,cc) lcx, lcy = cx, cy end io.write("\27[2J\27[H") draw(true) local frd = false while true do draw(frd) frd=false local tE = {event.pull()} if tE[1] == "key_down" then ch, co = tE[3], tE[4] if ch == 23 and co == 17 then break elseif co == 200 then -- up cy = cy - 1 elseif co == 208 then -- down cy = cy + 1 elseif co == 203 then -- left cx = cx - 1 elseif co == 205 then -- right cx = cx + 1 elseif ch > 31 and ch < 127 then -- insert character buffer[cy] = buffer[cy]:sub(1,cx-1) .. string.char(ch) .. buffer[cy]:sub(cx) cx = cx + 1 elseif ch == 8 and co == 14 then -- backspace if cx == 1 and cy > 1 then cx = #buffer[cy-1]+1 buffer[cy-1] = buffer[cy-1] .. table.remove(buffer, cy) cy = cy - 1 frd = true else buffer[cy] = buffer[cy]:sub(1,cx-2) .. buffer[cy]:sub(cx) cx = cx - 1 end elseif ch == 127 and co == 211 then -- delete if cx == #buffer[cy]+1 then buffer[cy] = buffer[cy] .. (table.remove(buffer,cy+1) or "") frd = true else buffer[cy] = buffer[cy]:sub(1,cx-1) .. buffer[cy]:sub(cx+1) end elseif ch == 13 and co == 28 then -- enter table.insert(buffer, cy+1, buffer[cy]:sub(cx)) buffer[cy] = buffer[cy]:sub(1,cx-1) cx,cy=1,cy+1 frd = true elseif co == 199 then -- home cx = 1 elseif co == 207 then -- end cx = #buffer[cy] + 1 elseif co == 201 then -- pgup cy = cy - (my-1) elseif co == 209 then -- pgdn cy = cy + (my-1) elseif ch == 19 and co == 31 then -- ^s, save save() elseif ch == 16 and co == 25 then -- ^p, print local tn = os.tmpname() save(tn) io.write("\27[2J\27[H") os.execute(string.format("wipprint '%s'", tn)) require("filesystem").remove(tn) frd = true end elseif tE[1] == "touch" then local tx, ty = tE[3], tE[4] cx, cy = vx + tx - 5, vy + ty - 1 frd = true end end io.write("\27[2J\27[H")