moving everything neatly into the assets directory

This commit is contained in:
minjaesong
2020-12-24 11:00:32 +09:00
parent 74b1279ed4
commit 608f61c617
111 changed files with 98 additions and 28 deletions

View File

@@ -0,0 +1,3 @@
// load a BASIC rom
sys.mapRom(1);
execApp(sys.romReadAll());

View File

@@ -0,0 +1,454 @@
let PROMPT_TEXT = ">";
let CURRENT_DRIVE = "A";
let shell_pwd = [""];
let goInteractive = false;
let goFancy = false;
let DEBUG_PRINT = true;
let errorlevel = 0;
const welcome_text = "TSVM Disk Operating System, version " + _TVDOS.VERSION;
function print_prompt_text() {
if (goFancy) {
con.color_pair(239,161);
print(" "+CURRENT_DRIVE+":");
con.color_pair(161,253);
con.addch(16);
con.color_pair(0,253);
print(" \\"+shell_pwd.join("\\").substring(1)+" ");
if (errorlevel != 0) {
con.color_pair(166,253);
print("["+errorlevel+"] ");
}
con.color_pair(253,255);
con.addch(16);
con.addch(32);
con.color_pair(239,255);
}
else {
if (errorlevel != 0)
print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + " [" + errorlevel + "]" + PROMPT_TEXT);
else
print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + PROMPT_TEXT);
}
}
function greet() {
if (goFancy) {
con.color_pair(0,253);
//print(welcome_text + " ".repeat(_fsh.scrwidth - welcome_text.length));
print(welcome_text + " ".repeat(80 - welcome_text.length));
con.color_pair(239,255);
println();
}
else
println(welcome_text);
}
function trimStartRevSlash(s) {
var cnt = 0;
while (cnt < s.length) {
var chr = s[cnt];
if (chr != '\\') break;
cnt += 1;
}
return s.substring(cnt);
}
let shell = {};
shell.getPwd = function() { return shell_pwd; }
shell.getCurrentDrive = function() { return CURRENT_DRIVE; }
// example input: echo "the string" > subdir\test.txt
shell.parse = function(input) {
var tokens = [];
var stringBuffer = "";
var mode = "LITERAL"; // LITERAL, QUOTE, ESCAPE, LIMBO
var i = 0
while (i < input.length) {
const c = input[i];
/*digraph g {
LITERAL -> QUOTE [label="\""]
LITERAL -> LIMBO [label="space"]
LITERAL -> LITERAL [label=else]
QUOTE -> LIMBO [label="\""]
QUOTE -> ESCAPE [label="\\"]
QUOTE -> QUOTE [label=else]
ESCAPE -> QUOTE
LIMBO -> LITERAL [label="not space"]
LIMBO -> QUOTE [label="\""]
LIMBO -> LIMBO [label="space"]
}*/
if ("LITERAL" == mode) {
if (' ' == c) {
tokens.push(stringBuffer); stringBuffer = "";
mode = "LIMBO";
}
else if ('"' == c) {
tokens.push(stringBuffer); stringBuffer = "";
mode = "QUOTE";
}
else {
stringBuffer += c;
}
}
else if ("LIMBO" == mode) {
if ('"' == c) {
mode = "QUOTE";
}
else if (c != ' ') {
mode = "LITERAL";
stringBuffer += c;
}
}
else if ("QUOTE" == mode) {
if ('"' == c) {
tokens.push(stringBuffer); stringBuffer = "";
mode = "LIMBO";
}
else if ('^' == c) {
mode = "ESCAPE";
}
else {
stringBuffer += c;
}
}
else if ("ESCAPE" == mode) {
TODO();
}
i += 1;
}
if (stringBuffer.length > 0) {
tokens.push(stringBuffer);
}
return tokens;
}
shell.resolvePathInput = function(input) {
// replace slashes into revslashes
var pathstr = input.replaceAll('/','\\\\');
var startsWithSlash = input.startsWith('\\');
var newPwd = [];
// split them into an array while filtering empty elements except for the root 'head'
var ipwd = (startsWithSlash ? [""] : shell_pwd).concat(pathstr.split("\\").filter(function(it) { return (it.length > 0); }));
serial.println("command.js > resolvePathInput > ipwd = "+ipwd);
serial.println("command.js > resolvePathInput > newPwd = "+newPwd);
// process dots
ipwd.forEach(function(it) {
serial.println("command.js > resolvePathInput > ipwd.forEach > it = "+it);
if (it === ".." && newPwd[1] !== undefined) {
newPwd.pop();
}
else if (it !== ".." && it !== ".") {
newPwd.push(it);
}
serial.println("command.js > resolvePathInput > newPwd = "+newPwd);
});
// construct new pathstr from pwd arr so it will be sanitised
pathstr = newPwd.join('\\').substring(1);
return { string: pathstr, pwd: newPwd };
}
shell.coreutils = {
/* Args follow this format:
* <command-name> <1st arg> <2nd arg> ...
* NOTE:
* even if there's no 1st arg, length of args may not be 1, therefore don't:
* if (args.length < 2)
* but do instead:
* if (args[1] === undefined)
*/
cd: function(args) {
if (args[1] === undefined) {
println(CURRENT_DRIVE+":"+shell_pwd.join("\\"));
return
}
var path = shell.resolvePathInput(args[1])
if (DEBUG_PRINT) serial.println("command.js > cd > pathstr = "+path.string);
// check if path is valid
filesystem.open(CURRENT_DRIVE, path.string, 'R');
var dirOpened = filesystem.isDirectory(CURRENT_DRIVE); // open a dir; if path is nonexistent, file won't actually be opened
if (!dirOpened) { printerrln("CHDIR failed for '"+path.string+"'"); return; } // if file is not opened, FALSE will be returned
shell_pwd = path.pwd;
},
mkdir: function(args) {
if (args[1] === undefined) {
printerrln("Syntax error");
return
}
var path = shell.resolvePathInput(args[1])
if (DEBUG_PRINT) serial.println("command.js > mkdir > pathstr = "+path.string);
// check if path is valid
var dirOpened = filesystem.open(CURRENT_DRIVE, path.string, 'W');
var mkdird = filesystem.mkDir(CURRENT_DRIVE);
if (!mkdird) { printerrln("MKDIR failed for '"+path.string+"'"); return; }
},
cls: function(args) {
con.clear();
},
exit: function(args) {
cmdExit = true;
},
ver: function(args) {
println(welcome_text);
},
echo: function(args) {
if (args[1] !== undefined) {
args.forEach(function(it,i) { if (i > 0) print(it+" ") });
}
println();
},
rem: function(args) {
return 0;
},
set: function(args) {
// print all the env vars
if (args[1] === undefined) {
Object.entries(_TVDOS.variables).forEach(function(a) { println(a[0]+"="+a[1]); })
}
else {
// parse key-value pair with splitter '='
var key = undefined; var value = undefined;
// if syntax "<key> = <value>" is used?
if ('=' == args[2]) {
key = args[1].toUpperCase(); value = args[3];
}
else if (args[2] === undefined) {
var pair = args[1].split('=');
key = pair[0].toUpperCase(); value = pair[1];
}
if (key == undefined) throw SyntaxError("Input format must be 'key=value'");
// if value is undefined, show what envvar[key] has
if (value === undefined) {
if (_TVDOS.variables[key] === undefined)
println("Environment variable '"+key+"' not found");
else
println(_TVDOS.variables[key])
}
else {
// TODO parse %var_name% line
_TVDOS.variables[key] = value;
}
}
},
dir: function(args) {
var pathstr = (args[1] !== undefined) ? args[1] : "\\"+shell_pwd.join("\\");
// check if path is valid
var pathOpened = filesystem.open(CURRENT_DRIVE, pathstr, 'R');
if (!pathOpened) { printerrln("File not found"); return; }
var port = filesystem._toPorts(CURRENT_DRIVE)[0]
com.sendMessage(port, "LIST");
println(com.pullMessage(port));
}
};
shell.coreutils.chdir = shell.coreutils.cd;
Object.freeze(shell.coreutils);
shell.execute = function(line) {
if (0 == line.size) return;
var tokens = shell.parse(line);
var cmd = tokens[0];
if (cmd === undefined || cmd === '') return 0;
// handle Ctrl-C
if (con.hitterminate()) return 1;
if (shell.coreutils[cmd.toLowerCase()] !== undefined) {
var retval = shell.coreutils[cmd.toLowerCase()](tokens);
return retval|0; // return value of undefined will cast into 0
}
else {
// search through PATH for execution
var fileExists = false;
var searchDir = (cmd.startsWith("\\")) ? [""] : ["\\"+shell_pwd.join("\\")].concat(_TVDOS.getPath());
var pathExt = []; // it seems Nashorn does not like 'let' too much? this line gets ignored sometimes
// fill pathExt using %PATHEXT% but also capitalise them
if (cmd.split(".")[1] === undefined)
_TVDOS.variables.PATHEXT.split(';').forEach(function(it) { pathExt.push(it); pathExt.push(it.toUpperCase()); });
else
pathExt.push(""); // final empty extension
searchLoop:
for (var i = 0; i < searchDir.length; i++) {
for (var j = 0; j < pathExt.length; j++) {
var search = searchDir[i]; if (!search.endsWith('\\')) search += '\\';
var path = trimStartRevSlash(search + cmd + pathExt[j]);
if (DEBUG_PRINT) {
serial.println("[command.js > shell.execute] file search path: "+path);
}
if (filesystem.open(CURRENT_DRIVE, path, "R")) {
fileExists = true;
break searchLoop;
}
}
}
if (!fileExists) {
printerrln('Bad command or filename: "'+cmd+'"');
return 127;
}
else {
var programCode = filesystem.readAll(CURRENT_DRIVE);
var extension = undefined;
// get proper extension
var dotSepTokens = cmd.split('.');
if (dotSepTokens.length > 1) extension = dotSepTokens[dotSepTokens.length - 1].toUpperCase();
if ("BAT" == extension) {
// parse and run as batch file
var lines = programCode.split('\n').filter(function(it) { return it.length > 0; });
lines.forEach(function(line) {
shell.execute(line);
});
}
else {
return execApp(programCode, tokens)|0; // return value of undefined will cast into 0
}
}
}
};
Object.freeze(shell);
_G.shell = shell;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (exec_args[1] !== undefined) {
// only meaningful switches would be either /c or /k anyway
var firstSwitch = exec_args[1].toLowerCase();
// command /c <commands>
// ^[0] ^[1] ^[2]
if ("/c" == firstSwitch) {
if ("" == exec_args[2]) return 0; // no commands were given, just exit successfully
return shell.execute(exec_args[2]);
}
else if ("/k" == firstSwitch) {
if ("" == exec_args[2]) return 0; // no commands were given, just exit successfully
shell.execute(exec_args[2]);
goInteractive = true;
}
else if ("/fancy" == firstSwitch) {
goFancy = true;
goInteractive = true;
}
else {
printerrln("Invalid switch: "+exec_args[1]);
return 1;
}
}
else {
goInteractive = true;
}
let cmdExit = false;
if (goInteractive) {
con.reset_graphics();
greet();
let cmdHistory = []; // zeroth element is the oldest
let cmdHistoryScroll = 0; // 0 for outside-of-buffer, 1 for most recent
while (!cmdExit) {
con.reset_graphics();
print_prompt_text();
var cmdbuf = "";
while (true) {
var key = con.getch();
// printable chars
if (key >= 32 && key <= 126) {
var s = String.fromCharCode(key);
cmdbuf += s;
print(s);
}
// backspace
else if (key === 8 && cmdbuf.length > 0) {
cmdbuf = cmdbuf.substring(0, cmdbuf.length - 1);
print(String.fromCharCode(key));
}
// enter
else if (key === 10 || key === 13) {
println();
try {
errorlevel = 0; // reset the number
errorlevel = shell.execute(cmdbuf);
if (isNaN(errorlevel)) errorlevel = 2;
}
catch (e) {
printerrln("\n"+e);
if (errorlevel === 0 || isNaN(errorlevel)) {
errorlevel = 1; // generic failure
}
}
finally {
if (cmdbuf.trim().length > 0)
cmdHistory.push(cmdbuf);
cmdHistoryScroll = 0;
con.curs_set(1);
break;
}
}
// up arrow
else if (key === 19 && cmdHistory.length > 0 && cmdHistoryScroll < cmdHistory.length) {
cmdHistoryScroll += 1;
// back the cursor in order to type new cmd
var x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll];
// re-type the new command
print(cmdbuf);
}
// down arrow
else if (key === 20) {
if (cmdHistoryScroll > 0) {
// back the cursor in order to type new cmd
var x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll];
// re-type the new command
print(cmdbuf);
cmdHistoryScroll -= 1;
}
else {
// back the cursor in order to type new cmd
var x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = "";
}
}
}
}
}
return 0;

View File

@@ -0,0 +1 @@
return 1;

View File

@@ -0,0 +1,106 @@
let CURRENT_DRIVE = "A";
let shell_pwd = [""];
const welcome_text = "TSVM Disk Operating System, version " + _TVDOS.VERSION;
function print_prompt_text() {
// oh-my-zsh-like prompt
con.color_pair(239,161);
print(" "+CURRENT_DRIVE+":");
con.color_pair(161,253);
con.addch(16);
con.color_pair(0,253);
print(" \\"+shell_pwd.join("\\")+" ");
con.color_pair(253,255);
con.addch(16);
con.addch(32);
con.color_pair(239,255);
}
function greet() {
con.color_pair(0,253);
//print(welcome_text + " ".repeat(_fsh.scrwidth - welcome_text.length));
print(welcome_text + " ".repeat(80 - welcome_text.length));
con.color_pair(239,255);
println();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
con.clear();
greet();
let cmdHistory = []; // zeroth element is the oldest
let cmdHistoryScroll = 0; // 0 for outside-of-buffer, 1 for most recent
while (true) {
print_prompt_text();
let cmdbuf = "";
while (true) {
let key = con.getch();
// printable chars
if (key >= 32 && key <= 126) {
let s = String.fromCharCode(key);
cmdbuf += s;
print(s);
}
// backspace
else if (key === 8 && cmdbuf.length > 0) {
cmdbuf = cmdbuf.substring(0, cmdbuf.length - 1);
print(String.fromCharCode(key));
}
// enter
else if (key === 10 || key === 13) {
println();
try {
println("You entered: " + cmdbuf);
}
catch (e) {
println(e);
}
finally {
if (cmdbuf.trim().length > 0)
cmdHistory.push(cmdbuf);
cmdHistoryScroll = 0;
break;
}
}
// up arrow
else if (key === 19 && cmdHistory.length > 0 && cmdHistoryScroll < cmdHistory.length) {
cmdHistoryScroll += 1;
// back the cursor in order to type new cmd
let x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll];
// re-type the new command
print(cmdbuf);
}
// down arrow
else if (key === 20) {
if (cmdHistoryScroll > 0) {
// back the cursor in order to type new cmd
let x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll];
// re-type the new command
print(cmdbuf);
cmdHistoryScroll -= 1;
}
else {
// back the cursor in order to type new cmd
let x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = "";
}
}
}
}

View File

@@ -0,0 +1,131 @@
graphics.setBackground(3,3,3);
graphics.resetPalette();
function captureUserInput() {
sys.poke(-40, 1);
}
function getKeyPushed(keyOrder) {
return sys.peek(-41 - keyOrder);
}
var _fsh = {};
_fsh.titlebarTex = new GL.Texture(2, 14, base64.atob("/u/+/v3+/f39/f39/f39/f39/P39/Pz8/Pv7+w=="));
_fsh.scrdim = con.getmaxyx();
_fsh.scrwidth = _fsh.scrdim[1];
_fsh.scrheight = _fsh.scrdim[0];
_fsh.brandName = "f\xb3Sh";
_fsh.brandLogoTexSmall = new GL.Texture(24, 14, gzip.decomp(base64.atob(
"H4sIAAAAAAAAAPv/Hy/4Qbz458+fIeILQQBIwoSh6qECuMVBukCmIJkDVQ+RQNgLE0MX/w+1lyhxqIUwTLJ/sQMAcIXsbVABAAA="
)));
_fsh.scrlayout = ["com.fsh.clock","com.fsh.calendar","com.fsh.apps_n_files"];
_fsh.drawTitlebar = function(titletext) {
GL.drawTexPattern(_fsh.titlebarTex, 0, 0, 560, 14);
if (titletext === undefined || titletext.length == 0) {
con.move(1,1);
print(" ".repeat(_fsh.scrwidth));
GL.drawTexImageOver(_fsh.brandLogoTexSmall, 268, 0);
}
else {
con.color_pair(240, 255);
GL.drawTexPattern(_fsh.titlebarTex, 268, 0, 24, 14);
con.move(1, 1 + (_fsh.scrwidth - titletext.length) / 2);
print(titletext);
}
con.color_pair(254, 255);
};
_fsh.Widget = function(id, w, h) {
this.identifier = id;
this.width = w;
this.height = h;
if (!this.identifier) {
this.identifier = "";
}
//this.update = function() {};
/**
* Params charXoff and charYoff are ZERO-BASED!
*/
this.draw = function(charXoff, charYoff) {};
}
_fsh.widgets = {}
_fsh.registerNewWidget = function(widget) {
_fsh.widgets[widget.identifier] = widget;
}
var clockWidget = new _fsh.Widget("com.fsh.clock", _fsh.scrwidth - 8, 7);
clockWidget.numberSheet = new GL.SpriteSheet(19, 22, new GL.Texture(190, 22, gzip.decomp(base64.atob(
"H4sIAAAAAAAAAMWVW3LEMAgE739aHcFJJV5ZMD2I9ToVfcl4GBr80HF8r/FaR1ozMuIyoUu87lEXI0al5qVR5AebSwchSaNE6Nyo1Nw5HXF3SfPT4Bshl"+
"EycA8RD96mLlHbuhTgOrfLnUDZspafbSQWk56WEGvQEtWaWwgb8iz7a8AOXhsraO/q9Qw2/GnXovfVN+q2wM/p/oddn2cjF239GX3y11+SWCtc6FTHC1v"+
"TVPkDPWWn0w+DDz93UX9v9mF5KIsQ6OdN2KJoB4ui1bXXr0AMp0YfiQo//4XhpK8555dsNehAqVS5uhb5iHn3Kko769J59KmLBe/TSR7hcsd+hr+HnrwR"+
"9uvRF9+D3MP14gN7lqx+8OuNT+uqt3NFX3SN9fTbeeHNq+C29pRWzX5+Rcm7SZyjOKJ/2hkSPqul4xN279DrSYvCrNu2NI7ZMp1ouBxK3KBVVnEeAUWbK"+
"MUDn5DPsPxmUqHZQjGpy2hergM3EVBAAAA=="
))));
clockWidget.clockColon = new GL.Texture(4, 3, base64.atob("7+/v7+/v7+/v7+/v"));
clockWidget.monthNames = ["Spring", "Summer", "Autumn", "Winter"];
clockWidget.dayNames = ["Mondag ", "Tysdag ", "Midtveke", "Torsdag ", "Fredag ", "Laurdag ", "Sundag ", "Verddag "];
clockWidget.draw = function(charXoff, charYoff) {
con.color_pair(254, 255);
var xoff = charXoff * 7;
var yoff = charYoff * 14 + 3;
var timeInMinutes = ((sys.currentTimeInMills() / 60000)|0);
var mins = timeInMinutes % 60;
var hours = ((timeInMinutes / 60)|0) % 24;
var ordinalDay = ((timeInMinutes / (60*24))|0) % 120;
var visualDay = (ordinalDay % 30) + 1;
var months = ((timeInMinutes / (60*24*30))|0) % 4;
var dayName = ordinalDay % 7; // 0 for Mondag
if (ordinalDay == 119) dayName = 7; // Verddag
var years = ((timeInMinutes / (60*24*30*120))|0) + 125;
// draw timepiece
GL.drawSprite(clockWidget.numberSheet, (hours / 10)|0, 0, xoff, yoff);
GL.drawSprite(clockWidget.numberSheet, hours % 10, 0, xoff + 24, yoff);
GL.drawTexImage(clockWidget.clockColon, xoff + 48, yoff + 5);
GL.drawTexImage(clockWidget.clockColon, xoff + 48, yoff + 14);
GL.drawSprite(clockWidget.numberSheet, (mins / 10)|0, 0, xoff + 57, yoff);
GL.drawSprite(clockWidget.numberSheet, mins % 10, 0, xoff + 81, yoff);
// print month and date
con.move(1 + charYoff, 17 + charXoff);
print(clockWidget.monthNames[months]+" "+visualDay);
// print year and dayname
con.mvaddch(2 + charYoff, 17 + charXoff, 5);
con.move(2 + charYoff, 18 + charXoff);
print(years+" "+clockWidget.dayNames[dayName]);
};
// register widgets
_fsh.registerNewWidget(clockWidget);
// screen init
con.color_pair(254, 255);
con.clear();
con.curs_set(0);
_fsh.drawTitlebar();
// TEST
con.move(2,1);
print("Hit backspace to exit");
while (true) {
captureUserInput();
if (getKeyPushed(0) == 67) break;
_fsh.widgets["com.fsh.clock"].draw(25, 2);
}
con.move(3,1);
con.color_pair(201,255);
print("cya!");
let konsht = 3412341241;
println(konsht);
let pppp = graphics.getCursorYX();
println(pppp.toString());

