Advertisement
kssr3951

filer

Jun 14th, 2014
257
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 15.26 KB | None | 0 0
  1. local function isOneOf(val, possibleValues)
  2.   for _, v in ipairs(possibleValues) do
  3.     if val == v then
  4.       return true;
  5.     end
  6.   end
  7.   return false;
  8. end
  9.  
  10. local function startsWith(subject, prefix)
  11.   if subject:len() < prefix:len() then
  12.     return false;
  13.   end
  14.   for i = 1, prefix:len() do
  15.     if subject:sub(i, i) ~= prefix:sub(i, i) then
  16.       return false;
  17.     end
  18.   end
  19.   return true;
  20. end
  21.  
  22. local function makePageData(width, height, directoryOnlyFlg)
  23.   local rawLst = fs.list(shell.dir());
  24.   local fLst = { };
  25.   local dLst = { };
  26.   for _, val in ipairs(rawLst) do
  27.     if fs.isDir(shell.dir() .. "/" .. val) then
  28.       table.insert(dLst, { name = val, isDir = true });
  29.     else
  30.       table.insert(fLst, { name = val, isDir = false });
  31.     end
  32.   end
  33.   function comp(a, b)
  34.     return a.name < b.name;
  35.   end
  36.   local lst = { };
  37.  
  38.   if "" ~= shell.dir() then
  39.     table.insert(lst, { name = "..", isDir = true });
  40.   end
  41.  
  42.   if directoryOnlyFlg then
  43.     table.insert(lst, { name = ".", isDir = true });
  44.   end
  45.  
  46.   table.sort(dLst, comp);
  47.   for _, val in ipairs(dLst) do
  48.     table.insert(lst, val);
  49.   end
  50.  
  51.   if not directoryOnlyFlg then
  52.     table.sort(fLst, comp);
  53.     for _, val in ipairs(fLst) do
  54.       table.insert(lst, val);
  55.     end
  56.   end
  57.  
  58.   local pages = { };
  59.   local currPage = { };
  60.   for _, val in ipairs(lst) do
  61.     table.insert(currPage, val);
  62.     if height - 1 <= #currPage then
  63.       table.insert(pages, currPage);
  64.       currPage = { };
  65.     end
  66.   end
  67.   if 0 < #currPage then
  68.     table.insert(pages, currPage);
  69.   end
  70.   return pages;
  71. end
  72.  
  73. local function resetTerm()
  74.   term.setBackgroundColor(colors.black);
  75.   term.setTextColor(colors.white);
  76.   term.clear();
  77.   term.setCursorPos(1, 1);
  78. end
  79.  
  80. local function prepareExit(initialDir)
  81.   resetTerm();
  82.   shell.setDir(initialDir);
  83. end
  84.  
  85. local function pagingAction(isUp, pageMode, pageIdx, lineIdx, pages, newNotice)
  86.  
  87.   if isUp then
  88.     if pageMode then
  89.       pageIdx = math.max(pageIdx - 1, 1);
  90.     else
  91.       if lineIdx - 1 <= 0 then
  92.         if 2 <= pageIdx then
  93.           pageIdx = pageIdx - 1;
  94.           lineIdx = #pages[pageIdx];
  95.         end
  96.       else
  97.         lineIdx = lineIdx - 1;
  98.       end
  99.     end
  100.  
  101.   else
  102.     if pageMode then
  103.       pageIdx = math.min(pageIdx + 1, #pages);
  104.     else
  105.       if #pages[pageIdx] < lineIdx + 1 then
  106.         if pageIdx <= #pages - 1 then
  107.           pageIdx = pageIdx + 1;
  108.           lineIdx = 1;
  109.         end
  110.       else
  111.         lineIdx = lineIdx + 1;
  112.       end
  113.     end
  114.   end
  115.  
  116.   local elm = pages[pageIdx][lineIdx];
  117.   if not pageMode then
  118.     if elm.isDir and ".." == elm.name then
  119.       newNotice = ".. means parent directory.";
  120.     elseif elm.isDir and "." == elm.name then
  121.       newNotice = ". means current directory.";
  122.     end
  123.   end
  124.  
  125.   return pageIdx, lineIdx, newNotice;
  126. end
  127.  
  128. local function getParentPath(directoryPath)
  129.   local tmp = directoryPath:reverse();
  130.   return tmp:sub(tmp:find("/", 1, true) + 1):reverse();
  131. end
  132.  
  133. local function ascendDirectory()
  134.   if "" == shell.dir() then
  135.     return false, "";
  136.  
  137.   else
  138.     returnTrip = true;
  139.     shell.setDir(getParentPath(shell.dir()));
  140.  
  141.     local newNotice;
  142.     if "" == shell.dir() then
  143.       newNotice = "ascended. /";
  144.     else
  145.       newNotice = "ascended. " .. shell.dir();
  146.     end
  147.     return true, newNotice;
  148.   end
  149. end
  150.  
  151. local function lineModeAction(currentAction, currentSubject,
  152.                               pathIndexStack, pageIdx_, lineIdx_,
  153.                               toolIdx, moveToMode, moveSrcPath)
  154.   local directoryChanged = false;
  155.   local returnTrip = false;
  156.   local newNotice = "";
  157.  
  158.   if startsWith(currentAction, "edit") then
  159.     shell.run("edit", currentSubject);
  160.  
  161.   elseif startsWith(currentAction, "cd") then
  162.     if ".." == currentSubject then
  163.       returnTrip, newNotice = ascendDirectory();
  164.  
  165.     else
  166.       table.insert(pathIndexStack, { pageIdx = pageIdx_, lineIdx = lineIdx_ });
  167.       shell.setDir(shell.dir() .. "/" .. currentSubject);
  168.       newNotice = "descended. " .. shell.dir();
  169.     end
  170.     directoryChanged = true;
  171.  
  172.   elseif startsWith(currentAction, "delete") then
  173.     if "." == currentSubject or ".." == currentSubject then
  174.       newNotice = currentSubject .. " cannot delete.";
  175.     else
  176.       resetTerm();
  177.       print("[delete] " .. currentSubject);
  178.       print("Do you really want to delete this file?");
  179.       term.write("[y]es / [n]o >");
  180.       if "y" == read() then
  181.         shell.run("delete", currentSubject);
  182.         newNotice = currentSubject .. " was (maybe) deleted.";
  183.         directoryChanged = true;
  184.  
  185.       else
  186.         newNotice = "delete canceled.";
  187.       end
  188.     end
  189.  
  190.   elseif startsWith(currentAction, "rename") then
  191.     if "." == currentSubject or ".." == currentSubject then
  192.       newNotice = currentSubject .. " cannot rename.";
  193.     else
  194.       resetTerm();
  195.       print("[rename] " .. currentSubject);
  196.       print("Enter new name.");
  197.       print("To borrow original name, press [up] cursor key.");
  198.       print("If you want to cancel renaming, enter blank.");
  199.       term.write(">");
  200.       local newName = read(nil, { currentSubject });
  201.       if "" ~= newName then
  202.         shell.run("rename", currentSubject, newName);
  203.         newNotice = currentSubject .. " was (maybe) renamed.";
  204.         directoryChanged = true;
  205.  
  206.       else
  207.         newNotice = "rename canceled.";
  208.       end
  209.     end
  210.  
  211.   elseif startsWith(currentAction, "copy") then
  212.     if "." == currentSubject or ".." == currentSubject then
  213.       newNotice = currentSubject .. " cannot copy.";
  214.     else
  215.       resetTerm();
  216.       print("[copy] " .. currentSubject);
  217.       print("Enter new name.");
  218.       print("To borrow original name, press [up] cursor key.");
  219.       print("If you want to cancel copy, enter blank.");
  220.       term.write(">");
  221.       local newName = read(nil, { currentSubject });
  222.       if "" ~= newName then
  223.         shell.run("copy", currentSubject, newName);
  224.         newNotice = currentSubject .. " was (maybe) copied.";
  225.         directoryChanged = true;
  226.  
  227.       else
  228.         newNotice = "copy canceled.";
  229.       end
  230.     end
  231.  
  232.   elseif      startsWith(currentAction, "move")
  233.       and not startsWith(currentAction, "moveTo") then
  234.     if "." == currentSubject or ".." == currentSubject then
  235.       newNotice = currentSubject .. " cannot copy.";
  236.     else
  237.       moveToMode = true;
  238.       newNotice = "<<move>> select moveTo directory.";
  239.       directoryChanged = true;
  240.       moveSrcPath = shell.dir() .. "/" .. currentSubject;
  241.       pageIdx_ = 1;
  242.       lineIdx_ = 1;
  243.       toolIdx = 1;
  244.     end
  245.  
  246.   elseif startsWith(currentAction, "cancel move") then
  247.     moveToMode = false;
  248.     newNotice = "move canceled.";
  249.     directoryChanged = true;
  250.     pageIdx_ = 1;
  251.     lineIdx_ = 1;
  252.     toolIdx = 1;
  253.  
  254.   elseif startsWith(currentAction, "moveTo") then
  255.     local choice = "move / copy";
  256.     local wrong = false;
  257.     local moveDstPath;
  258.     if "." == currentSubject then
  259.       moveDstPath = shell.dir();
  260.     elseif ".." == currentSubject then
  261.       moveDstPath = getParentPath(shell.dir());
  262.     else
  263.       moveDstPath = shell.dir() .. "/" .. currentSubject;
  264.     end
  265.  
  266.     while true do
  267.       resetTerm();
  268.       print("[" .. choice .. "]");
  269.       print("source      :");
  270.       print("  " .. moveSrcPath);
  271.       print("destination :");
  272.       print("  " .. moveDstPath);
  273.  
  274.       print("select move or copy.");
  275.       if wrong then
  276.         wrong = false;
  277.         print("*** Wrong input. Please retry.");
  278.       end
  279.       print(" copy : input \"c\" and hit enter key.");
  280.       print(" move : hit enter key with no input.");
  281.       print(" or [r]eselect destination directory.");
  282.       print(" or [q]uit. (cancel move or copy.)");
  283.       term.write(">");
  284.       local input = read();
  285.       if "c" == input then
  286.         choice = "copy";
  287.         break;
  288.       elseif "" == input then
  289.         choice = "move";
  290.         break;
  291.       elseif "r" == input then
  292.         choice = "reselect";
  293.         break;
  294.       elseif "q" == input then
  295.         choice = "quit";
  296.         break;
  297.       else
  298.         wrong = true;
  299.       end
  300.     end
  301.     if "copy" == choice then
  302.       shell.run("copy", moveSrcPath, moveDstPath);
  303.       newNotice = "The copy was successful maybe.";
  304.     elseif "move" == choice then
  305.       shell.run("move", moveSrcPath, moveDstPath);
  306.       newNotice = "The move was successful maybe.";
  307.     elseif "reselect" == choice then
  308.       newNotice = "<<move>> select moveTo directory.";
  309.       toolIdx = 1;
  310.     elseif "quit" == choice then
  311.       newNotice = "copy canceled.";
  312.     end
  313.  
  314.     if "reselect" ~= choice then
  315.       moveToMode = false;
  316.       directoryChanged = true;
  317.       pageIdx_ = 1;
  318.       lineIdx_ = 1;
  319.       toolIdx = 1;
  320.     end
  321.  
  322.   elseif startsWith(currentAction, "[other]") then
  323.     if "." == currentSubject or ".." == currentSubject then
  324.       newNotice = currentSubject .. " cannot [other].";
  325.     else
  326.       resetTerm();
  327.       local stage = 1;
  328.       local input = "";
  329.       local ret;
  330.       while true do
  331.         print("[other]");
  332.         local hist = { };
  333.         table.insert(hist, currentSubject);
  334.         table.insert(hist, currentSubject .. " " .. currentSubject);
  335.         if "" ~= input then
  336.           table.insert(hist, input);
  337.         end
  338.  
  339.         if 1 == stage then
  340.           print("Input command.");
  341.           term.write(">");
  342.           input = read(nil, hist);
  343.           if "" == input then
  344.             newNotice = "[other] canceled.";
  345.             break;
  346.           else
  347.             stage = 2;
  348.           end
  349.         elseif 2 == stage then
  350.           print("command = ");
  351.           print(input);
  352.           print("");
  353.           print("execute? [y]es, [e]dit, [c]ancel");
  354.           term.write(">");
  355.           local ch = read();
  356.           if "y" == ch then
  357.             ret = shell.run(input);
  358.             newNotice = "[other] returned " .. tostring(ret);
  359.             break;
  360.           elseif "e" == ch then
  361.             stage = 1;
  362.           elseif "c" == ch then
  363.             newNotice = "[other] canceled.";
  364.             break;
  365.           end
  366.         end
  367.       end
  368.     end
  369.   end
  370.   return directoryChanged, pathIndexStack, returnTrip, newNotice, moveToMode,
  371.          pageIdx_, lineIdx_, toolIdx, moveSrcPath;
  372. end
  373.  
  374. local SPACE = " ";
  375. local pageIdx = 1;
  376. local lineIdx = 1;
  377. local toolIdx = 1;
  378. local pageMode = true;
  379. local tools = { dir  = { "cd   --> ", "delete --> ", "rename --> ",
  380.                          "copy --> ", "move --> ", "[other] --> "},
  381.                 file = { "edit --> ", "delete --> ", "rename --> ",
  382.                          "copy --> ", "move --> ", "[other] --> "},
  383.                 move = { "cd --> ", "moveTo --> ", "cancel move " } };
  384. local directoryChanged;
  385. local pages;
  386. local width, height = term.getSize();
  387. local returnTrip = false;
  388. local pathIndexStack = { };
  389. local initialDir = shell.dir();
  390. local miniHelp = { true_  = "[q]uit, up/down=paging, [->]=line mode",
  391.                    false_ = "[->]=change action, enter=exec action" };
  392. local statusBarText = "";
  393. local newNotice = "";
  394. local moveToMode = false;
  395. local directoryOnlyFlg = false;
  396. local moveSrcPath = "";
  397.  
  398. local KNtC = { };
  399.  
  400. for i = 0, 256 do
  401.   local name = keys.getName(i);
  402.   if nil ~= name then
  403.     KNtC[name] = i;
  404.   end
  405. end
  406.  
  407. directoryChanged = true;
  408. while true do
  409.  
  410.   if moveToMode then
  411.     directoryOnlyFlg = true;
  412.   else
  413.     directoryOnlyFlg = false;
  414.   end
  415.  
  416.   if directoryChanged then
  417.     pages = makePageData(width, height, directoryOnlyFlg);
  418.     pageIdx = math.min(#pages, pageIdx);
  419.     lineIdx = math.min(#pages[pageIdx], lineIdx);
  420.     if returnTrip and #pathIndexStack then
  421.       local o = table.remove(pathIndexStack);
  422.       pageIdx = o.pageIdx;
  423.       lineIdx = o.lineIdx;
  424.     end
  425.     returnTrip = false;
  426.     directoryChanged = false;
  427.   end
  428.  
  429.   local currentLineIsDir;
  430.   local currentAction = "";
  431.   local currentSubject;
  432.   local toolSetKey;
  433.  
  434.   resetTerm();
  435.   for i, val in ipairs(pages[pageIdx]) do
  436.     term.setCursorPos(1, i);
  437.     local arrow = "";
  438.     if not pageMode then
  439.       lineIdx = math.min(lineIdx, #pages[pageIdx]);
  440.  
  441.       if moveToMode then
  442.         toolSetKey = "move";
  443.       else
  444.         if val.isDir then
  445.           toolSetKey = "dir";
  446.         else
  447.           toolSetKey = "file";
  448.         end
  449.       end
  450.  
  451.       if i == lineIdx then
  452.         arrow = tools[toolSetKey][toolIdx];
  453.         currentAction = arrow;
  454.         currentLineIsDir = val.isDir;
  455.         currentSubject = val.name;
  456.       else
  457.         arrow = SPACE:rep(#tools[toolSetKey][toolIdx]);
  458.       end
  459.     end
  460.  
  461.     if val.isDir then
  462.       term.write(arrow .. "<dir> " .. val.name
  463.                  .. SPACE:rep(math.max(0, width - (#arrow + #val.name))));
  464.     else
  465.       term.write(arrow .. val.name
  466.                  .. SPACE:rep(math.max(0, width - (#arrow + #val.name))));
  467.     end
  468.   end
  469.   for i = #pages[pageIdx] + 1, height do
  470.     term.setCursorPos(1, i);
  471.     term.write(SPACE:rep(width));
  472.   end
  473.  
  474.   term.setCursorPos(1, height);
  475.   term.setTextColor(colors.black);
  476.   term.setBackgroundColor(colors.white);
  477.  
  478.   if not moveToMode then
  479.     if "" ~= newNotice then
  480.       statusBarText = newNotice;
  481.       newNotice = "";
  482.     else
  483.       statusBarText = miniHelp[tostring(pageMode) .. "_"];
  484.     end
  485.   else
  486.     statusBarText = newNotice;
  487.   end
  488.   term.write(statusBarText .. SPACE:rep(math.max(0, width - #statusBarText)));
  489.  
  490.   local easyExitFlg = false;
  491.   while true do
  492.     local event, scanCode = os.pullEvent("key");
  493.  
  494.     -- key name
  495.     -- http://computercraft.info/wiki/Keys_(API)
  496.     if isOneOf(scanCode, { KNtC.up, KNtC.p, KNtC.b, KNtC.w, KNtC.a }) then
  497.       pageIdx, lineIdx, newNotice
  498.         = pagingAction(true,  pageMode, pageIdx, lineIdx, pages, newNotice);
  499.       break;
  500.  
  501.     elseif isOneOf(scanCode,
  502.              { KNtC.down, KNtC.n, KNtC.f, KNtC.s, KNtC.d, KNtC.space }) then
  503.       pageIdx, lineIdx, newNotice
  504.         = pagingAction(false, pageMode, pageIdx, lineIdx, pages, newNotice);
  505.       break;
  506.  
  507.     elseif isOneOf(scanCode, { KNtC.right }) then
  508.       if not pageMode then
  509.         toolIdx = (toolIdx % #tools[toolSetKey]) + 1;
  510.         if startsWith(
  511.             tools[toolSetKey][toolIdx], "copy") then
  512.           newNotice = "The copy on the same directory.";
  513.  
  514.         elseif      startsWith(tools[toolSetKey][toolIdx], "move")
  515.             and not startsWith(tools[toolSetKey][toolIdx], "moveTo") then
  516.           newNotice = "Move (or copy) to other directory.";
  517.  
  518.         elseif startsWith(tools[toolSetKey][toolIdx], "[other]") then
  519.           newNotice = "A command can be executed manually.";
  520.         end
  521.       end
  522.       pageMode = false;
  523.       break;
  524.  
  525.     elseif isOneOf(scanCode, { KNtC.left }) then
  526.       toolIdx = 1;
  527.       if pageMode then
  528.         returnTrip, newNotice = ascendDirectory();
  529.         directoryChanged = returnTrip;
  530.       end
  531.       if not moveToMode then
  532.         pageMode = true;
  533.       end
  534.       break;
  535.  
  536.     elseif isOneOf(scanCode, { KNtC.q, KNtC.e }) then
  537.       prepareExit(initialDir);
  538.       return;
  539.  
  540.     elseif isOneOf(scanCode, { KNtC.enter }) then
  541.       directoryChanged, pathIndexStack, returnTrip, newNotice, moveToMode,
  542.       pageIdx, lineIdx, toolIdx, moveSrcPath
  543.         = lineModeAction(currentAction, currentSubject, pathIndexStack,
  544.                          pageIdx, lineIdx, toolIdx, moveToMode, moveSrcPath);
  545.       break;
  546.     end
  547.     sleep(0.5);
  548.   end
  549. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement