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