Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local function isOneOf(val, possibleValues)
- for _, v in ipairs(possibleValues) do
- if val == v then
- return true;
- end
- end
- return false;
- end
- local function startsWith(subject, prefix)
- if subject:len() < prefix:len() then
- return false;
- end
- for i = 1, prefix:len() do
- if subject:sub(i, i) ~= prefix:sub(i, i) then
- return false;
- end
- end
- return true;
- end
- local function makePageData(width, height, directoryOnlyFlg)
- local rawLst = fs.list(shell.dir());
- local fLst = { };
- local dLst = { };
- for _, val in ipairs(rawLst) do
- if fs.isDir(shell.dir() .. "/" .. val) then
- table.insert(dLst, { name = val, isDir = true });
- else
- table.insert(fLst, { name = val, isDir = false });
- end
- end
- function comp(a, b)
- return a.name < b.name;
- end
- local lst = { };
- if "" ~= shell.dir() then
- table.insert(lst, { name = "..", isDir = true });
- end
- if directoryOnlyFlg then
- table.insert(lst, { name = ".", isDir = true });
- end
- table.sort(dLst, comp);
- for _, val in ipairs(dLst) do
- table.insert(lst, val);
- end
- if not directoryOnlyFlg then
- table.sort(fLst, comp);
- for _, val in ipairs(fLst) do
- table.insert(lst, val);
- end
- end
- local pages = { };
- local currPage = { };
- for _, val in ipairs(lst) do
- table.insert(currPage, val);
- if height - 1 <= #currPage then
- table.insert(pages, currPage);
- currPage = { };
- end
- end
- if 0 < #currPage then
- table.insert(pages, currPage);
- end
- return pages;
- end
- local function resetTerm()
- term.setBackgroundColor(colors.black);
- term.setTextColor(colors.white);
- term.clear();
- term.setCursorPos(1, 1);
- end
- local function prepareExit(initialDir)
- resetTerm();
- shell.setDir(initialDir);
- end
- local function pagingAction(isUp, pageMode, pageIdx, lineIdx, pages, newNotice)
- if isUp then
- if pageMode then
- pageIdx = math.max(pageIdx - 1, 1);
- else
- if lineIdx - 1 <= 0 then
- if 2 <= pageIdx then
- pageIdx = pageIdx - 1;
- lineIdx = #pages[pageIdx];
- end
- else
- lineIdx = lineIdx - 1;
- end
- end
- else
- if pageMode then
- pageIdx = math.min(pageIdx + 1, #pages);
- else
- if #pages[pageIdx] < lineIdx + 1 then
- if pageIdx <= #pages - 1 then
- pageIdx = pageIdx + 1;
- lineIdx = 1;
- end
- else
- lineIdx = lineIdx + 1;
- end
- end
- end
- local elm = pages[pageIdx][lineIdx];
- if not pageMode then
- if elm.isDir and ".." == elm.name then
- newNotice = ".. means parent directory.";
- elseif elm.isDir and "." == elm.name then
- newNotice = ". means current directory.";
- end
- end
- return pageIdx, lineIdx, newNotice;
- end
- local function getParentPath(directoryPath)
- local tmp = directoryPath:reverse();
- return tmp:sub(tmp:find("/", 1, true) + 1):reverse();
- end
- local function ascendDirectory()
- if "" == shell.dir() then
- return false, "";
- else
- returnTrip = true;
- shell.setDir(getParentPath(shell.dir()));
- local newNotice;
- if "" == shell.dir() then
- newNotice = "ascended. /";
- else
- newNotice = "ascended. " .. shell.dir();
- end
- return true, newNotice;
- end
- end
- local function lineModeAction(currentAction, currentSubject,
- pathIndexStack, pageIdx_, lineIdx_,
- toolIdx, moveToMode, moveSrcPath)
- local directoryChanged = false;
- local returnTrip = false;
- local newNotice = "";
- if startsWith(currentAction, "edit") then
- shell.run("edit", currentSubject);
- elseif startsWith(currentAction, "cd") then
- if ".." == currentSubject then
- returnTrip, newNotice = ascendDirectory();
- else
- table.insert(pathIndexStack, { pageIdx = pageIdx_, lineIdx = lineIdx_ });
- shell.setDir(shell.dir() .. "/" .. currentSubject);
- newNotice = "descended. " .. shell.dir();
- end
- directoryChanged = true;
- elseif startsWith(currentAction, "delete") then
- if "." == currentSubject or ".." == currentSubject then
- newNotice = currentSubject .. " cannot delete.";
- else
- resetTerm();
- print("[delete] " .. currentSubject);
- print("Do you really want to delete this file?");
- term.write("[y]es / [n]o >");
- if "y" == read() then
- shell.run("delete", currentSubject);
- newNotice = currentSubject .. " was (maybe) deleted.";
- directoryChanged = true;
- else
- newNotice = "delete canceled.";
- end
- end
- elseif startsWith(currentAction, "rename") then
- if "." == currentSubject or ".." == currentSubject then
- newNotice = currentSubject .. " cannot rename.";
- else
- resetTerm();
- print("[rename] " .. currentSubject);
- print("Enter new name.");
- print("To borrow original name, press [up] cursor key.");
- print("If you want to cancel renaming, enter blank.");
- term.write(">");
- local newName = read(nil, { currentSubject });
- if "" ~= newName then
- shell.run("rename", currentSubject, newName);
- newNotice = currentSubject .. " was (maybe) renamed.";
- directoryChanged = true;
- else
- newNotice = "rename canceled.";
- end
- end
- elseif startsWith(currentAction, "copy") then
- if "." == currentSubject or ".." == currentSubject then
- newNotice = currentSubject .. " cannot copy.";
- else
- resetTerm();
- print("[copy] " .. currentSubject);
- print("Enter new name.");
- print("To borrow original name, press [up] cursor key.");
- print("If you want to cancel copy, enter blank.");
- term.write(">");
- local newName = read(nil, { currentSubject });
- if "" ~= newName then
- shell.run("copy", currentSubject, newName);
- newNotice = currentSubject .. " was (maybe) copied.";
- directoryChanged = true;
- else
- newNotice = "copy canceled.";
- end
- end
- elseif startsWith(currentAction, "move")
- and not startsWith(currentAction, "moveTo") then
- if "." == currentSubject or ".." == currentSubject then
- newNotice = currentSubject .. " cannot copy.";
- else
- moveToMode = true;
- newNotice = "<<move>> select moveTo directory.";
- directoryChanged = true;
- moveSrcPath = shell.dir() .. "/" .. currentSubject;
- pageIdx_ = 1;
- lineIdx_ = 1;
- toolIdx = 1;
- end
- elseif startsWith(currentAction, "cancel move") then
- moveToMode = false;
- newNotice = "move canceled.";
- directoryChanged = true;
- pageIdx_ = 1;
- lineIdx_ = 1;
- toolIdx = 1;
- elseif startsWith(currentAction, "moveTo") then
- local choice = "move / copy";
- local wrong = false;
- local moveDstPath;
- if "." == currentSubject then
- moveDstPath = shell.dir();
- elseif ".." == currentSubject then
- moveDstPath = getParentPath(shell.dir());
- else
- moveDstPath = shell.dir() .. "/" .. currentSubject;
- end
- while true do
- resetTerm();
- print("[" .. choice .. "]");
- print("source :");
- print(" " .. moveSrcPath);
- print("destination :");
- print(" " .. moveDstPath);
- print("select move or copy.");
- if wrong then
- wrong = false;
- print("*** Wrong input. Please retry.");
- end
- print(" copy : input \"c\" and hit enter key.");
- print(" move : hit enter key with no input.");
- print(" or [r]eselect destination directory.");
- print(" or [q]uit. (cancel move or copy.)");
- term.write(">");
- local input = read();
- if "c" == input then
- choice = "copy";
- break;
- elseif "" == input then
- choice = "move";
- break;
- elseif "r" == input then
- choice = "reselect";
- break;
- elseif "q" == input then
- choice = "quit";
- break;
- else
- wrong = true;
- end
- end
- if "copy" == choice then
- shell.run("copy", moveSrcPath, moveDstPath);
- newNotice = "The copy was successful maybe.";
- elseif "move" == choice then
- shell.run("move", moveSrcPath, moveDstPath);
- newNotice = "The move was successful maybe.";
- elseif "reselect" == choice then
- newNotice = "<<move>> select moveTo directory.";
- toolIdx = 1;
- elseif "quit" == choice then
- newNotice = "copy canceled.";
- end
- if "reselect" ~= choice then
- moveToMode = false;
- directoryChanged = true;
- pageIdx_ = 1;
- lineIdx_ = 1;
- toolIdx = 1;
- end
- elseif startsWith(currentAction, "[other]") then
- if "." == currentSubject or ".." == currentSubject then
- newNotice = currentSubject .. " cannot [other].";
- else
- resetTerm();
- local stage = 1;
- local input = "";
- local ret;
- while true do
- print("[other]");
- local hist = { };
- table.insert(hist, currentSubject);
- table.insert(hist, currentSubject .. " " .. currentSubject);
- if "" ~= input then
- table.insert(hist, input);
- end
- if 1 == stage then
- print("Input command.");
- term.write(">");
- input = read(nil, hist);
- if "" == input then
- newNotice = "[other] canceled.";
- break;
- else
- stage = 2;
- end
- elseif 2 == stage then
- print("command = ");
- print(input);
- print("");
- print("execute? [y]es, [e]dit, [c]ancel");
- term.write(">");
- local ch = read();
- if "y" == ch then
- ret = shell.run(input);
- newNotice = "[other] returned " .. tostring(ret);
- break;
- elseif "e" == ch then
- stage = 1;
- elseif "c" == ch then
- newNotice = "[other] canceled.";
- break;
- end
- end
- end
- end
- end
- return directoryChanged, pathIndexStack, returnTrip, newNotice, moveToMode,
- pageIdx_, lineIdx_, toolIdx, moveSrcPath;
- end
- local SPACE = " ";
- local pageIdx = 1;
- local lineIdx = 1;
- local toolIdx = 1;
- local pageMode = true;
- local tools = { dir = { "cd --> ", "delete --> ", "rename --> ",
- "copy --> ", "move --> ", "[other] --> "},
- file = { "edit --> ", "delete --> ", "rename --> ",
- "copy --> ", "move --> ", "[other] --> "},
- move = { "cd --> ", "moveTo --> ", "cancel move " } };
- local directoryChanged;
- local pages;
- local width, height = term.getSize();
- local returnTrip = false;
- local pathIndexStack = { };
- local initialDir = shell.dir();
- local miniHelp = { true_ = "[q]uit, up/down=paging, [->]=line mode",
- false_ = "[->]=change action, enter=exec action" };
- local statusBarText = "";
- local newNotice = "";
- local moveToMode = false;
- local directoryOnlyFlg = false;
- local moveSrcPath = "";
- local KNtC = { };
- for i = 0, 256 do
- local name = keys.getName(i);
- if nil ~= name then
- KNtC[name] = i;
- end
- end
- directoryChanged = true;
- while true do
- if moveToMode then
- directoryOnlyFlg = true;
- else
- directoryOnlyFlg = false;
- end
- if directoryChanged then
- pages = makePageData(width, height, directoryOnlyFlg);
- pageIdx = math.min(#pages, pageIdx);
- lineIdx = math.min(#pages[pageIdx], lineIdx);
- if returnTrip and #pathIndexStack then
- local o = table.remove(pathIndexStack);
- pageIdx = o.pageIdx;
- lineIdx = o.lineIdx;
- end
- returnTrip = false;
- directoryChanged = false;
- end
- local currentLineIsDir;
- local currentAction = "";
- local currentSubject;
- local toolSetKey;
- resetTerm();
- for i, val in ipairs(pages[pageIdx]) do
- term.setCursorPos(1, i);
- local arrow = "";
- if not pageMode then
- lineIdx = math.min(lineIdx, #pages[pageIdx]);
- if moveToMode then
- toolSetKey = "move";
- else
- if val.isDir then
- toolSetKey = "dir";
- else
- toolSetKey = "file";
- end
- end
- if i == lineIdx then
- arrow = tools[toolSetKey][toolIdx];
- currentAction = arrow;
- currentLineIsDir = val.isDir;
- currentSubject = val.name;
- else
- arrow = SPACE:rep(#tools[toolSetKey][toolIdx]);
- end
- end
- if val.isDir then
- term.write(arrow .. "<dir> " .. val.name
- .. SPACE:rep(math.max(0, width - (#arrow + #val.name))));
- else
- term.write(arrow .. val.name
- .. SPACE:rep(math.max(0, width - (#arrow + #val.name))));
- end
- end
- for i = #pages[pageIdx] + 1, height do
- term.setCursorPos(1, i);
- term.write(SPACE:rep(width));
- end
- term.setCursorPos(1, height);
- term.setTextColor(colors.black);
- term.setBackgroundColor(colors.white);
- if not moveToMode then
- if "" ~= newNotice then
- statusBarText = newNotice;
- newNotice = "";
- else
- statusBarText = miniHelp[tostring(pageMode) .. "_"];
- end
- else
- statusBarText = newNotice;
- end
- term.write(statusBarText .. SPACE:rep(math.max(0, width - #statusBarText)));
- local easyExitFlg = false;
- while true do
- local event, scanCode = os.pullEvent("key");
- -- key name
- -- http://computercraft.info/wiki/Keys_(API)
- if isOneOf(scanCode, { KNtC.up, KNtC.p, KNtC.b, KNtC.w, KNtC.a }) then
- pageIdx, lineIdx, newNotice
- = pagingAction(true, pageMode, pageIdx, lineIdx, pages, newNotice);
- break;
- elseif isOneOf(scanCode,
- { KNtC.down, KNtC.n, KNtC.f, KNtC.s, KNtC.d, KNtC.space }) then
- pageIdx, lineIdx, newNotice
- = pagingAction(false, pageMode, pageIdx, lineIdx, pages, newNotice);
- break;
- elseif isOneOf(scanCode, { KNtC.right }) then
- if not pageMode then
- toolIdx = (toolIdx % #tools[toolSetKey]) + 1;
- if startsWith(
- tools[toolSetKey][toolIdx], "copy") then
- newNotice = "The copy on the same directory.";
- elseif startsWith(tools[toolSetKey][toolIdx], "move")
- and not startsWith(tools[toolSetKey][toolIdx], "moveTo") then
- newNotice = "Move (or copy) to other directory.";
- elseif startsWith(tools[toolSetKey][toolIdx], "[other]") then
- newNotice = "A command can be executed manually.";
- end
- end
- pageMode = false;
- break;
- elseif isOneOf(scanCode, { KNtC.left }) then
- toolIdx = 1;
- if pageMode then
- returnTrip, newNotice = ascendDirectory();
- directoryChanged = returnTrip;
- end
- if not moveToMode then
- pageMode = true;
- end
- break;
- elseif isOneOf(scanCode, { KNtC.q, KNtC.e }) then
- prepareExit(initialDir);
- return;
- elseif isOneOf(scanCode, { KNtC.enter }) then
- directoryChanged, pathIndexStack, returnTrip, newNotice, moveToMode,
- pageIdx, lineIdx, toolIdx, moveSrcPath
- = lineModeAction(currentAction, currentSubject, pathIndexStack,
- pageIdx, lineIdx, toolIdx, moveToMode, moveSrcPath);
- break;
- end
- sleep(0.5);
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement