View difference between Paste ID: 5tq5iWem and md15Hcmv
SHOW: | | - or go back to the newest paste.
1
2
local tArgs = { ... }
3
if #tArgs == 0 then
4
	print( "Usage: edit <path>" )
5
	return
6
end
7
8
local sPath = shell.resolve( tArgs[1] )
9
local bReadOnly = fs.isReadOnly( sPath )
10
if fs.exists( sPath ) and fs.isDir( sPath ) then
11
	print( "Cannot edit a directory" )
12
	return
13
end
14
15
local w,h = term.getSize()
16
local x,y = 1,1
17
local scrollX, scrollY = 0,0
18
19
local bMenu = false
20
local nMenuItem = 1
21
22
local tStatusParts = {left='',right=''}
23
local sStatus = ""
24
local tLines = {}
25
26
local function load()
27
	tLines = {}
28
	if fs.exists( sPath ) then
29
		local file = io.open( sPath, "r" )
30
		local sLine = file:read()
31
		while sLine do
32
			table.insert( tLines, sLine )
33
			sLine = file:read()
34
		end
35
		file:close()
36
	else
37
		table.insert( tLines, "" )
38
	end
39
end
40
41
local function save()
42
	local file = io.open( sPath, "w" )
43
	if file then
44
		for n, sLine in ipairs( tLines ) do
45
			file:write( sLine .. "\n" )
46
		end
47
		file:close()
48
		return true
49
	end
50
	return false
51
end
52
53
local function redrawText()
54
	for y=1,h-1 do
55
		term.setCursorPos( 1 - scrollX, y )
56
		term.clearLine()
57
58
		local sLine = tLines[ y + scrollY ]
59
		if sLine ~= nil then
60
			term.write( sLine )
61
		end
62
	end
63
	term.setCursorPos( x - scrollX, y - scrollY )
64
end
65
66
local function redrawLine()
67
	local sLine = tLines[y]
68
	term.setCursorPos( 1 - scrollX, y - scrollY )
69
	term.clearLine()
70
	term.write( sLine )
71
	term.setCursorPos( x - scrollX, y - scrollY )
72
end
73
74
local tMenuItems = { "Save", "Exit" }
75
76
local function redrawMenu()
77
    term.setCursorPos( 1, h )
78
	term.clearLine()
79
	
80-
		term.write( sStatus )
80+
	if bMenu then
81
		local sBuild = ''
82
		for n,sItem in ipairs( tMenuItems ) do
83
			if n == nMenuItem then
84-
				term.write( "["..sItem.."]" )
84+
				sBuild=sBuild.."["..sItem.."]"
85
			else
86-
				term.write( " "..sItem.." " )
86+
				sBuild=sBuild.." "..sItem.." " --<FIXME> Might want to shave this.
87
			end
88
		end
89
		tStatusParts['left']=sBuild
90
	else
91
		tStatusParts['left']='Ctrl'
92
	end
93
	if tStatusParts['right'] then
94-
local function setStatus( _sText )
94+
		term.setCursorPos( w-tStatusParts['right']:len(), h )
95-
	sStatus = _sText
95+
		term.write(tStatusParts['right'])
96
	end
97
	if tStatusParts['left'] then
98
		term.setCursorPos( 1, h )
99
		term.write(tStatusParts['left'])
100
	end
101
    term.setCursorPos( x - scrollX, y - scrollY )
102
end
103
104
local function setStatus(pos, _sText)
105
	tStatusParts[pos] = _sText
106
	redrawMenu()
107
end
108
109
local function updateRightStatus()
110
	-- Tracks current position of total line numbers.
111
	--print(y)
