Computer Craft のメモ
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
ただいまコメントを受けつけておりません。
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