View File

@@ -0,0 +1,20 @@
if (exec_args[1] === undefined) {
printerrln("Usage: hexdump <file>")
return 1;
}
let fileOpened = filesystem.open(_G.shell.getCurrentDrive(), _G.shell.resolvePathInput(exec_args[1]).string, "R");
if (!fileOpened) {
printerrln(_G.shell.resolvePathInput(exec_args[1]).string+": cannot open");
return 1;
}
let fileContent = filesystem.readAll(_G.shell.getCurrentDrive());
let visible = "";
for (let k = 0; k < fileContent.length; k++) {
if (k > 0 && k % 16 == 0) visible += "\n";
visible += `${fileContent.charCodeAt(k).toString(16).toUpperCase().padStart(2, '0')} `;
}
println(visible);
return 0;

View File

@@ -0,0 +1,143 @@
if (exec_args[1] === undefined) {
println('Missing filename ("less -?" for help)');
return 0;
}
/*let help = "\n
SUMMARY OF COMMANDS\n
\n
h H Display this help\n
q Q Exit
\n"*/
if (exec_args[1].startsWith("-?")) {
println("less <filename>");
return 0;
}
let fileOpened = filesystem.open(_G.shell.getCurrentDrive(), _G.shell.resolvePathInput(exec_args[1]).string, "R");
if (!fileOpened) {
printerrln(_G.shell.resolvePathInput(exec_args[1]).string+": cannot open");
return 1;
}
let scroll = 0;
let pan = -1;
let termW = con.getmaxyx()[1];
let termH = con.getmaxyx()[0] - 1;
let buf = "";
let fileContent = filesystem.readAll(_G.shell.getCurrentDrive());
let key = -1;
let panSize = termW >> 1;
let scrollSize = termH >> 3;
// initialise some helper variables
let lineToBytes = [0];
let maxPan = 0;
let maxPanCur = 0;
for (let i = 0; i < fileContent.length; i++) {
let char = fileContent.charCodeAt(i);
maxPanCur += 1;
if (char == 10 || char == 13) {
lineToBytes.push(i + 1);
if (maxPanCur > maxPan) maxPan = maxPanCur;
maxPanCur = 0;
}
}
let startAddr = -1;
let paintCur = 0;
let cy = 1;
let cx = 1;
let char = -1;
let numbuf = 0;
let resetKeyReadStatus = function() {
numbuf = 0;
}
let repaint = function() {
con.move(1,1); con.clear();
startAddr = lineToBytes[scroll];
cy = 1; cx = -pan; paintCur = 0;
while (cy <= termH) {
char = fileContent.charCodeAt(startAddr + paintCur);
if (isNaN(char)) break;
if (cy <= termH) {
if (cx >= 0 && cx < termW) {
con.move(cy, cx);
if (char != 10 && char != 13)
con.addch(char);
}
cx += 1;
}
if (char == 10 || char == 13) {
cy += 1;
cx = -pan;
}
paintCur += 1;
}
}
repaint();
con.move(termH + 1, 1);
print(":"+" ".repeat(termW - 2));
con.move(termH + 1, 2);
while (true) {
// read a key
key = con.getch();
// do something with key read
/*Q*/if (key == 113 || key == 81) break;
/*R*/else if (key == 114 || key == 82) repaint();
/*up*/else if (key == 19) {
scroll -= scrollSize;
if (scroll < 0) scroll = 0;
repaint();
}
/*down*/else if (key == 20) {
scroll += scrollSize;
if (scroll > lineToBytes.length - termH) scroll = lineToBytes.length - termH;
repaint();
}
/*left*/else if (key == 21 && pan > 0) {
pan -= panSize;
repaint();
}
/*right*/else if (key == 22 && pan < maxPan - termW) {
pan += panSize;
repaint();
}
/*0-9*/else if (key >= 48 && key <= 57) {
print(String.fromCharCode(key));
numbuf = (numbuf * 10) + (key - 48);
}
/*bksp*/else if (key == 8) {
if (numbuf > 0) print(String.fromCharCode(key));
numbuf = (numbuf / 10)|0;
}
/*u*/else if (key == 117) {
scroll -= numbuf;
if (scroll < 0) scroll = 0;
repaint();
}
/*d*/else if (key == 100) {
scroll += numbuf;
if (scroll > lineToBytes.length - termH) scroll = lineToBytes.length - termH;
repaint();
}
if (!(key >= 48 && key <= 57 || key == 8)) {
resetKeyReadStatus();
con.move(termH + 1, 1);
print(":"+" ".repeat(termW - 2));
con.move(termH + 1, 2);
}
serial.println("numbuf = "+numbuf);
}
con.move(termH + 1, 1);
return 0;

View File

@@ -0,0 +1,30 @@
if (exec_args[1] === undefined) {
println("TOUCH - TVDOS file date and time setting utility");
println()
println("SYNOPSIS")
println(" TOUCH [/C] path")
println()
println("/C = don't create files that do not already exist")
return 1;
}
let path = _G.shell.resolvePathInput(exec_args[2] || exec_args[1]).string;
let driveLetter = _G.shell.getCurrentDrive();
let noNewFile = (exec_args[1] == "/c" || exec_args[1] == "/C");
let fileOpened = filesystem.open(driveLetter, path, "W");
if (!fileOpened) {
printerrln("TOUCH: Can't open "+driveLetter+":\\"+path+" due to IO error");
return 1;
}
if (!noNewFile) {
filesystem.mkFile(driveLetter);
}
let touched = filesystem.touch(driveLetter);
if (!touched) {
printerrln("TOUCH: Can't touch "+driveLetter+":\\"+path+" due to IO error");
return 1;
}
return 0;

View File

@@ -0,0 +1 @@
return 0;