Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --Included libs:
- --delegate (by me)
- local function delegate()
- return setmetatable({func = {},
- add = function(self,func)
- checkTypes({self,func},{"table","function"})
- self.func[#self.func+1] = func
- end,
- sub = function(self,func)
- checkTypes({self,func},{"table","function"})
- for i=1,#self.func do
- local v = self.func[i]
- if v == func then
- table.remove(self.func,i)
- end
- end
- end,
- },
- {__call = function(tbl,...)
- if type(tbl.func) == "table" then
- local c,r = 0,{}
- for k,v in pairs(tbl.func) do
- if type(v) == "function" then
- c = c+1
- r[c] = {pcall(v,...)}
- end
- end
- return c,r
- end
- end,
- __add = function(self,func)
- self:add(func)
- end,
- __sub = function(self,func)
- self:sub(func)
- end,
- })
- end
- --Setup vars:
- --general vars
- local filepath = ""
- --display vars
- local scroll = {0,0}
- local showncolumncount = 10
- local w,h = term.getSize()
- local gridw, gridh = w-2, h-2 --why not put this here :P
- local gridx, gridy = 4,2
- local defaultColumnWidth = 10
- --selection vars
- local selected = {1,1} --selected cell position
- local endselection = {}
- local multiselect = false
- --file content vars
- local grid = {}
- local columnWidths = {}
- --copy/paste vars
- local clipboard = {}
- --theme vars
- local theme = term.isColor() and {
- default = {colors.white, colors.black},
- selected = {colors.green, colors.white},
- multiselected = {colors.lime, colors.black},
- menu = {colors.green, colors.white},
- border = {colors.lightGray, colors.black}
- } or {
- default = {colors.black, colors.white},
- selected = {colors.white, colors.black},
- multiselected = {colors.gray, colors.black},
- menu = {colors.white, colors.black},
- border = {colors.lightGray, colors.black}
- }
- --Handle args:
- local tArgs = {...}
- if #tArgs < 1 then --not enough args
- print[[
- Usage:
- speadersheet <filename>
- ]]
- error("",0)
- end
- filepath = tArgs[1]
- --Local functions:
- local function selectColors(name) --selects colors, args: name of theme
- local cols = theme[name]
- term.setBackgroundColor(cols[1])
- term.setTextColor(cols[2])
- end
- local function redrawGrid() --redraws grid and bottom line
- --this is the function that will need lots of optimization probably
- local drawing = {scroll[1], scroll[2]} --which cell are we drawing (to get the content)
- for y=gridy, gridh + gridy - 1 do
- drawing[2] = drawing[2] + 1
- drawing[1] = scroll[1]
- term.setCursorPos(gridx, y)
- for i=1,showncolumncount do
- drawing[1] = drawing[1] + 1
- local cwidth = columnWidths[drawing[1]] or defaultColumnWidth
- selectColors((selected[1] == drawing[1] and selected[2] == drawing[2]) and "selected" or (multiselect and (selected[1] >= drawing[1] and selected[2] >= drawing[2]) and (endselection[1] <= drawing[1] and endselection[2] <= drawing[2])) and "multiselected" or "default")
- local text = grid[drawing[1]] and grid[drawing[1]][drawing[2]] and grid[drawing[1]][drawing[2]] or ""
- term.write(text .. (#text < cwidth - 1 and string.rep(" ",(cwidth - 1) - #text) or ""))
- if selected[1] == drawing[1] and selected[2] == drawing[2] then
- local oldx,oldy = term.getCursorPos()
- term.setCursorPos(1,h)
- selectColors("menu")
- --This is repeated because of functions later
- local realtext = grid[drawing[1]] and grid[drawing[1]][drawing[2]] and grid[drawing[1]][drawing[2]] or ""
- term.write(realtext .. (#realtext < w and string.rep(" ",w - #realtext) or ""))
- term.setCursorPos(oldx,oldy)
- end
- selectColors("border")
- term.write(" ")
- end
- end
- end
- local function redrawMenu() --redraws column and row numbers
- --redraw top column numbers
- do
- local drawing = scroll[1]
- term.setCursorPos(gridx, 1)
- selectColors("menu")
- term.clearLine()
- term.setCursorPos(gridx, 1)
- for i=1,showncolumncount do
- drawing = drawing + 1
- local cwidth = columnWidths[drawing] or defaultColumnWidth
- term.write(drawing)
- term.write(string.rep(" ",cwidth - #tostring(drawing)))
- end
- end
- --redraw line numbers
- local drawing = scroll[2]
- for y=gridy, gridh + gridy - 1 do
- drawing = drawing + 1
- term.setCursorPos(1, y)
- term.write(tostring(drawing) .. string.rep(" ",3 - #tostring(drawing)))
- end
- end
- local function checkScroll() --scrolls if needed
- local scrolled = false
- --horizontal:
- local cx = gridx
- local count = 0
- local drawing = scroll[1]
- for i=1,w do -- count how many columns are on screen
- drawing = drawing + 1
- local cwidth = columnWidths[drawing] or defaultColumnWidth
- cx = cx + cwidth
- count = count + 1
- if cx >= w then break end
- end
- showncolumncount = count
- while selected[1] - scroll[1] < 1 do
- scroll[1] = scroll[1] - 1
- scrolled = true
- end
- while selected[1] > scroll[1] + count do
- scroll[1] = scroll[1] + 1
- scrolled = true
- end
- --vertical:
- while selected[2] - scroll[2] < 1 do
- scroll[2] = scroll[2] - 1
- scrolled = true
- end
- while selected[2] > scroll[2] + gridh do
- scroll[2] = scroll[2] + 1
- scrolled = true
- end
- if scrolled then
- redrawGrid()
- redrawMenu()
- end
- end
- local function save() --saves persistant data
- local h = fs.open(filepath,"w")
- local cont = textutils.serialize{
- grid,
- selected,
- endselection,
- multiselect,
- columnWidths,
- showhelp,
- scroll
- }
- h.write(cont)
- h.close()
- end
- local function reload() --loads persistant data
- if fs.exists(filepath) then
- local h = fs.open(filepath,"r")
- local cont = textutils.unserialize(h.readAll())
- h.close()
- grid = cont[1] or {}
- selected = cont[2] or {1,1}
- endselection = cont[3] or {1,1}
- multiselect = cont[4]
- columnWidths = cont[5] or {}
- showhelp = cont[6] or true
- scroll = cont[7] or {0,0}
- end
- end
- local function cancel() --cancels multiselection
- if multiselect then
- multiselect = false
- end
- endselection = {selected[1], selected[2]}
- end
- local function initMultiselect() --inits multiselection if needed
- if not multiselect then
- multiselect = true
- endselection = {selected[1], selected[2]}
- end
- end
- local function convertSelection() -- converts multi/single selection to a smaller sub grid and returns it
- local subx, suby = 1,1
- local subgrid = {}
- for x = endselection[1], selected[1] do
- subgrid[subx] = {}
- for y = endselection[2], selected[2] do
- subgrid[subx][suby] = grid[x] and grid[x][y] and grid[x][y] or ""
- suby = suby + 1
- end
- suby = 1
- subx = subx + 1
- end
- return subgrid
- end
- local function pasteSubgrid(subgrid, x, y) --pastes subgrid in main grid
- for i=#subgrid, 1, -1 do
- local line = subgrid[i]
- for j = #line, 1, -1 do
- local cell = line[j]
- if not grid[x + i - 1] then
- grid[x + i - 1] = {}
- end
- grid[x + i - 1][y + j - 1] = cell
- end
- end
- end
- local function deleteSelection()
- for x = endselection[1], selected[1] do
- for y = endselection[2], selected[2] do
- if grid[x] then
- grid[x][y] = ""
- end
- end
- end
- end
- reload()
- --Key-event table:
- local handler = {
- --[[
- movement:
- arrow keys = move
- p/l = multiselect (move right bottom corner right/down)
- enter = edit
- home = first column
- end = first row
- page up = page up
- page down = page down
- general:
- s = save
- q = exit
- copy/paste:
- c = copy
- v = paste
- x = cut
- ]]
- key = {
- [keys.up] = function() cancel() selected[2] = selected[2] > 1 and selected[2] - 1 or 1 redrawGrid() end;
- [keys.down] = function() cancel() selected[2] = selected[2] + 1 redrawGrid() end;
- [keys.left] = function() cancel() selected[1] = selected[1] > 1 and selected[1] - 1 or 1 redrawGrid() end;
- [keys.right] = function() cancel() selected[1] = selected[1] + 1 redrawGrid() end;
- [keys.home] = function() cancel() selected[1] = 1 redrawGrid() end;
- [keys["end"]] = function() cancel() selected[2] = 1 redrawGrid() end;
- [keys.pageUp] = function() cancel() selected[2] = selected[2] > gridh-1 and selected[2] - (gridh-1) or 1 redrawGrid() end;
- [keys.pageDown] = function() cancel() selected[2] = selected[2] + gridh - 1 redrawGrid() end;
- [keys.p] = function() initMultiselect() selected[1] = selected[1] + 1 redrawGrid() end;
- [keys.l] = function() initMultiselect() selected[2] = selected[2] + 1 redrawGrid() end;
- [keys.enter] = function()
- term.setCursorPos(1,h)
- selectColors("menu")
- term.clearLine()
- term.setCursorPos(1,h)
- if not grid[selected[1]] then
- grid[selected[1]] = {}
- end
- grid[selected[1]][selected[2]] = read()
- redrawGrid()
- redrawMenu()
- end;
- [keys.s] = function()
- save()
- end;
- [keys.q] = function()
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- term.setCursorPos(1,1)
- sleep(0)
- error("",0)
- end;
- [keys.c] = function()
- clipboard = convertSelection()
- end;
- [keys.v] = function()
- pasteSubgrid(clipboard, selected[1], selected[2])
- redrawGrid()
- end;
- [keys.x] = function()
- clipboard = convertSelection()
- deleteSelection()
- redrawGrid()
- end;
- }
- }
- --Main loop:
- term.clear()
- redrawGrid()
- redrawMenu()
- while true do
- local event,param = os.pullEvent()
- if handler[event] and handler[event][param] then
- handler[event][param]()
- checkScroll()
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement