Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from ctruLua/lsh
Replacing the old shell with LSH
- Loading branch information
Showing
3 changed files
with
242 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
-- LSH version 0.1 | ||
-- ctrµLua official shell | ||
|
||
local ctr = require("ctr") | ||
local gfx = require("ctr.gfx") | ||
|
||
local function saveGraphicsState() | ||
local old = {gfx.get3D(), gfx.color.getDefault(), gfx.color.getBackground(), | ||
gfx.font.getDefault()} | ||
|
||
local mono = gfx.font.load(ctruLua.root .. "resources/VeraMono.ttf") | ||
|
||
gfx.set3D(false) | ||
gfx.color.setDefault(0xFFFDFDFD) | ||
gfx.color.setBackground(0xFF333333) | ||
gfx.font.setDefault(mono) | ||
|
||
return old | ||
end | ||
|
||
local function restoreGraphicsState(state) | ||
gfx.set3D(state[1]) | ||
gfx.color.setDefault(state[2]) | ||
gfx.color.setBackground(state[3]) | ||
gfx.font.setDefault(state[4]) | ||
end | ||
|
||
local function getExtension(sel, bindings) | ||
for _, ext in ipairs(bindings) do | ||
if ext.ext == sel:match("%..+$") then | ||
return ext | ||
end | ||
end | ||
end | ||
|
||
local function getFilelist(cur) | ||
local files = ctr.fs.list(cur) | ||
|
||
if cur ~= "/" and cur ~= "sdmc:/" then | ||
table.insert(files, {name = "..", isDirectory = true}) | ||
end | ||
|
||
-- Stealy stealing code from original openfile.lua | ||
table.sort(files, function(i, j) | ||
if i.isDirectory and not j.isDirectory then | ||
return true | ||
elseif i.isDirectory == j.isDirectory then | ||
return string.lower(i.name) < string.lower(j.name) | ||
end | ||
end) | ||
|
||
return files | ||
end | ||
|
||
local function drawBottom(cur, selFile, bindings) | ||
local ext = getExtension(selFile.name, bindings) | ||
|
||
gfx.start(gfx.BOTTOM) | ||
gfx.rectangle(0, 0, gfx.BOTTOM_WIDTH, 16, 0, 0xFF0000B3) | ||
gfx.text(1, 0, cur, 12) | ||
gfx.text(1, 15, selFile.name, 12) | ||
if not selFile.isDirectory then | ||
gfx.text(1, 45, selFile.fileSize, 12) | ||
end | ||
|
||
local keys = {"X: Quit/Cancel"} | ||
if selFile.isDirectory then | ||
gfx.text(1, 30, "Directory", 12, 0xFF727272) | ||
gfx.text(1, gfx.BOTTOM_HEIGHT - 30, "A: Open", 12) | ||
gfx.text(1, gfx.BOTTOM_HEIGHT - 15, keys[1], 12) | ||
elseif ext then | ||
local lines = 1 | ||
|
||
-- Keys | ||
if ext.y then | ||
lines = lines + 1 | ||
table.insert(keys, "Y: " .. ext.y) | ||
end | ||
if ext.a then | ||
lines = lines + 1 | ||
table.insert(keys, "A: " .. ext.a) | ||
end | ||
|
||
-- Drawing | ||
for i=lines, 1, -1 do | ||
gfx.text(1, gfx.BOTTOM_HEIGHT - 15*i, keys[i], 12) | ||
end | ||
gfx.text(1, 30, ext.name, 12, 0xFF727272) | ||
gfx.text(1, 45, tostring(selFile.fileSize) .. "B", 12, 0xFF727272) | ||
else | ||
gfx.text(1, 30, "File", 12, 0xFF727272) | ||
gfx.text(1, 45, tostring(selFile.fileSize) .. "B", 12, 0xFF727272) | ||
gfx.text(1, gfx.BOTTOM_HEIGHT - 15, keys[1], 12) | ||
end | ||
gfx.stop() | ||
end | ||
|
||
local function drawTop(files, sel, scr) | ||
gfx.start(gfx.TOP) | ||
gfx.rectangle(0, (sel-scr-1)*15, gfx.TOP_WIDTH, 16, 0, 0xFF0000B3) | ||
local over = #files - scr >= 16 and 16 or #files - scr | ||
for i=scr+1, scr+over do | ||
local color = files[i].isDirectory and 0xFF727272 or 0xFFFDFDFD | ||
gfx.text(1, (i-scr-1)*15+1, files[i].name or "", 12, color) | ||
end | ||
gfx.stop() | ||
end | ||
|
||
local function runA(cur, selFile, bindings) | ||
if not selFile.isDirectory then | ||
local ext = getExtension(selFile.name, bindings) | ||
if not ext then return end | ||
if ext.a then return cur .. selFile.name, ext.ext end | ||
end | ||
end | ||
|
||
local function runY(cur, selFile, bindings) | ||
if not selFile.isDirectory then | ||
local ext = getExtension(selFile.name, bindings) | ||
if not ext then return end | ||
if ext.y then return cur .. selFile.name, ext.ext end | ||
end | ||
end | ||
|
||
--- Open a file browser to allow the user to select a file. | ||
-- It will save current graphical settings and set them back after ending. Press up or down to move one element at a time, and press left or right to go at the beginning or at the end of the list. This function is the return result of requiring filepicker.lua | ||
-- @name filePicker | ||
-- @param bindings A table of the extensions the user can select in the format {{name, ext, a, y},...}, name will show up instead of "File" or "Directory" on the bottom screen, a and y set the action names for those keys on the bottom screen (and also enable them, so if there's neither a or y, the file will have a custom type name but won't be effectively selectable), and ext is the extension to search for, dot included. Everything must be strings. | ||
-- @param workdir Optional, current working directory will be used if not specified, otherwise, sets the path at which the file browser first shows up, a string. | ||
-- @returns The absolute path to the file, nil in case no file was picked. | ||
-- @returns The extension of the file, this might be helpful in cases were multiple file types could be expected, nil in case no file was picked. | ||
-- @returns The "mode", which indicates which key was used to select the file, "A" or "Y". "X" in case no file was picked. | ||
return function(bindings, workdir) | ||
-- Initialization | ||
local old = saveGraphicsState() | ||
local cur = workdir or ctr.fs.getDirectory() | ||
if cur:sub(-1) ~= "/" then | ||
cur = cur .. "/" | ||
end | ||
local bindings = bindings or {} | ||
|
||
local files = getFilelist(cur) or {{name = "- Empty -"}} | ||
local sel = 1 | ||
local scr = 0 | ||
|
||
while ctr.run() do | ||
drawBottom(cur, files[sel], bindings) | ||
drawTop(files, sel, scr) | ||
gfx.render() | ||
|
||
ctr.hid.read() | ||
local state = ctr.hid.keys() | ||
if (state.down.dDown or state.down.cpadDown) and sel < #files then | ||
sel = sel + 1 | ||
if sel - scr >= 16 then | ||
scr = scr + 1 | ||
end | ||
elseif (state.down.dUp or state.down.cpadUp) and sel > 1 then | ||
sel = sel - 1 | ||
if sel == scr then | ||
scr = scr - 1 | ||
end | ||
elseif state.down.dLeft or state.down.cpadLeft then | ||
sel = 1 | ||
scr = 0 | ||
elseif state.down.dRight or state.down.cpadRight then | ||
sel = #files | ||
if #files > 15 then | ||
scr = #files - 16 | ||
end | ||
|
||
elseif state.down.a then | ||
local selFile = files[sel] | ||
if selFile.isDirectory then | ||
if selFile.name == ".." then | ||
cur = cur:gsub("[^/]+/$", "") | ||
else | ||
cur = cur .. selFile.name .. "/" | ||
end | ||
files, sel, scr = getFilelist(cur), 1, 0 | ||
else | ||
local file, ext = runA(cur, selFile, bindings) | ||
if file then | ||
restoreGraphicsState(old) | ||
return file, ext, "A" | ||
end | ||
end | ||
elseif state.down.y then | ||
local file, ext = runY(cur, files[sel], bindings) | ||
if file then | ||
restoreGraphicsState(old) | ||
return file, ext, "Y" | ||
end | ||
elseif state.down.x then | ||
restoreGraphicsState(old) | ||
return nil, nil, "X" | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,53 @@ | ||
local ctr = require("ctr") | ||
local fs = require("ctr.fs") | ||
local gfx = require("ctr.gfx") | ||
local fs = require("ctr.fs") | ||
|
||
-- Initializing "constants" | ||
ctruLua = {} | ||
|
||
--- The ctruLua root directory's absolute path | ||
ctruLua.root = fs.getDirectory() | ||
|
||
-- Set up path | ||
local ldir = fs.getDirectory().."libs/" | ||
package.path = package.path..";".. ldir.."?.lua;".. ldir.."?/init.lua" | ||
|
||
repeat | ||
-- Erroring | ||
local function displayError(err) | ||
gfx.set3D(false) | ||
gfx.color.setBackground(0xFF0000B3) | ||
gfx.color.setDefault(0xFFFDFDFD) | ||
gfx.font.setDefault(gfx.font.load(ctruLua.root .. "resources/VeraMono.ttf")) | ||
|
||
while ctr.run() do | ||
gfx.start(gfx.TOP) | ||
gfx.text(1, 1, "An error has occured.", 12) | ||
gfx.wrappedText(1, 30, err, gfx.TOP_WIDTH-2, 12) | ||
gfx.text(1, gfx.TOP_HEIGHT-15, "Press Start to continue.", 12) | ||
gfx.stop() | ||
gfx.start(gfx.BOTTOM) | ||
gfx.stop() | ||
|
||
gfx.render() | ||
ctr.hid.read() | ||
if ctr.hid.keys().down.start then break end | ||
end | ||
end | ||
|
||
-- Main loop | ||
while ctr.run() do | ||
gfx.set3D(false) | ||
gfx.color.setDefault(0xFFFFFFFF) | ||
gfx.color.setBackground(0xFF000000) | ||
gfx.font.setDefault() | ||
local file = require("openfile")("Choose a Lua file to execute", nil, ".lua", "exist") | ||
if file then | ||
gfx.color.setDefault(0xFFFDFDFD) | ||
gfx.color.setBackground(0xFF333333) | ||
local file, ext, mode = require("filepicker")({{name="Lua Script", ext=".lua", a="Execute"}}) | ||
if file and mode == "A" then | ||
fs.setDirectory(file:match("^(.-)[^/]*$")) | ||
local success, err = pcall(dofile, file) | ||
if not success then | ||
local hid = require("ctr.hid") | ||
gfx.set3D(false) | ||
gfx.color.setDefault(0xFFFFFFFF) | ||
gfx.color.setBackground(0xFF000000) | ||
gfx.font.setDefault() | ||
while true do | ||
hid.read() | ||
if hid.keys().down.start then break end | ||
gfx.start(gfx.TOP) | ||
gfx.wrappedText(0, 0, err, gfx.TOP_WIDTH) | ||
gfx.stop() | ||
gfx.render() | ||
end | ||
end | ||
local ok, err = pcall(dofile, file) | ||
if not ok then displayError(err) end | ||
else | ||
break | ||
end | ||
until not file | ||
end | ||
|
||
error("Main process has exited.\nPlease reboot.\nPressing Start does not work yet.") |
Binary file not shown.