#!/usr/bin/lua function setup_screen() os.execute("stty cbreak -echo") end function restore_screen() os.execute("stty -cbreak echo") end function termout(s) io.stdout:write(s) end function reset_terminal() termout("\27c") end function home_cursor() termout("\27[H") end function read_file(filename) return { data = file_contents(filename) , filename = filename , eobp = eobp , kill_line = kill_line , redraw = redraw_buf , execute = execute , save = save , backup = backup_buf , pos = 0 , forward = forward_buf , delete = delete_in_buf , insert = insert_in_buf } end function file_contents(filename) local fd = io.open(filename, "r") local data = fd:read("*all") fd:close() return data end function redraw_buf(self) reset_terminal() termout(string.sub(self.data, 1, self.pos - 1 ) )--  ) termout("|") termout(string.sub(self.data, self.pos)) end function execute(self, command) if command == "\2" then self:backup() -- control B elseif command == "\6" then self:forward() -- control F elseif command == "\127" then self:delete() -- delete character elseif command == "\11" then self:kill_line() -- control K else self:insert(command) end end function kill_line(self) while not self:eobp() and string.sub(self.data, self.pos, 1) ~= "\n" do self:forward() self:delete() end if not self:eobp() then self:forward(); self:delete() end end function eobp(self) return self.pos == #(self.data) + 1 end function save(self) local fd = io.open(self.filename, "w") fd:write(self.data) fd:close() end function backup_buf(self) if self.pos < 3 then self.pos = 1 else self.pos = self.pos - 1 end end function forward_buf(self) if self.pos > #(self.data) then self.pos = #(self.data) + 1 else self.pos = self.pos + 1 end end function delete_in_buf(self) if self.pos > 1 then self.data = string.sub(self.data, 1, self.pos - 2) .. string.sub(self.data, self.pos) self.pos = self.pos - 1 end end function insert_in_buf(self, character) self.data = string.sub(self.data, 1, self.pos - 1) .. character .. string.sub(self.data, self.pos) self.pos = self.pos + 1 end function editormain(filename) local buf = read_file(filename) setup_editor() while 1 do buf:redraw() local command = read_command() if command == exit_command then break end buf:execute(command) end buf:save() end function read_file(filename) return { data = file_contents(filename) , filename = filename , eobp = eobp , kill_line = kill_line , redraw = redraw_buf , execute = execute , save = save , backup = backup_buf , pos = 0 , forward = forward_buf , delete = delete_in_buf , insert = insert_in_buf } end function setup_editor() setup_screen() reset_terminal() end function read_command() return io.stdin:read(1) end exit_command = "\24" local filename = ... assert(filename) editormain(filename) restore_screen()