|
- local ed = package.loaded.ed or {}
- ed.bfunc = ed.bfunc or {}
- ed.ifunc = ed.ifunc or setmetatable({},{__index=ed.bfunc})
- ed.buffers = ed.buffers or {}
-
- function ed.bfunc:load(fpath)
- local f = io.open(fpath,"rb")
- if not f then return false, "unable to open file" end
- for line in f:lines() do
- self[#self+1] = line
- end
- f:close()
- self.path = fpath
- return true, #self
- end
-
- function ed.bfunc:save(fpath)
- local path = fpath or self.path
- if not path then return false, "no path" end
- self.path = path
- local f = io.open(path,"wb")
- if not f then return false, "unable to open file" end
- for k,v in ipairs(self) do
- f:write(v.."\n")
- end
- f:close()
- self.dirty = false
- return true
- end
-
- function ed.bfunc:close(discard)
- if not discard and self.dirty then
- local saved = self:save()
- if not saved then return false, "unable to save buffer" end
- end
- for k,v in pairs(ed.buffers) do
- if v == self then
- table.remove(ed.buffers,k)
- return true
- end
- end
- return false, "unable to find buffer handle"
- end
-
- function ed.bfunc:range(start,finish)
- start, finish = math.max(1,tonumber(start) or 1), math.min(#self,tonumber(finish) or #self)
- local rt = {}
- for i = start, finish do
- rt[#rt+1] = self[i]
- end
- return rt
- end
-
- function ed.bfunc:checkCursor()
- self.y = math.max(self.y,1)
- self.y = math.min(self.y,#self)
- self.x = math.max(self.x,1)
- self.x = math.min(self.x,math.max(self[self.y]:len()+1,1))
- end
-
- function ed.ifunc.buffers()
- for k,v in pairs(ed.buffers) do
- print(string.format("\27[31m%4i\27[0m %s",k,v.path or "?"))
- end
- end
-
- function ed.ifunc.help()
- print("Available commands:")
- for k,v in pairs(ed.bfunc) do
- print(k)
- end
- for k,v in pairs(ed.ifunc) do
- print(k)
- end
- end
-
- function ed.ifunc:list(start,finish)
- start, finish = math.max(1,tonumber(start) or 1), math.min(#self,tonumber(finish) or #self)
- local lt = self:range(start,finish)
- for k,v in pairs(lt) do
- print(string.format("\27[31m%4d\27[0m %s",k+start-1,v))
- end
- end
-
- function ed.ifunc:insert(p,o)
- ed.ifunc.pointer(self,p)
- while true do
- io.write(string.format("\27[31m%4d\27[0m ",self.y + (o or 0)))
- local line = io.read()
- if line == "." then break end
- table.insert(self,self.y + (o or 0),line)
- self.dirty = true
- self.y = self.y + 1
- end
- end
-
- function ed.ifunc:append(p)
- ed.ifunc.insert(self,p,1)
- end
-
- function ed.ifunc:pointer(n)
- self.y = math.max(1,tonumber(n) or 1)
- self.y = math.min(#self,self.y)
- print(self.y)
- end
-
- function ed.newBuffer()
- local nb = setmetatable({},{__index=ed.bfunc})
- nb.x,nb.y = 1, 1
- ed.buffers[#ed.buffers+1] = nb
- return nb
- end
-
- function ed.open(buffer)
- local bpath = buffer
- if ed.buffers[buffer] then
- buffer = ed.buffers[buffer]
- end
- if type(buffer) == "string" then
- nb = ed.newBuffer()
- nb:load(buffer)
- buffer = nb
- end
- if type(buffer) ~= "table" then buffer = ed.newBuffer() end
- buffer[1] = buffer[1] or ""
- buffer.path = buffer.path or "/"..((bpath:sub(1,1) == "/" and table.concat(fs.segments(path),"/")) or table.concat(fs.segments(os.getenv("PWD").."/"..bpath),"/"))
- return buffer
- end
-
- function ed.interactive(buffer)
- buffer=ed.open(buffer)
- while true do
- io.write("\27[34mced:\27[0m ")
- local line = io.read()
- local words = {}
- for word in line:gmatch("[^%s]+") do
- words[#words+1] = word
- end
- local cmd = table.remove(words,1)
- if ed.ifunc[cmd] then
- print(ed.ifunc[cmd](buffer,table.unpack(words)))
- elseif cmd == "quit" then
- break
- else
- print("Unknown command.")
- end
- if cmd == "close" then
- break
- end
- end
- end
-
- function ed.visual(buffer)
- buffer=ed.open(buffer)
- local mx, my = 40, 13
- local cx,cy = math.max(1,buffer.x-mx//2), math.max(1,buffer.y-my//2)
- local ox, oy
- local mode = "c"
- local mult, multstr = 1, ""
- local resized = false
- io.write("\27[999;999H\27[6n")
- local function drawBuffer(force)
- if cx ~= ox or cy ~= oy or force then
- io.write("\27[2J\27[H")
- for i = cy, cy+my do
- print(string.format("\27[31m%4i \27[0m%s",i,(buffer[i] or "\27[36m~"):sub(cx,cx+mx-6)))
- end
- elseif mode == "i" then
- print(string.format("\27[2K\27[999D\27[31m%4i \27[0m%s",buffer.y,(buffer[buffer.y] or "\27[36m~"):sub(cx,cx+mx-6)))
- end
- io.write(string.format("\27[1;%iH\27[0;36;%im\27[2K[%s] ced visual: %i,%i/%i, %iK free %i",my+2,(mode == "c" and 7) or 0, mode, buffer.x, buffer.y, #buffer, computer.freeMemory()//1024,mult))
- io.write(string.format("\27[%i;%iH\27[0m",buffer.x+6-cx,buffer.y-cy+1))
- end
- os.setTimeout(0.0005)
- while true do
- drawBuffer()
- ox, oy = cx, cy
- io.write("\27[100;101m")
- local c=io.read(1)
- if c == "\27" then
- local b = ""
- repeat
- c=io.read(1)
- b=b..c
- until c:match("%a")
- dprint(b)
- local nx, ny = b:match("%[(%d+);(%d+)")
- if nx and ny then
- mx, my = math.max(mx, tonumber(nx)), math.max(my, tonumber(ny)-2)
- drawBuffer(true)
- end
- end
- if mode == "c" then
- if c == "q" then
- io.write("\27[0m\27[2J\27[H")
- break
- elseif c == "h" then
- buffer.x = buffer.x - mult
- elseif c == "l" then
- buffer.x = buffer.x + mult
- elseif c == "j" then
- buffer.y = buffer.y + mult
- elseif c == "k" then
- buffer.y = buffer.y - mult
- elseif c == "d" then
- for i = 1, mult do
- table.remove(buffer,buffer.y)
- end
- drawBuffer(true)
- elseif c == "i" or c == "\t" then
- mode = "i"
- elseif c == "a" then
- buffer.x = buffer.x + 1
- mode = "i"
- elseif c == ":" then
- io.write("\27[1;999H\27[2K")
- ed.interactive(buffer)
- drawBuffer(true)
- elseif c == "w" then
- buffer:save()
- elseif c:match("%d") then
- multstr = multstr .. c
- mult = tonumber(multstr)
- end
- if c:match("%D") then
- multstr = ""
- mult = 1
- end
- else
- if c == "\t" then
- mode = "c"
- elseif c == "\8" and buffer.x == 1 and buffer.y > 1 then
- local lblen = buffer[buffer.y-1]:len()
- buffer[buffer.y-1] = buffer[buffer.y-1] .. table.remove(buffer,buffer.y)
- buffer.x, buffer.y = lblen+1, buffer.y - 1
- drawBuffer(true)
- elseif c == "\8" then
- buffer[buffer.y] = buffer[buffer.y]:sub(1,buffer.x - 2)..buffer[buffer.y]:sub(buffer.x)
- buffer.x = buffer.x - 1
- else
- buffer[buffer.y] = buffer[buffer.y]:sub(1,buffer.x-1)..c..buffer[buffer.y]:sub(buffer.x)
- buffer.x = buffer.x + 1
- local fh,sh = buffer[buffer.y]:match("(.*)\n(.*)")
- if fh and sh then
- buffer[buffer.y] = fh
- table.insert(buffer,buffer.y+1,sh)
- buffer.x, buffer.y = 1, buffer.y + 1
- drawBuffer(true)
- end
- end
- end
- buffer:checkCursor()
- local ax, amx = buffer.x + 5, mx - 5
- if cy + my < buffer.y + 3 then
- cy = math.min(#buffer-my,buffer.y + 6 - my)
- end
- if cy + 3 > buffer.y then
- cy = math.max(1,buffer.y - 6)
- end
- if buffer.x + 5 > cx + mx - 4 then
- cx = math.max(1,(buffer.x + 6) - (mx - 6))
- end
- if buffer.x < cx + 3 then
- cx = math.max(1,buffer.x - 6)
- end
- end
- end
-
- return ed
|