Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Get file to edit
- local tArgs = { ... }
- if #tArgs == 0 then
- print( "Usage: edit <path>" )
- return
- end
- local isColor = false
- -- Error checking
- local sPath = shell.resolve( tArgs[1] )
- local bReadOnly = false --fs.isReadOnly( sPath )
- if fs.exists( sPath ) and fs.isDir( sPath ) then
- print( "Cannot edit a directory." )
- return
- end
- local gpu = component.gpu
- local x,y = 1,1
- local w,h = gpu.getResolution()
- local scrollX, scrollY = 0,0
- local tLines = {}
- local bRunning = true
- local mColors = {
- black = 0x000000;
- white = 0xFFFFFF;
- yellow = 0xF2DD3A;
- green = 0x1B6320;
- red = 0xFF0000;
- }
- -- Minecraft key code bindings
- -- See http://www.minecraftwiki.net/wiki/Key_codes for more info
- local nothing = 42
- local tKeys = {
- nil, "one", "two", "three", "four", -- 1
- "five", "six", "seven", "eight", "nine", -- 6
- "zero", "minus", "equals", "backspace","tab", -- 11
- "q", "w", "e", "r", "t", -- 16
- "y", "u", "i", "o", "p", -- 21
- "leftBracket","rightBracket","enter","leftCtrl","a", -- 26
- "s", "d", "f", "g", "h", -- 31
- "j", "k", "l", "semiColon","apostrophe", -- 36
- "grave", "leftShift","backslash","z", "x", -- 41
- "c", "v", "b", "n", "m", -- 46
- "comma", "period", "slash", "rightShift","multiply", -- 51
- "leftAlt", "space", "capsLock", "f1", "f2", -- 56
- "f3", "f4", "f5", "f6", "f7", -- 61
- "f8", "f9", "f10", "numLock", "scollLock", -- 66
- "numPad7", "numPad8", "numPad9", "numPadSubtract","numPad4", -- 71
- "numPad5", "numPad6", "numPadAdd","numPad1", "numPad2", -- 76
- "numPad3", "numPad0", "numPadDecimal",nil, nil, -- 81
- nil, "f11", "f12", nil, nil, -- 86
- nil, nil, nil, nil, nil, -- 91
- nil, nil, nil, nil, "f13", -- 96
- "f14", "f15", nil, nil, nil, -- 101
- nil, nil, nil, nil, nil, -- 106
- nil, "kana", nil, nil, nil, -- 111
- nil, nil, nil, nil, nil, -- 116
- "convert", nil, "noconvert",nil, "yen", -- 121
- nil, nil, nil, nil, nil, -- 126
- nil, nil, nil, nil, nil, -- 131
- nil, nil, nil, nil, nil, -- 136
- "numPadEquals",nil, nil, "cimcumflex","at", -- 141
- "colon", "underscore","kanji", "stop", "ax", -- 146
- nil, "numPadEnter","rightCtrl",nil, nil, -- 151
- nil, nil, nil, nil, nil, -- 156
- nil, nil, nil, nil, nil, -- 161
- nil, nil, nil, nil, nil, -- 166
- nil, nil, nil, nil, nil, -- 171
- nil, nil, nil, "numPadComma",nil, -- 176
- "numPadDivide",nil, nil, "rightAlt", nil, -- 181
- nil, nil, nil, nil, nil, -- 186
- nil, nil, nil, nil, nil, -- 191
- nil, "pause", nil, "home", "up", -- 196
- "pageUp", nil, "left", nil, "right", -- 201
- nil, "end", "down", "pageDown", "insert", -- 206
- "delete" -- 211
- }
- local keys = {}
- for nKey, sKey in pairs( tKeys ) do
- keys[sKey] = nKey
- end
- keys["return"] = keys.enter
- -- mColors
- local highlightColour, keywordColour, commentColour, textColour, bgColour
- if isColor then
- bgColour = mColors.black
- textColour = mColors.white
- highlightColour = mColors.yellow
- keywordColour = mColors.yellow
- commentColour = mColors.green
- stringColour = mColors.red
- else
- bgColour = mColors.black
- textColour = mColors.white
- highlightColour = mColors.white
- keywordColour = mColors.white
- commentColour = mColors.white
- stringColour = mColors.white
- end
- -- Menus
- local bMenu = false
- local nMenuItem = 1
- local tMenuItems
- if bReadOnly then
- tMenuItems = { "Exit", "Print" }
- else
- tMenuItems = { "Save", "Exit", "Print" }
- end
- local sStatus = "Press Ctrl to access menu"
- local function load( _sPath )
- tLines = {}
- if fs.exists( _sPath ) then
- local file = io.open( _sPath, "r" )
- local sLine = file:read()
- while sLine do
- table.insert( tLines, sLine )
- sLine = file:read()
- end
- file:close()
- end
- if #tLines == 0 then
- table.insert( tLines, "" )
- end
- end
- local function save( _sPath )
- -- Create intervening folder
- local sDir = sPath:sub(1, sPath:len() - fs.name(sPath):len() )
- if not fs.exists( sDir ) then
- fs.makeDirectory( sDir )
- end
- -- Save
- local file = nil
- local function innerSave()
- file = io.open( _sPath, "w" )
- if file then
- for n, sLine in ipairs( tLines ) do
- file:write( sLine .. "\n" )
- end
- else
- error( "Failed to open ".._sPath )
- end
- end
- local ok = pcall( innerSave )
- if file then
- file:close()
- end
- return ok
- end
- local tKeywords = {
- ["and"] = true,
- ["break"] = true,
- ["do"] = true,
- ["else"] = true,
- ["elseif"] = true,
- ["end"] = true,
- ["false"] = true,
- ["for"] = true,
- ["function"] = true,
- ["if"] = true,
- ["in"] = true,
- ["local"] = true,
- ["nil"] = true,
- ["not"] = true,
- ["or"] = true,
- ["repeat"] = true,
- ["return"] = true,
- ["then"] = true,
- ["true"] = true,
- ["until"]= true,
- ["while"] = true,
- }
- local function tryWrite( sLine, regex, colour )
- local match = string.match( sLine, regex )
- if match then
- if type(colour) == "number" then
- gpu.setForeground( colour )
- else
- gpu.setForeground( colour(match) )
- end
- term.write( match )
- gpu.setForeground( textColour )
- return string.sub( sLine, string.len(match) + 1 )
- end
- return nil
- end
- local function writeHighlighted( sLine )
- while string.len(sLine) > 0 do
- sLine =
- tryWrite( sLine, "^%-%-%[%[.-%]%]", commentColour ) or
- tryWrite( sLine, "^%-%-.*", commentColour ) or
- tryWrite( sLine, "^\".-[^\\]\"", stringColour ) or
- tryWrite( sLine, "^\'.-[^\\]\'", stringColour ) or
- tryWrite( sLine, "^%[%[.-%]%]", stringColour ) or
- tryWrite( sLine, "^[%w_]+", function( match )
- if tKeywords[ match ] then
- return keywordColour
- end
- return textColour
- end ) or
- tryWrite( sLine, "^[^%w_]", textColour )
- end
- end
- local function redrawText()
- for y=1,h-1 do
- term.setCursor( 1 - scrollX, y )
- term.clearLine()
- local sLine = tLines[ y + scrollY ]
- if sLine ~= nil then
- writeHighlighted( sLine )
- end
- end
- term.setCursor( x - scrollX, y - scrollY )
- end
- local function redrawLine(_nY)
- local sLine = tLines[_nY]
- term.setCursor( 1 - scrollX, _nY - scrollY )
- term.clearLine()
- writeHighlighted( sLine )
- term.setCursor( x - scrollX, _nY - scrollY )
- end
- local function redrawMenu()
- term.setCursor( 1, h )
- term.clearLine()
- local sLeft, sRight
- local nLeftColour, nLeftHighlight1, nLeftHighlight2
- if bMenu then
- local sMenu = ""
- for n,sItem in ipairs( tMenuItems ) do
- if n == nMenuItem then
- nLeftHighlight1 = sMenu:len() + 1
- nLeftHighlight2 = sMenu:len() + sItem:len() + 2
- end
- sMenu = sMenu.." "..sItem.." "
- end
- sLeft = sMenu
- nLeftColour = textColour
- else
- sLeft = sStatus
- nLeftColour = highlightColour
- end
- -- Left goes last so that it can overwrite the line numbers.
- sRight = "Ln "..y
- gpu.setForeground( highlightColour )
- term.setCursor( w-sRight:len() + 1, h )
- term.write(sRight)
- sRight = tostring(y)
- gpu.setForeground( textColour )
- term.setCursor( w-sRight:len() + 1, h )
- term.write(sRight)
- if sLeft then
- term.setCursor( 1, h )
- gpu.setForeground( nLeftColour )
- term.write(sLeft)
- if nLeftHighlight1 then
- gpu.setForeground( highlightColour )
- term.setCursor( nLeftHighlight1, h )
- term.write( "[" )
- term.setCursor( nLeftHighlight2, h )
- term.write( "]" )
- end
- gpu.setForeground( textColour )
- end
- -- Cursor highlights selection
- term.setCursor( x - scrollX, y - scrollY )
- end
- local tMenuFuncs = {
- Save=function()
- if bReadOnly then
- sStatus = "Access denied"
- else
- local ok, err = save( sPath )
- if ok then
- sStatus="Saved to "..sPath
- else
- sStatus="Error saving to "..sPath
- end
- end
- redrawMenu()
- end,
- Print=function()
- --[[
- local sPrinterSide = nil
- for n,sName in ipairs(peripheral.getNames()) do
- if peripheral.isPresent(sName) and peripheral.getType(sName) == "printer" then
- sPrinterSide = sName
- break
- end
- end
- if not sPrinterSide then
- sStatus = "No printer attached"
- return
- end
- local nPage = 0
- local sName = fs.getName( sPath )
- local printer = peripheral.wrap(sPrinterSide)
- if printer.getInkLevel() < 1 then
- sStatus = "Printer out of ink"
- return
- elseif printer.getPaperLevel() < 1 then
- sStatus = "Printer out of paper"
- return
- end
- local terminal = {
- getCursorPos = printer.getCursorPos,
- setCursorPos = printer.setCursorPos,
- getSize = printer.getPageSize,
- write = printer.write,
- }
- terminal.scroll = function()
- if nPage == 1 then
- printer.setPageTitle( sName.." (page "..nPage..")" )
- end
- while not printer.newPage() do
- if printer.getInkLevel() < 1 then
- sStatus = "Printer out of ink, please refill"
- elseif printer.getPaperLevel() < 1 then
- sStatus = "Printer out of paper, please refill"
- else
- sStatus = "Printer output tray full, please empty"
- end
- term.restore()
- redrawMenu()
- term.redirect( terminal )
- local timer = os.startTimer(0.5)
- sleep(0.5)
- end
- nPage = nPage + 1
- if nPage == 1 then
- printer.setPageTitle( sName )
- else
- printer.setPageTitle( sName.." (page "..nPage..")" )
- end
- end
- bMenu = false
- term.redirect( terminal )
- local ok, error = pcall( function()
- term.scroll()
- for n, sLine in ipairs( tLines ) do
- print( sLine )
- end
- end )
- term.restore()
- if not ok then
- print( error )
- end
- while not printer.endPage() do
- sStatus = "Printer output tray full, please empty"
- redrawMenu()
- sleep( 0.5 )
- end
- bMenu = true
- if nPage > 1 then
- sStatus = "Printed "..nPage.." Pages"
- else
- sStatus = "Printed 1 Page"
- end]]
- sStatus = "Printing disabled in OC port"
- redrawMenu()
- end,
- Exit=function()
- bRunning = false
- end
- }
- local function doMenuItem( _n )
- tMenuFuncs[tMenuItems[_n]]()
- if bMenu then
- bMenu = false
- term.setCursorBlink( true )
- end
- redrawMenu()
- end
- local function setCursort( x, y )
- local screenX = x - scrollX
- local screenY = y - scrollY
- local bRedraw = false
- if screenX < 1 then
- scrollX = x - 1
- screenX = 1
- bRedraw = true
- elseif screenX > w then
- scrollX = x - w
- screenX = w
- bRedraw = true
- end
- if screenY < 1 then
- scrollY = y - 1
- screenY = 1
- bRedraw = true
- elseif screenY > h-1 then
- scrollY = y - (h-1)
- screenY = h-1
- bRedraw = true
- end
- if bRedraw then
- redrawText()
- end
- term.setCursor( screenX, screenY )
- -- Statusbar now pertains to menu, it would probably be safe to redraw the menu on every key event.
- redrawMenu()
- end
- -- Actual program functionality begins
- load(sPath)
- gpu.setBackground( bgColour )
- term.clear()
- term.setCursor(x,y)
- term.setCursorBlink( true )
- redrawText()
- redrawMenu()
- -- Handle input
- while bRunning do
- local sEvent, id, paramc, param, param1 = event.pull()
- if sEvent == "key_down" then
- if param == keys.up then
- -- Up
- if not bMenu then
- if y > 1 then
- -- Move cursor up
- y = y - 1
- x = math.min( x, string.len( tLines[y] ) + 1 )
- setCursort( x, y )
- end
- end
- elseif param == keys.down then
- -- Down
- if not bMenu then
- -- Move cursor down
- if y < #tLines then
- y = y + 1
- x = math.min( x, string.len( tLines[y] ) + 1 )
- setCursort( x, y )
- end
- end
- elseif param == keys.tab then
- -- Tab
- if not bMenu and not bReadOnly then
- -- Indent line
- tLines[y]=" "..tLines[y]
- x = x + 2
- setCursort( x, y )
- redrawLine(y)
- end
- elseif param == keys.pageUp then
- -- Page Up
- if not bMenu then
- -- Move up a page
- local sx,sy=term.getSize()
- y=y-sy-1
- if y<1 then y=1 end
- x = math.min( x, string.len( tLines[y] ) + 1 )
- setCursort( x, y )
- end
- elseif param == keys.pageDown then
- -- Page Down
- if not bMenu then
- -- Move down a page
- local sx,sy=term.getSize()
- if y<#tLines-sy-1 then
- y = y+sy-1
- else
- y = #tLines
- end
- x = math.min( x, string.len( tLines[y] ) + 1 )
- setCursort( x, y )
- end
- elseif param == keys.home then
- -- Home
- if not bMenu then
- -- Move cursor to the beginning
- x=1
- setCursort(x,y)
- end
- elseif param == keys["end"] then
- -- End
- if not bMenu then
- -- Move cursor to the end
- x = string.len( tLines[y] ) + 1
- setCursort(x,y)
- end
- elseif param == keys.left then
- -- Left
- if not bMenu then
- if x > 1 then
- -- Move cursor left
- x = x - 1
- elseif x==1 and y>1 then
- x = string.len( tLines[y-1] ) + 1
- y = y - 1
- end
- setCursort( x, y )
- else
- -- Move menu left
- nMenuItem = nMenuItem - 1
- if nMenuItem < 1 then
- nMenuItem = #tMenuItems
- end
- redrawMenu()
- end
- elseif param == keys.right then
- -- Right
- if not bMenu then
- if x < string.len( tLines[y] ) + 1 then
- -- Move cursor right
- x = x + 1
- elseif x==string.len( tLines[y] ) + 1 and y<#tLines then
- x = 1
- y = y + 1
- end
- setCursort( x, y )
- else
- -- Move menu right
- nMenuItem = nMenuItem + 1
- if nMenuItem > #tMenuItems then
- nMenuItem = 1
- end
- redrawMenu()
- end
- elseif param == keys.delete then
- -- Delete
- if not bMenu and not bReadOnly then
- if x < string.len( tLines[y] ) + 1 then
- local sLine = tLines[y]
- tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)
- redrawLine(y)
- elseif y<#tLines then
- tLines[y] = tLines[y] .. tLines[y+1]
- table.remove( tLines, y+1 )
- redrawText()
- redrawMenu()
- end
- end
- elseif param == keys.backspace then
- -- Backspace
- if not bMenu and not bReadOnly then
- if x > 1 then
- -- Remove character
- local sLine = tLines[y]
- tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)
- redrawLine(y)
- x = x - 1
- setCursort( x, y )
- elseif y > 1 then
- -- Remove newline
- local sPrevLen = string.len( tLines[y-1] )
- tLines[y-1] = tLines[y-1] .. tLines[y]
- table.remove( tLines, y )
- redrawText()
- x = sPrevLen + 1
- y = y - 1
- setCursort( x, y )
- end
- end
- elseif param == keys.enter then
- -- Enter
- if not bMenu and not bReadOnly then
- -- Newline
- local sLine = tLines[y]
- local _,spaces=string.find(sLine,"^[ ]+")
- if not spaces then
- spaces=0
- end
- tLines[y] = string.sub(sLine,1,x-1)
- table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )
- redrawText()
- x = spaces+1
- y = y + 1
- setCursort( x, y )
- elseif bMenu then
- -- Menu selection
- doMenuItem( nMenuItem )
- end
- elseif param == keys.leftCtrl or param == keys.rightCtrl then
- -- Menu toggle
- bMenu = not bMenu
- if bMenu then
- term.setCursorBlink( false )
- nMenuItem = 1
- else
- term.setCursorBlink( true )
- end
- redrawMenu()
- elseif paramc and paramc ~= 0 then
- param = string.char(paramc)
- if param then
- if not bMenu and not bReadOnly then
- -- Input text
- local sLine = tLines[y]
- tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
- redrawLine(y)
- x = x + string.len( param )
- setCursort( x, y )
- elseif bMenu then
- -- Select menu items
- for n,sMenuItem in ipairs( tMenuItems ) do
- if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then
- doMenuItem( n )
- break
- end
- end
- end
- end
- end
- os.sleep(0.01)
- --[[elseif sEvent == "mouse_click" then
- if not bMenu then
- if param == 1 then
- -- Left click
- local cx,cy = param2, param3
- if cy < h then
- y = math.min( math.max( scrollY + cy, 1 ), #tLines )
- x = math.min( math.max( scrollX + cx, 1 ), string.len( tLines[y] ) + 1 )
- setCursort( x, y )
- end
- end
- end
- elseif sEvent == "mouse_scroll" then
- if not bMenu then
- if param == -1 then
- -- Scroll up
- if scrollY > 0 then
- -- Move cursor up
- scrollY = scrollY - 1
- redrawText()
- end
- elseif param == 1 then
- -- Scroll down
- local nMaxScroll = #tLines - (h-1)
- if scrollY < nMaxScroll then
- -- Move cursor down
- scrollY = scrollY + 1
- redrawText()
- end
- end
- end]]
- end
- end
- -- Cleanup
- term.clear()
- term.setCursorBlink( false )
- term.setCursor( 1, 1 )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement