View difference between Paste ID: 5Xqu44zK and EAE1V9Ty
SHOW: | | - or go back to the newest paste.
1
-- Get file to edit
2
local tArgs = { ... }
3
if #tArgs == 0 then
4
	print( "Usage: edit <path>" )
5
	return
6
end
7
8
mon = peripheral.wrap("right")
9
10
-- Error checking
11
local sPath = shell.resolve( tArgs[1] )
12
local bReadOnly = fs.isReadOnly( sPath )
13
if fs.exists( sPath ) and fs.isDir( sPath ) then
14
	print( "Cannot edit a directory." )
15
	return
16
end
17-
local w,h = term.getSize()
17+
18
local x,y = 1,1
19
local w,h = mon.getSize()
20
local scrollX, scrollY = 0,0
21
22
local tLines = {}
23
local bRunning = true
24
25-
if term.isColour() then
25+
26
local highlightColour, keywordColour, commentColour, textColour, bgColour
27
if mon.isColour() then
28
	bgColour = colours.black
29
	textColour = colours.white
30
	highlightColour = colours.yellow
31
	keywordColour = colours.yellow
32
	commentColour = colours.green
33
	stringColour = colours.red
34
else
35
	bgColour = colours.black
36
	textColour = colours.white
37
	highlightColour = colours.white
38
	keywordColour = colours.white
39
	commentColour = colours.white
40
	stringColour = colours.white
41
end
42
43
-- Menus
44
local bMenu = false
45
local nMenuItem = 1
46
local tMenuItems
47
if bReadOnly then
48
	tMenuItems = { "Exit", "Print" }
49
else
50
	tMenuItems = { "Save", "Exit", "Print" }
51
end
52
	
53
local sStatus = "Press Ctrl to access menu"
54
55
local function load( _sPath )
56
	tLines = {}
57
	if fs.exists( _sPath ) then
58
		local file = io.open( _sPath, "r" )
59
		local sLine = file:read()
60
		while sLine do
61
			table.insert( tLines, sLine )
62
			sLine = file:read()
63
		end
64
		file:close()
65
	end
66
	
67
	if #tLines == 0 then
68
		table.insert( tLines, "" )
69
	end
70
end
71
72
local function save( _sPath )
73
	-- Create intervening folder
74
	local sDir = sPath:sub(1, sPath:len() - fs.getName(sPath):len() )
75
	if not fs.exists( sDir ) then
76
		fs.makeDir( sDir )
77
	end
78
79
	-- Save
80
	local file = nil
81
	local function innerSave()
82
		file = fs.open( _sPath, "w" )
83
		if file then
84
			for n, sLine in ipairs( tLines ) do
85
				file.write( sLine .. "\n" )
86
			end
87
		else
88
			error( "Failed to open ".._sPath )
89
		end
90
	end
91
	
92
	local ok = pcall( innerSave )
93
	if file then 
94
		file.close()
95
	end
96
	return ok
97
end
98
99
local tKeywords = {
100
	["and"] = true,
101
	["break"] = true,
102
	["do"] = true,
103
	["else"] = true,
104
	["elseif"] = true,
105
	["end"] = true,
106
	["false"] = true,
107
	["for"] = true,
108
	["function"] = true,
109
	["if"] = true,
110
	["in"] = true,
111
	["local"] = true,
112
	["nil"] = true,
113
	["not"] = true,
114
	["or"] = true,
115
	["repeat"] = true,
116
	["return"] = true,
117
	["then"] = true,
118
	["true"] = true,
119
	["until"]= true,
120
	["while"] = true,
121
}
122
123
local function tryWrite( sLine, regex, colour )
124
	local match = string.match( sLine, regex )
125-
			term.setTextColour( colour )
125+
126
		if type(colour) == "number" then
127-
			term.setTextColour( colour(match) )
127+
			mon.setTextColour( colour )
128
		else
129-
		term.write( match )
129+
			mon.setTextColour( colour(match) )
130-
		term.setTextColour( textColour )
130+
131
		mon.write( match )
132
		mon.setTextColour( textColour )
133
		return string.sub( sLine, string.len(match) + 1 )
134
	end
135
	return nil
136
end
137
138
local function writeHighlighted( sLine )
139
	while string.len(sLine) > 0 do	
140
		sLine = 
141
			tryWrite( sLine, "^%-%-%[%[.-%]%]", commentColour ) or
142
			tryWrite( sLine, "^%-%-.*", commentColour ) or
143
			tryWrite( sLine, "^\".-[^\\]\"", stringColour ) or
144
			tryWrite( sLine, "^\'.-[^\\]\'", stringColour ) or
145
			tryWrite( sLine, "^%[%[.-%]%]", stringColour ) or
146
			tryWrite( sLine, "^[%w_]+", function( match )
147
				if tKeywords[ match ] then
148
					return keywordColour
149
				end
150
				return textColour
151
			end ) or
152
			tryWrite( sLine, "^[^%w_]", textColour )
153
	end
154
end
155
156-
		term.setCursorPos( 1 - scrollX, y )
156+
157-
		term.clearLine()
157+
158
		mon.setCursorPos( 1 - scrollX, y )
159
		mon.clearLine()
160
161
		local sLine = tLines[ y + scrollY ]
162
		if sLine ~= nil then
163
			writeHighlighted( sLine )
164-
	term.setCursorPos( x - scrollX, y - scrollY )
164+
165
	end
166
	mon.setCursorPos( x - scrollX, y - scrollY )
167
end
168
169-
	term.setCursorPos( 1 - scrollX, _nY - scrollY )
169+
170-
	term.clearLine()
170+
171
	mon.setCursorPos( 1 - scrollX, _nY - scrollY )
172-
	term.setCursorPos( x - scrollX, _nY - scrollY )
172+
	mon.clearLine()
173
	writeHighlighted( sLine )
174
	mon.setCursorPos( x - scrollX, _nY - scrollY )
175
end
176
177-
    term.setCursorPos( 1, h )
177+
178-
	term.clearLine()
178+
179
    mon.setCursorPos( 1, h )
180
	mon.clearLine()
181-
    term.setCursorPos( w - string.len( "Ln "..y ) + 1, h )
181+
182-
    term.setTextColour( highlightColour )
182+
183-
    term.write( "Ln " )
183+
    mon.setCursorPos( w - string.len( "Ln "..y ) + 1, h )
184-
    term.setTextColour( textColour )
184+
    mon.setTextColour( highlightColour )
185-
    term.write( y )
185+
    mon.write( "Ln " )
186
    mon.setTextColour( textColour )
187-
    term.setCursorPos( 1, h )
187+
    mon.write( y )
188
189
    mon.setCursorPos( 1, h )
190-
		term.setTextColour( textColour )
190+
191
        -- Draw menu
192
		mon.setTextColour( textColour )
193-
				term.setTextColour( highlightColour )
193+
194-
				term.write( "[" )
194+
195-
				term.setTextColour( textColour )
195+
				mon.setTextColour( highlightColour )
196-
				term.write( sItem )
196+
				mon.write( "[" )
197-
				term.setTextColour( highlightColour )
197+
				mon.setTextColour( textColour )
198-
				term.write( "]" )
198+
				mon.write( sItem )
199-
        		term.setTextColour( textColour )
199+
				mon.setTextColour( highlightColour )
200
				mon.write( "]" )
201-
				term.write( " "..sItem.." " )
201+
        		mon.setTextColour( textColour )
202
			else
203
				mon.write( " "..sItem.." " )
204
			end
205
		end
206-
        term.setTextColour( highlightColour )
206+
207-
        term.write( sStatus )
207+
208-
        term.setTextColour( textColour )
208+
        mon.setTextColour( highlightColour )
209
        mon.write( sStatus )
210
        mon.setTextColour( textColour )
211
    end
212-
	term.setCursorPos( x - scrollX, y - scrollY )
212+
213
	-- Reset cursor
214
	mon.setCursorPos( x - scrollX, y - scrollY )
215
end
216
217
local tMenuFuncs = { 
218
	Save=function()
219
		if bReadOnly then
220
			sStatus = "Access denied"
221
		else
222
			local ok, err = save( sPath )
223
			if ok then
224
				sStatus="Saved to "..sPath
225
			else
226
				sStatus="Error saving to "..sPath
227
			end
228
		end
229
		redrawMenu()
230
	end,
231
	Print=function()
232
		local printer = peripheral.find( "printer" )
233
		if not printer then
234
			sStatus = "No printer attached"
235
			return
236
		end
237
238
		local nPage = 0
239
		local sName = fs.getName( sPath )
240
		if printer.getInkLevel() < 1 then
241
			sStatus = "Printer out of ink"
242
			return
243
		elseif printer.getPaperLevel() < 1 then
244
			sStatus = "Printer out of paper"
245
			return
246-
		local screenTerminal = term.current()
246+
247-
		local printerTerminal = {
247+
248
		local screenmoninal = mon.current()
249
		local printermoninal = {
250
			getCursorPos = printer.getCursorPos,
251
			setCursorPos = printer.setCursorPos,
252
			getSize = printer.getPageSize,
253-
		printerTerminal.scroll = function()
253+
254
		}
255
		printermoninal.scroll = function()
256
			if nPage == 1 then
257
				printer.setPageTitle( sName.." (page "..nPage..")" )			
258
			end
259
			
260
			while not printer.newPage()	do
261
				if printer.getInkLevel() < 1 then
262
					sStatus = "Printer out of ink, please refill"
263
				elseif printer.getPaperLevel() < 1 then
264
					sStatus = "Printer out of paper, please refill"
265
				else
266
					sStatus = "Printer output tray full, please empty"
267-
				term.redirect( screenTerminal )
267+
268
	
269-
				term.redirect( printerTerminal )
269+
				mon.redirect( screenmoninal )
270
				redrawMenu()
271
				mon.redirect( printermoninal )
272
				
273
				local timer = os.startTimer(0.5)
274
				sleep(0.5)
275
			end
276
277
			nPage = nPage + 1
278
			if nPage == 1 then
279
				printer.setPageTitle( sName )
280
			else
281
				printer.setPageTitle( sName.." (page "..nPage..")" )
282
			end
283
		end
284-
		term.redirect( printerTerminal )
284+
285
		bMenu = false
286-
			term.scroll()
286+
		mon.redirect( printermoninal )
287
		local ok, error = pcall( function()
288
			mon.scroll()
289
			for n, sLine in ipairs( tLines ) do
290
				print( sLine )
291-
        term.redirect( screenTerminal )
291+
292
		end )
293
        mon.redirect( screenmoninal )
294
		if not ok then
295
			print( error )
296
		end
297
		
298
		while not printer.endPage() do
299
			sStatus = "Printer output tray full, please empty"
300
			redrawMenu()
301
			sleep( 0.5 )
302
		end
303
		bMenu = true
304
			
305
		if nPage > 1 then
306
			sStatus = "Printed "..nPage.." Pages"
307
		else
308
			sStatus = "Printed 1 Page"
309
		end
310
		redrawMenu()
311
	end,
312
	Exit=function()
313
		bRunning = false
314
	end
315
}
316
317
local function doMenuItem( _n )
318
	tMenuFuncs[tMenuItems[_n]]()
319-
		term.setCursorBlink( true )
319+
320
		bMenu = false
321
		mon.setCursorBlink( true )
322
	end
323
	redrawMenu()
324
end
325
326
local function setCursor( x, y )
327
	local screenX = x - scrollX
328
	local screenY = y - scrollY
329
	
330
	local bRedraw = false
331
	if screenX < 1 then
332
		scrollX = x - 1
333
		screenX = 1
334
		bRedraw = true
335
	elseif screenX > w then
336
		scrollX = x - w
337
		screenX = w
338
		bRedraw = true
339
	end
340
	
341
	if screenY < 1 then
342
		scrollY = y - 1
343
		screenY = 1
344
		bRedraw = true
345
	elseif screenY > h-1 then
346
		scrollY = y - (h-1)
347
		screenY = h-1
348
		bRedraw = true
349
	end
350
	
351
	if bRedraw then
352-
	term.setCursorPos( screenX, screenY )
352+
353
	end
354
	mon.setCursorPos( screenX, screenY )
355
	
356
	-- Statusbar now pertains to menu, it would probably be safe to redraw the menu on every key event.
357
	redrawMenu()
358
end
359
360
-- Actual program functionality begins
361-
term.setBackgroundColour( bgColour )
361+
362-
term.clear()
362+
363-
term.setCursorPos(x,y)
363+
mon.setBackgroundColour( bgColour )
364-
term.setCursorBlink( true )
364+
mon.clear()
365
mon.setCursorPos(x,y)
366
mon.setCursorBlink( true )
367
368
redrawText()
369
redrawMenu()
370
371
-- Handle input
372
while bRunning do
373
	local sEvent, param, param2, param3 = os.pullEvent()
374
	if sEvent == "key" then
375
		if param == keys.up then
376
			-- Up
377
			if not bMenu then
378
				if y > 1 then
379
					-- Move cursor up
380
					y = y - 1
381
					x = math.min( x, string.len( tLines[y] ) + 1 )
382
					setCursor( x, y )
383
				end
384
			end
385
		elseif param == keys.down then
386
			-- Down
387
			if not bMenu then
388
				-- Move cursor down
389
				if y < #tLines then
390
					y = y + 1
391
					x = math.min( x, string.len( tLines[y] ) + 1 )
392
					setCursor( x, y )
393
				end
394
			end
395
		elseif param == keys.tab then
396
			-- Tab
397
			if not bMenu and not bReadOnly then
398
				-- Indent line
399
				tLines[y]="  "..tLines[y]
400
				x = x + 2
401
				setCursor( x, y )
402
				redrawLine(y)
403
			end
404
		elseif param == keys.pageUp then
405
			-- Page Up
406
			if not bMenu then
407
				-- Move up a page
408
				if y - (h - 1) >= 1 then
409
					y = y - (h - 1)
410
				else
411
					y = 1
412
				end
413
				x = math.min( x, string.len( tLines[y] ) + 1 )
414
				setCursor( x, y )
415
			end
416
		elseif param == keys.pageDown then
417
			-- Page Down
418
			if not bMenu then
419
				-- Move down a page
420
				if y + (h - 1) <= #tLines then
421
					y = y + (h - 1)
422
				else
423
					y = #tLines
424
				end
425
				x = math.min( x, string.len( tLines[y] ) + 1 )
426
				setCursor( x, y )
427
			end
428
		elseif param == keys.home then
429
			-- Home
430
			if not bMenu then
431
				-- Move cursor to the beginning
432
				x=1
433
				setCursor(x,y)
434
			end
435
		elseif param == keys["end"] then
436
			-- End
437
			if not bMenu then
438
				-- Move cursor to the end
439
				x = string.len( tLines[y] ) + 1
440
				setCursor(x,y)
441
			end
442
		elseif param == keys.left then
443
			-- Left
444
			if not bMenu then
445
				if x > 1 then
446
					-- Move cursor left
447
					x = x - 1
448
				elseif x==1 and y>1 then
449
					x = string.len( tLines[y-1] ) + 1
450
					y = y - 1
451
				end
452
				setCursor( x, y )
453
			else
454
				-- Move menu left
455
				nMenuItem = nMenuItem - 1
456
				if nMenuItem < 1 then
457
					nMenuItem = #tMenuItems
458
				end
459
				redrawMenu()
460
			end
461
		elseif param == keys.right then
462
			-- Right
463
			if not bMenu then
464
				if x < string.len( tLines[y] ) + 1 then
465
					-- Move cursor right
466
					x = x + 1
467
				elseif x==string.len( tLines[y] ) + 1 and y<#tLines then
468
					x = 1
469
					y = y + 1
470
				end
471
				setCursor( x, y )
472
			else
473
				-- Move menu right
474
				nMenuItem = nMenuItem + 1
475
				if nMenuItem > #tMenuItems then
476
					nMenuItem = 1
477
				end
478
				redrawMenu()
479
			end
480
		elseif param == keys.delete then
481
			-- Delete
482
			if not bMenu and not bReadOnly then
483
				if  x < string.len( tLines[y] ) + 1 then
484
					local sLine = tLines[y]
485
					tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)
486
					redrawLine(y)
487
				elseif y<#tLines then
488
					tLines[y] = tLines[y] .. tLines[y+1]
489
					table.remove( tLines, y+1 )
490
					redrawText()
491
					redrawMenu()
492
				end
493
			end
494
		elseif param == keys.backspace then
495
			-- Backspace
496
			if not bMenu and not bReadOnly then
497
				if x > 1 then
498
					-- Remove character
499
					local sLine = tLines[y]
500
					tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)
501
					redrawLine(y)
502
			
503
					x = x - 1
504
					setCursor( x, y )
505
				elseif y > 1 then
506
					-- Remove newline
507
					local sPrevLen = string.len( tLines[y-1] )
508
					tLines[y-1] = tLines[y-1] .. tLines[y]
509
					table.remove( tLines, y )
510
					redrawText()
511
				
512
					x = sPrevLen + 1
513
					y = y - 1
514
					setCursor( x, y )
515
				end
516
			end
517
		elseif param == keys.enter then
518
			-- Enter
519
			if not bMenu and not bReadOnly then
520
				-- Newline
521
				local sLine = tLines[y]
522
				local _,spaces=string.find(sLine,"^[ ]+")
523
				if not spaces then
524
					spaces=0
525
				end
526
				tLines[y] = string.sub(sLine,1,x-1)
527
				table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )
528
				redrawText()
529
			
530
				x = spaces+1
531
				y = y + 1
532
				setCursor( x, y )
533
			elseif bMenu then
534
				-- Menu selection
535
				doMenuItem( nMenuItem )
536
			end
537
		elseif param == keys.leftCtrl or param == keys.rightCtrl then
538
			-- Menu toggle
539-
				term.setCursorBlink( false )
539+
540
			if bMenu then
541-
				term.setCursorBlink( true )
541+
				mon.setCursorBlink( false )
542
			else
543
				mon.setCursorBlink( true )
544
			end
545
			redrawMenu()
546
		end
547
		
548
	elseif sEvent == "char" then
549
		if not bMenu and not bReadOnly then
550
			-- Input text
551
			local sLine = tLines[y]
552
			tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
553
			redrawLine(y)
554
		
555
			x = x + 1
556
			setCursor( x, y )
557
		elseif bMenu then
558
			-- Select menu items
559
			for n,sMenuItem in ipairs( tMenuItems ) do
560
				if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then
561
					doMenuItem( n )
562
					break
563
				end
564
			end
565
		end
566
567
	elseif sEvent == "paste" then
568
		if not bMenu and not bReadOnly then
569
			-- Input text
570
			local sLine = tLines[y]
571
			tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
572
			redrawLine(y)
573
574
			x = x + string.len( param )
575
			setCursor( x, y )
576
		end
577
		
578
	elseif sEvent == "mouse_click" then
579
		if not bMenu then
580
			if param == 1 then
581
				-- Left click
582
				local cx,cy = param2, param3
583
				if cy < h then
584
					y = math.min( math.max( scrollY + cy, 1 ), #tLines )
585
					x = math.min( math.max( scrollX + cx, 1 ), string.len( tLines[y] ) + 1 )
586
					setCursor( x, y )
587
				end
588
			end
589
		end
590
		
591
	elseif sEvent == "mouse_scroll" then
592
		if not bMenu then
593
			if param == -1 then
594
				-- Scroll up
595
				if scrollY > 0 then
596
					-- Move cursor up
597
					scrollY = scrollY - 1
598
					redrawText()
599
				end
600
			
601
			elseif param == 1 then
602
				-- Scroll down
603
				local nMaxScroll = #tLines - (h-1)
604
				if scrollY < nMaxScroll then
605
					-- Move cursor down
606
					scrollY = scrollY + 1
607
					redrawText()
608
				end
609
				
610
			end
611-
	elseif sEvent == "term_resize" then
611+
612-
	    w,h = term.getSize()
612+
613
	elseif sEvent == "mon_resize" then
614
	    w,h = mon.getSize()
615
        setCursor( x, y )
616
        redrawMenu()
617
        redrawText()
618
619
	end
620
end
621-
term.clear()
621+
622-
term.setCursorBlink( false )
622+
623-
term.setCursorPos( 1, 1 )
623+
mon.clear()
624
mon.setCursorBlink( false )
625
mon.setCursorPos( 1, 1 )