· 9 years ago · Oct 21, 2016, 08:20 PM
1--[[
2 fsExpose (name by supernicejohn - he is indeed nice)
3 [INFO(offtopic):]
4
5 I did this while I couldn't access my home computer on my MacBook,
6 so I had many problems with the keyboard and maybe there are some
7 awkward spaces between functions here :P
8
9 [INFO(on this program):]
10
11 -Right window shows every file in the current directory
12
13 -Left window shows the code of a file (click on a file in the right window)
14
15 -Right click to:
16 -create a new folder
17 -create a new file
18 -delete a file/folder
19 -copy a file/a whole folder
20 -paste a file/a whole folder with the stuff inside
21 -edit a file
22
23 -To add in new entries in the right-click menu OR edited the way an entry works:
24 -scroll down a bit to the function drawRightClick(), to add in new entries, or edit the text
25 -scroll down to _set = {}, and edit the functions or add new ones
26 -scroll down to drawScreen(), and down to the comment "Commands" and edit how to handle the return of drawRightClick()
27 (or just go to line 571, for the lazy peeps out there)
28
29 -Click on the searchbar to get to a path directly
30
31 -Click on the left arrow to go back to the folder you were before
32
33 -Click on the right arrow to go to the folder, where you were, before you pressed back (much like a normal filebrowser, basically)
34
35 [Current state:]
36
37 -Works quite decent.
38
39 -No bugs currently found.
40
41 -(Yes, cat does not go to the next line if a line in a file is too long to display, this is intended (mainly to prevent glitches I had))
42
43 -I'm going to implement this (with edited commands) into doorX, after I tested it out with the resizeable windows (I didn't test the resize handle yet)
44]]--
45
46
47
48--[[
49 listDir(Path[, true (if you want to get the full path)])
50
51 lists the whole tree in the given directory
52
53 Example:
54 listDir("/rom", true)
55
56 Returns:
57
58 /rom/autorun
59 /rom/programs/shell
60 /rom/programs/ls
61 [...]
62]]
63
64local function listDir(path, withP)
65 local t = {}
66 local files = fs.list(path)
67 for _, a in ipairs(files) do
68 if fs.isDir(path.."/"..a) then
69 local tab = listDir(path.."/"..a, true)
70 for _, a in ipairs(tab) do
71 table.insert(t, a)
72 end
73 else
74 if withP then
75 table.insert(t, path.."/"..a)
76 else
77 table.insert(t, a)
78 end
79 end
80 end
81 return t
82end
83
84--[[
85 Preset settings!
86
87 If you want to (e.g. open a file with a different command)
88 edit these commands, set the commands :)
89]]
90
91_set = {}
92function _set.open(f)
93 --runs the file or opens the folder
94 if not fs.isDir(f) then
95return shell.run(f)
96 else
97table.insert(_history, currentPath)
98currentPath = f
99 end
100end
101function _set.copy(f)
102 --inserts the file as fdat[FILENAME] = [TEXT]
103 fdat = {}
104 if fs.isDir(f) then
105 nf = string.sub(f, #currentPath)
106 _filename = nf
107 for _, a in ipairs(listDir(f, true)) do
108 local _, file = pcall(fs.open, a, "r")
109 if _ then
110 local inhalt = file.readAll()
111 file.close()
112 if string.find(a, currentPath, 1, #currentPath) then
113 a = string.sub(a, #currentPath)
114 end
115 fdat[a] = inhalt
116 else
117 printErr(file)
118 end
119 end
120 else
121 local file = fs.open(f, "r")
122 local inhalt = file.readAll()
123 file.close()
124 f = string.sub(f, #currentPath)
125 fdat[f] = inhalt
126 end
127end
128
129function _set.delete(f)
130 --deletes the file
131 local _, ok, err = pcall(fs.delete, f)
132 if not _ then
133 printErr(ok)
134 end
135end
136
137
138function _set.edit(f)
139 --edit a file with 'edit <path>'
140 shell.run("edit", f)
141end
142
143
144function _set.paste(f)
145 --paste everything in the fdat table to the current directory
146
147 if #_filename > 0 then
148 if string.find(_filename, "/", 1, 1) then _filename = string.sub(_filename, 2) end
149 local c = 1
150 local str = _filename
151 repeat
152 if fs.exists(currentPath..str) then
153 str = _filename.."-"..tostring(c)
154 c = c+1
155 else
156 break
157 end
158 until not fs.exists(currentPath..str)
159 oldfname = _filename
160 _filename = str
161 fs.makeDir(currentPath.._filename)
162 table.insert(_history, currentPath)
163 currentPath = currentPath.._filename
164 end
165 for a, b in pairs(fdat) do
166 local c = 1
167 local str = a
168 if string.find(str, oldfname, 1, #oldfname) then
169 str = string.sub(str, #oldfname+2)
170 end
171 repeat
172 if fs.exists(currentPath..str) then
173 str = a.."-"..tostring(c)
174 c = c+1
175 end
176 until not fs.exists(currentPath..str)
177 a = str
178 local _, file = pcall(fs.open, currentPath..a, "w")
179 if _ then
180 file.write(b)
181 file.close()
182 else
183 printErr(file)
184 end
185 end
186 fdat = {}
187 oldfname = ""
188 _filename = ""
189end
190
191local function clear(bg, fg)
192 --[[
193 This function clears the screen in the
194 desired Background (bg) and the desired
195 Foreground (fg) color. (This is very very
196 simple :D)
197 ]]--
198 term.setCursorPos(1,1)
199 term.setBackgroundColor(bg)
200 term.setTextColor(fg)
201 term.clear()
202end
203
204--[[
205 Here is the right-click menu
206
207 If you want to add stuff,
208 then write your new entry
209 and increase "height".
210]]
211
212
213function drawRightClick(x, y, invert)
214 --increase (or decrease) this variable to make the menu smaller/bigger (mainly for removing/adding entries)
215 local height = 7
216 w = window.create(oldTerm, x, y, 15, height)
217 term.redirect(w)
218 clear(colors.white, colors.black)
219 term.write(" Open ")
220 term.setCursorPos(1, 2)
221 term.setTextColor(colors.blue)
222 term.write(" Copy ")
223 term.setCursorPos(1, 3)
224 term.setTextColor(colors.red)
225 term.write(" Delete ")
226 term.setCursorPos(1, 4)
227 term.setTextColor(colors.lime)
228 term.write(" Paste ")
229 term.setCursorPos(1, 5)
230 term.setTextColor(colors.black)
231 term.write(" New Folder ")
232 term.setCursorPos(1, 6)
233 term.write(" New File ")
234 term.setCursorPos(1, 7)
235 term.write(" Edit ")
236 --[[
237 EXAMPLE NEW ENTRY:
238
239 term.setCursorPos(1,8)
240 term.setTextColor(colors.yellow)
241 term.write("Secret function")
242 ]]
243 term.redirect(oldTerm)
244 while true do
245 w.redraw()
246 local _, button, a, b = os.pullEvent("mouse_click")
247 if _ == "mouse_click" and button == 1 and a >= x and a <= x+15-1 and b >= y and b <= y+6 then
248 if b == y then
249 return "open"
250 elseif b == y+1 then
251 return "copy"
252 elseif b == y+2 then
253 return "delete"
254 elseif b == y+3 then
255 return "paste"
256 elseif b == y+4 then
257 return "newfolder"
258 elseif b == y+5 then
259 return "newfile"
260 elseif b == y+6 then
261 return "edit"
262 end
263 --[[
264 CONTINUEATION OF THE EXAMPLE
265 elseif b == y+7 then
266 return "secretfunction"
267 ]]
268 elseif _ == "mouse_click" then
269 w.setVisible(false)
270 term.redirect(oldTerm)
271 w = nil
272 break
273 end
274 end
275end
276
277
278
279
280
281
282--variables
283_ver = 2.1
284_name = "doorX file manager"
285currentPath = "/" --self explaining
286selected = "" --stores the path of the selected file
287_cFiles = {} --stores the files in the current directory
288_history = {} --Stores every path the user is heading
289_last = nil --Stores the path that the user was in, before he pressed back
290_filename = "" --stores the original filename
291_fScroll = 0 --stores the number of times _files did scroll
292_cScroll = 0 --stores the number of times _tree did scroll
293_cMax = 0 --stores the maximum lines of cat
294_cX, _cY = 0, 0 --stores the size of the cat window
295oldfname = "" --saving purposes
296fdat = {} --stores all the listed files and their data
297catTab = {} --stores the cat'ed file in a table (one entry per line)
298maxFiles = 0
299missingFiles = 0
300leftFiles = 0
301
302
303--functions
304
305
306local function drawButton(text)
307 --[[
308 Function to draw a blue button with
309 the given text.
310 (This is basically to prevent from me
311 writing that code over and over again)
312 ]]--
313 local c = term.getBackgroundColor()
314 term.setBackgroundColor(colors.blue)
315 term.write(text)
316 term.setBackgroundColor(c)
317end
318
319
320local function redrawScreens()
321 --[[
322 Put every file/folder in _cFiles and then
323 print them to the right panel and additionally
324 every folder to the left panel
325 ]]--
326 clear(colors.lightGray, colors.white)
327 local oldX, oldY = _files.getCursorPos()
328 _cFiles = {}
329 maxFiles = 0
330 missingFiles = 0
331 leftFiles = 0
332 --list files and clear screen
333 _cFiles = fs.list(currentPath)
334 term.redirect(_files)
335 clear(colors.gray, colors.lime)
336 _tree.redraw()
337 --print files and folders
338 for _, a in ipairs(_cFiles) do
339 if fs.isDir(currentPath..a) then
340 term.setTextColor(colors.blue)
341 end
342 term.write(a)
343 term.setTextColor(colors.lime)
344 local cx, cy = term.getCursorPos()
345 term.setCursorPos(1, cy+1)
346 end
347 _files.setCursorPos(1, 1)
348 --store new variables
349 term.redirect(oldTerm)
350 maxFiles = #_cFiles
351 local x, y = _tree.getSize()
352 x, y = _files.getSize()
353 leftFiles = maxFiles-y
354 if leftFiles < 0 then leftFiles = 0 end
355 term.redirect(searchBar)
356 clear(colors.gray, colors.lime)
357 if not string.find(currentPath, "/", 1, 1) then
358 currentPath = "/"..currentPath
359 end
360 if not string.find(currentPath, "/", #currentPath, #currentPath) then currentPath = currentPath.."/" end
361 term.write(currentPath)
362
363 local cScroll = 0
364 if _fScroll > cScroll then
365 repeat
366 _files.scroll(1)
367 _files.setCursorPos(1, y)
368 _files.setTextColor(colors.lime)
369 if fs.isDir(currentPath.._cFiles[missingFiles+y+1]) then
370 _files.setTextColor(colors.blue)
371 end
372 _files.write(_cFiles[missingFiles+y+1])
373 missingFiles = missingFiles+1
374 leftFiles = leftFiles-1
375 cScroll = cScroll+1
376 until cScroll == _fScroll
377 end
378 if leftFiles < 0 then leftFiles = 0 end
379 if w then w.redraw() end
380end
381
382
383
384local function rewriteCat()
385_cScroll = 1
386_cMax = 0
387catTab = {}
388_cX, _cY = _tree.getSize()
389 if #selected > 0 then
390 term.redirect(_tree)
391 clear(colors.gray, colors.lime)
392 local file, err = fs.open(selected, "r")
393 if not file then
394 printErr(err)
395 return
396 end
397 repeat
398 local str = file.readLine()
399 if str then
400 table.insert(catTab, str)
401 _cMax = _cMax+1
402 end
403 until str == nil
404 file.close()
405 term.setCursorPos(1,1)
406 clear(colors.gray, colors.lime)
407
408 for _, a in ipairs(catTab) do
409 term.write(a)
410 local x, y = term.getCursorPos()
411 term.setCursorPos(1, y+1)
412 end
413 term.setCursorPos(1,1)
414 term.redirect(oldTerm)
415 end
416end
417
418local function drawScreen()
419 --[[
420 This is basically the main function that
421 controls everything.
422 ]]--
423 clear(colors.lightBlue, colors.black)
424 --create the goback- and goforthbutton + searchbar
425 local maxX, maxY = term.getSize()
426 sBar = window.create(oldTerm, 1, 1, tonumber(maxX), 1)
427 term.redirect(sBar)
428 --draw the back and forth buttons
429 clear(colors.lightGray, colors.black)
430 term.setCursorPos(1,1)
431 drawButton("<")
432 term.write(" ")
433 drawButton(">")
434 term.write(" ")
435 --draw the searchbar, as a new window (and leave the last pixel again)
436 searchBar = window.create(sBar, 5, 1, maxX-5, 1)
437 term.redirect(searchBar)
438 clear(colors.gray, colors.lime)
439 term.write("Enter a path.")
440 --draw the left panel, to see the folders in the current path (to move to the folders)
441 term.redirect(oldTerm)
442 leftPanel = window.create(oldTerm, 1, 2, maxX/2-7, maxY-1)
443 term.redirect(leftPanel)
444 clear(colors.lightGray, colors.black)
445 local lx, ly = term.getSize()
446 _tree = window.create(leftPanel, 2, 2, lx-2, ly-2)
447 term.redirect(_tree)
448 clear(colors.gray, colors.lime)
449 term.redirect(oldTerm)
450 --draw the right panel, to manage files
451 rightPanel = window.create(oldTerm, lx+1, 2, maxX-lx+1, maxY-1)
452 term.redirect(rightPanel)
453 clear(colors.lightGray, colors.black)
454 local rx, ry = term.getSize()
455 _files = window.create(rightPanel, 2, 2, rx-2, ry-2)
456 term.redirect(_files)
457 clear(colors.gray, colors.lime)
458
459 --start the main loop, managing everything
460 while true do
461 term.redirect(oldTerm)
462 redrawScreens()
463 local _, button, x, y = os.pullEvent()
464
465 if _ == "term_resize" then
466 oMaxX, oMaxY = term.getSize()
467 --resize every window again
468 --complicated math, kappa
469 local x, y = term.getSize()
470 sBar.reposition(1, 1, x, 1)
471 sBar.redraw()
472 term.redirect(sBar)
473 x = term.getSize()
474 searchBar.reposition(5, 1, x-5, 1)
475 searchBar.redraw()
476 term.redirect(leftPanel)
477 leftPanel.reposition(1, 2, x/2-7, y-1)
478 leftPanel.redraw()
479 _tree.reposition(2, 2, x/2-9, y-3)
480 _tree.redraw()
481 term.redirect(rightPanel)
482 rightPanel.reposition((x/2-7)+1, 2, x-(x/2-7)+1, y-1)
483 rightPanel.redraw()
484 _files.reposition(2, 2, x-(x/2-7)-2, y-3)
485 _files.redraw()
486 term.redirect(oldTerm)
487 elseif _ == "mouse_click" and button == 1 and x >= 5 and x < oMaxX and y == 1 then
488 term.redirect(searchBar)
489 clear(colors.gray, colors.lime)
490 local oprint = print
491 _G.print = function(t)
492 return term.write(t)
493 end
494 local e = read()
495 _G.print = oprint
496 if fs.exists(e) and fs.isDir(e) then
497 table.insert(_history, currentPath)
498
499 currentPath = e
500 term.redirect(oldTerm)
501 else
502 clear(colors.gray, colors.red)
503 term.write("Invalid path.")
504 term.redirect(oldTerm)
505 sleep(1)
506 end
507 elseif _ == "mouse_click" and button == 1 and x == 1 and y == 1 then
508 if #_history > 0 then
509 _last = currentPath
510 currentPath = _history[#_history]
511 table.remove(_history, #_history)
512 end
513 elseif _ == "mouse_click" and button == 1 and x == 3 and y == 1 then
514 if _last ~= nil then
515 table.insert(_history, currentPath)
516 currentPath = _last
517 _last = nil
518 end
519 elseif _ == "mouse_scroll" and button == 1 and x >= 2 and x <= oMaxX/2-8 and y >= 3 and y <= oMaxY-2 and _cScroll+_cY-1 <= _cMax then
520 _tree.scroll(1)
521 _tree.setCursorPos(1, _cY)
522 _tree.write(tostring(catTab[_cScroll+_cY-2]))
523 _cScroll = _cScroll+1
524 elseif _ == "mouse_scroll" and button == -1 and x >= 2 and x <= oMaxX/2-8 and y >= 3 and y <= oMaxY-2 and _cScroll > 0 then
525 _tree.scroll(-1)
526 _tree.setCursorPos(1, 1)
527 _tree.write(tostring(catTab[_cScroll]))
528 _cScroll = _cScroll-1
529 elseif _ == "mouse_scroll" and button == -1 and x >= (oMaxX/2-8)+2 and x <= oMaxX-2 and y >= 3 and y <= oMaxY-1 and missingFiles > 0 then
530 _files.scroll(-1)
531 local x, y = _files.getSize()
532 _files.setCursorPos(1, y)
533 if fs.isDir(currentPath.._cFiles[missingFiles]) then
534 _files.setTextColor(colors.blue)
535 end
536 _files.write(_cFiles[missingFiles])
537 _files.setTextColor(colors.lime)
538 missingFiles = missingFiles-1
539 leftFiles = leftFiles+1
540 _fScroll = _fScroll-1
541 elseif _ == "mouse_scroll" and button == 1 and x >= (oMaxX/2-8)+2 and x <= oMaxX-2 and y >= 3 and y <= oMaxY-1 and leftFiles > 0 then
542 _files.scroll(1)
543 local x, y = _files.getSize()
544 _files.setCursorPos(1, y)
545 if fs.isDir(currentPath.._cFiles[missingFiles+y+1]) then
546 _files.setTextColor(colors.blue)
547 end
548 _files.write(_cFiles[missingFiles+y+1])
549 _files.setTextColor(colors.lime)
550 missingFiles = missingFiles+1
551 leftFiles = leftFiles-1
552 _fScroll = _fScroll+1
553 elseif _ == "mouse_click" and button == 1 and x >= (oMaxX/2-8)+2 and x <= oMaxX-2 and y >= 3 and y <= oMaxY-1 then
554 local realY = y
555 local y = y-2
556 if _cFiles[missingFiles+y] then
557 selected = _cFiles[missingFiles+y]
558 rewriteCat()
559 end
560 elseif _ == "mouse_click" and button == 2 and x >= (oMaxX/2-8)+2 and x <= oMaxX-2 and y >= 3 and y <= oMaxY-1 then
561
562--[[
563 Commands
564
565 If you added new entries,
566 Write your way of handling the click.
567]]
568
569
570 local realY = y
571 local y = y-2
572 local invert = false
573 if 19-realY < 7 then invert = true end
574 local command = ""
575 if not invert then
576 command = drawRightClick(x, realY, false)
577 else
578 command = drawRightClick(x, 12, false)
579 end
580
581 if command == "open" and _cFiles[missingFiles+y] then
582 _set.open(currentPath.._cFiles[missingFiles+y])
583
584 elseif command == "copy" and _cFiles[missingFiles+y] then
585 fileName = _cFiles[missingFiles+y]
586 local byteinhalt = _set.copy(currentPath.._cFiles[missingFiles+y])
587 fileData = byteinhalt
588 elseif command == "delete" and _cFiles[missingFiles+y] then
589 _set.delete(currentPath.._cFiles[missingFiles+y])
590 elseif command == "newfolder" then
591 term.redirect(searchBar)
592 clear(colors.gray, colors.lime)
593 term.write(currentPath)
594 local e = read()
595 if string.find(e, "%.%.") then
596 printErr("Invalid path.")
597 sleep(2)
598 elseif string.find(e, "//") then
599 printErr("Invalid path.")
600 sleep(2)
601 elseif fs.exists(currentPath..e) then
602 printErr("Already exists.")
603 sleep(2)
604 else
605 fs.makeDir(currentPath..e)
606 end
607 term.redirect(oldTerm)
608 elseif command == "paste" then
609 _set.paste()
610 elseif command == "edit" and _cFiles[missingFiles+y] and not fs.isDir(_cFiles[missingFiles+y]) then
611 _set.edit(currentPath.._cFiles[missingFiles+y])
612 elseif command == "newfile" then
613 term.redirect(searchBar)
614 clear(colors.gray, colors.lime)
615 term.write(currentPath)
616 local oprint = _G.print
617 _G.print = function(f)
618 term.write(f)
619 end
620 _G.print = oprint
621 local e = read()
622 if string.find(e, "%.%.") then
623 printErr("Invalid path.")
624 sleep(2)
625 elseif string.find(e, "//") then
626 printErr("Invalid path.")
627 sleep(2)
628 elseif fs.exists(currentPath..e) then
629 printErr("Already exists.")
630 sleep(2)
631 else
632 local ff = fs.open(currentPath..e, "w")
633 ff.close()
634 end
635 end
636 end
637 end
638end
639
640
641--code
642--catch the original terminal
643oldTerm = term.current()
644oMaxX, oMaxY = term.getSize()
645function printErr(str)
646 term.redirect(searchBar)
647 clear(colors.gray, colors.red)
648 term.write(str)
649 term.redirect(oldTerm)
650end
651drawScreen()