112
	--print(#tLines)
113
	setStatus("right", tostring(y)..'/'..tostring(#tLines))
114
end
115
116
local function setCursor( x, y )
117
	local screenX = x - scrollX
118
	local screenY = y - scrollY
119
	
120
	local bRedraw = false
121
	if screenX < 1 then
122
		scrollX = x - 1
123
		screenX = 1
124
		bRedraw = true
125
	elseif screenX > w then
126
		scrollX = x - w
127
		screenX = w
128
		bRedraw = true
129
	end
130
	
131
	if screenY < 1 then
132
		scrollY = y - 1
133
		screenY = 1
134
		bRedraw = true
135
	elseif screenY > h-1 then
136
		scrollY = y - (h-1)
137-
setStatus( "Press Ctrl to access menu" )
137+
138
		bRedraw = true
139
	end
140
	
141
	if bRedraw then
142
		redrawText()
143
	end
144
	term.setCursorPos( screenX, screenY )
145
end
146-
			setStatus( "Saved to "..sPath )
146+
147
load()
148-
			setStatus( "Access denied" )
148+
149
term.clear()
150
term.setCursorPos(x,y)
151
term.setCursorBlink( true )
152
153
redrawText()
154
updateRightStatus()
155
redrawMenu()
156
157
local bRunning = true
158
local tMenuFunctions = {
159
	["Exit"] = function()
160
		bRunning = false
161
	end,
162
	["Save"] = function()
163
		if save() then
164
			setStatus("left", "Saved to "..sPath )
165
		else
166
			setStatus("left", "Access denied" )
167
		end
168
	end,
169
}
170
171
local function doMenuItem( _n )
172
	local fnMenu = tMenuFunctions[ tMenuItems[_n] ]
173
	if fnMenu then
174
		fnMenu()
175
	end
176
177
	bMenu = false
178
	term.setCursorBlink( true )
179
	redrawMenu()
180
end
181
182
while bRunning do
183
  local sEvent, param = os.pullEvent()
184
  if sEvent == "key" then
185
    if param == 200 then
186
		-- Up
187
		if not bMenu then
188
			-- Move cursor up
189
			if y > 1 then
190
				y = y - 1
191
				x = math.min( x, string.len( tLines[y] ) + 1 )
192
				setCursor( x, y )
193
				updateRightStatus()
194
			end
195
		end
196
	elseif param == 208 then
197
		-- Down
198
		if not bMenu then
199
			-- Move cursor down
200
			if y < #tLines then
201
				y = y + 1
202
				x = math.min( x, string.len( tLines[y] ) + 1 )
203
				setCursor( x, y )
204
				updateRightStatus()
205
			end
206
		end
207
	elseif param == 15 then
208
		-- Tab
209
		if not bMenu then
210
			local sLine = tLines[y]
211
			tLines[y] = string.sub(sLine,1,x-1) .. "  " .. string.sub(sLine,x)
212
			redrawLine()
213
		
214
			x = x + 2
215
			setCursor( x, y )
216
		end
217
	elseif param == 201 then
218
		-- Page Up
219
		if not bMenu then
220
			-- Move up a page
221
			local sx,sy=term.getSize()
222
			if y>sy-1 then
223
				y = y-sy-1
224
			else
225
				y = 1
226
			end
227
			x = math.min( x, string.len( tLines[y] ) + 1 )
228
			setCursor( x, y )
229
			updateRightStatus()
230
		end
231
	elseif param == 209 then
232
		-- Page Down
233
		if not bMenu then
234
			-- Move down a page
235
			local sx,sy=term.getSize()
236
			if y<#tLines-sy-1 then
237
				y = y+sy-1
238
			else
239
				y = #tLines
240
			end
241
			x = math.min( x, string.len( tLines[y] ) + 1 )
242
			setCursor( x, y )
243
			updateRightStatus()
244
		end
245
	elseif param == 199 then
246
		-- Home
247
		if not bMenu then
248
			-- Move cursor to the beginning
249
			x=1
250
			setCursor(x,y)
251
		end
252
	elseif param == 207 then
253
		-- End
254
		if not bMenu then
255
			-- Move cursor to the end
256
			x = string.len( tLines[y] ) + 1
257
			setCursor(x,y)
258
		end
259
	elseif param == 203 then
260
		-- Left
261
		if not bMenu then
262
			-- Move cursor left
263
			if x > 1 then
264
				x = x - 1
265
			elseif x==1 and y>1 then
266
				x = string.len( tLines[y-1] ) + 1
267
				y = y - 1
268
				updateRightStatus()
269
			end
270
			setCursor( x, y )
271
		else
272
			-- Move menu left
273
			nMenuItem = nMenuItem - 1
274
			if nMenuItem < 1 then
275
				nMenuItem = #tMenuItems
276-
				-- don't touch that cursor
276+
277
			redrawMenu()
278
		end
279
	elseif param == 205 then
280
		-- Right
281
		if not bMenu then
282
			-- Move cursor right
283
   		 	if x < string.len( tLines[y] ) + 1 then
284
				x = x + 1
285
			elseif x==string.len( tLines[y] ) + 1 and y<#tLines then
286
				x = 1
287
				y = y + 1
288
				updateRightStatus()
289
			end
290
			setCursor( x, y )
291
		else
292
			-- Move menu right
293
			nMenuItem = nMenuItem + 1
294
		  	if nMenuItem > #tMenuItems then
295
				nMenuItem = 1
296
		  	end
297
		  	redrawMenu()
298
		end
299
	elseif param == 211 then
300
		-- Delete
301
		if not bMenu then
302
			if  x < string.len( tLines[y] ) + 1 then
303
				local sLine = tLines[y]
304
				tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)
305
				redrawLine()
306
			elseif y<#tLines then
307
				tLines[y] = tLines[y] .. tLines[y+1]
308
				table.remove( tLines, y+1 )
309
				redrawText()
310-
			table.insert( tLines, y+1, string.sub(sLine,x) )
310+
				updateRightStatus()
311
			end
312
		end
313-
			x = 1
313+
314
		-- Backspace
315-
			setCursor( x, y )		
315+
316
   		 	if x > 1 then
317
				-- Remove character
318
				local sLine = tLines[y]
319
				tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)
320
				redrawLine()
321
		
322
				x = x - 1
323
				setCursor( x, y )
324
			
325
			elseif y > 1 then
326
				-- Remove newline
327
				local sPrevLen = string.len( tLines[y-1] )
328
				tLines[y-1] = tLines[y-1] .. tLines[y]
329
				table.remove( tLines, y )
330
				redrawText()
331
			
332
				x = sPrevLen + 1
333
				y = y - 1
334
				setCursor( x, y )
335
				updateRightStatus()
336
		  	end
337
		end
338
		
339
	elseif param == 28 then
340
		-- Enter
341
		if not bMenu then
342
			-- Newline
343
			local sLine = tLines[y]
344
			local _,spaces=string.find(sLine,"^[ ]+")
345
			if not spaces then spaces=0 end
346
			tLines[y] = string.sub(sLine,1,x-1)
347
			table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )
348
			redrawText()
349
		
350
			x = spaces+1
351
			y = y + 1
352
			setCursor( x, y )
353
			updateRightStatus()
354
		else
355
			-- Menu selection
356
			doMenuItem( nMenuItem )
357
		end
358
		
359
	elseif param == 29 then
360
		-- Menu toggle
361
		bMenu = not bMenu
362
		if bMenu then
363
			term.setCursorBlink( false )
364
			nMenuItem = 1
365
		else
366
			setStatus("left","Ctrl")
367
			term.setCursorBlink( true )
368
		end
369
		redrawMenu()
370
	
371
	end
372
		
373
  elseif sEvent == "char" then
374
	if not bMenu then
375
    	-- Input text
376
		local sLine = tLines[y]
377
		tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
378
		redrawLine()
379
	
380
		x = x + string.len( param )
381
		setCursor( x, y )
382
	
383
	else
384
		-- Select menu items
385
		for n,sMenuItem in ipairs( tMenuItems ) do
386
			if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then
387
				doMenuItem( n )
388
				break
389
			end
390
		end
391
	end
392
  end
393
end
394
395
term.clear()
396
term.setCursorBlink( false )
397
term.setCursorPos( 1, 1 )