CLIte/clite/commands.js

494 lines
9.2 KiB
JavaScript

clite.commands.data = function() {
// insert commands below this line
clite.commands.load('help',function(args,env,io) {
if (args.length > 1) {
// TODO: implement command help lookup
io.write('help with arguments is a work in progress');
}
io.write(`
Welcome to CLIte (pronounced like 'site' with an added L).
Various unix-like commands are available for navigating the CLIte shell:
ls - list directory contents
cat - concatenate files and print to std output or local file
touch - create a new file
less - simple text file viewer
file - determines the file type
Under Development:
view - file viewer
edit - text file editor
Running any command with the argument -? will give you help for that program.
Or you can run help <command> to get the same info.
As a basic guide for guests:
Use ls to see what content is available, eg: ls web
Use view or less to view the content, eg: view web/about
`);
return 0;
});
clite.commands.load('ls',function(args,env,io) {
var dirs = [];
var long = false;
var stdlib = io.include('stdlib');
var stdio = io.include('stdio');
function help() {
io.write(`
ls - list directory contents
Usage: ls [OPTION] [FILE]
Options:
-? Print this help information
-l Display data in long format
`);
}
function writeNodeData(st,fd) {
if (long) {
if (st.type == stdio.types.FT_LINK) {
var d = stdio.readAll(fd);
if (!d)
d = '?';
io.write(st.perms+'\t'+st.uid+'\t'+st.gid+'\t'+st.name+' -> '+d);
}else{
io.write(st.perms+'\t'+st.uid+'\t'+st.gid+'\t'+st.name);
}
}else{
io.write(st.name);
}
}
for (var i=1; i<args.length; i++) {
if (args[i][0] == '-') {
for (var j=1; j<args[i].length; j++) {
switch (args[i][j]) {
case '?':
help();
return 0;
break;
case 'l':
long = true;
break;
default:
io.error('unknown argument: -'+args[i][j]);
}
}
}else{
dirs.push(stdlib.resolvePath(args[i],false));
}
}
if (dirs.length < 1)
dirs.push(env.PWD);
dirs.forEach(function(dir,index) {
if (dirs.length > 1)
io.write(dir+':');
var fd = stdio.open(dir,false);
if (!fd) {
io.error('cannot open directory: '+dir);
return;
}
var st = stdio.fstat(fd);
if (!st || st.type != stdio.types.FT_DIR) {
writeNodeData(st,fd);
stdio.close(fd);
return;
}
var e;
while ((e = stdio.read(fd)) != null) {
var efd = stdio.open(dir+'/'+e,false,true);
if (!efd) {
io.error('cannot read contents: '+dir);
break;
}
var est = stdio.fstat(efd);
if (!est) {
stdio.close(efd);
io.error('cannot read contents: '+dir);
break;
}
writeNodeData(est,efd);
stdio.close(efd);
}
stdio.close(fd);
});
return 0;
});
clite.commands.load('cat',function(args,env,io) {
var files = [];
var download = false;
var pending = 0;
var stdlib = io.include('stdlib');
var stdio = io.include('stdio');
function help() {
io.write(`
cat - concatenate files and print to std output or local file
Usage: cat [OPTION] <FILE> [FILE]
Options:
-? Print this help information
-d Download the file data, instead of printing it
`);
}
for (var i=1; i<args.length; i++) {
if (args[i][0] == '-') {
for (var j=1; j<args[i].length; j++) {
switch (args[i][j]) {
case '?':
help();
return 0;
break;
case 'd':
download = true;
break;
default:
io.error('unknown argument: -'+args[i][j]);
}
}
}else{
files.push(stdlib.resolvePath(args[i],false));
}
}
if (files.length < 1)
return 1;
pending = files.length;
function fcb(fd) {
var st = stdio.fstat(fd);
// check if it's a directory or link
if (!st || st.type == stdio.types.FT_DIR || st.type == stdio.types.FT_LINK) {
if (st) {
io.error('not a normal file: '+st.name);
}else{
io.error('not a normal file');
}
}else{
var d = stdio.readAll(fd);
if (d != null) {
if (download) {
var ld = stdio.open('/dev/local',false);
if (ld) {
stdio.write(ld,{name:st.name,data:d});
stdio.close(ld);
}else{
io.error('can not write to local device');
}
}else{
io.write(d);
}
}
}
pending--;
stdio.close(fd);
if (pending <1)
io.exit(0);
}
files.forEach(function(file,index) {
var st = stdio.stat(file);
// check if it's a directory or link
if (!st || st.type == stdio.types.FT_DIR || st.type == stdio.types.FT_LINK) {
io.error('not a normal file: '+file);
pending--;
return;
}
var fd = stdio.open(file,fcb);
if (!fd) {
io.error('cannot open file: '+file);
pending--;
return;
}
});
if (pending <1)
return 0;
return null;
});
clite.commands.load('touch',function(args,env,io) {
var file = null;
var stdlib = io.include('stdlib');
var stdio = io.include('stdio');
function help() {
io.write(`
touch - create a new empty file
Usage: touch [OPTION] <FILE>
Options:
-? Print this help information
`);
}
for (var i=1; i<args.length; i++) {
if (args[i][0] == '-') {
for (var j=1; j<args[i].length; j++) {
switch (args[i][j]) {
case '?':
help();
return 0;
break;
default:
io.error('unknown argument: -'+args[i][j]);
}
}
}else if (file == null) {
file = stdlib.resolvePath(args[i],false);
}else{
io.error('unknown argument: '+args[i]);
}
}
if (file == null) {
io.error('no file specified');
return 1;
}
function loadRemote(fd) {
if (!fd) {
io.error('unable to create file: '+file);
io.exit(1);
return;
}
io.exit(0);
}
if (!stdio.creat(file)) {
var fd = stdio.open(file,loadRemote);
return null;
}
return 0;
});
clite.commands.load('less',function(args,env,io) {
var stdlib = io.include('stdlib');
var stdio = io.include('stdio');
var term = io.include('term');
var file = null;
function help() {
io.write(`
less - text file viewer
Usage: less [OPTION] <FILE>
Options:
-? Print this help information
`);
}
for (var i=1; i<args.length; i++) {
if (args[i][0] == '-') {
for (var j=1; j<args[i].length; j++) {
switch (args[i][j]) {
case '?':
help();
return 0;
break;
default:
io.error('unknown argument: -'+args[i][j]);
}
}
}else if (file == null) {
file = stdlib.resolvePath(args[i],false);
}else{
io.error('unknown argument: '+args[i]);
}
}
if (file == null) {
io.error('no file specified');
return 1;
}
var lines = [];
var topLine = 0;
var bottomLine = 0;
function showAt(line) {
var start = line;
var end = line+tty.lines;
if (end > lines.length)
end = lines.length;
tty.clear();
for (var i=start; i<end; i++) {
tty.draw(lines[i]+'\n');
}
}
function prepFile(fd) {
if (!fd) {
io.error('could not open file: '+file);
io.exit(1);
return;
}
var t = stdlib.getFileType(fd);
if (t != 1 && t != 7) {
io.error('can not read files of this type');
io.exit(1);
return;
}
var txt = stdio.readAll(fd);
stdio.close(fd);
var parts = txt.split('\n');
parts.forEach(function(line) {
if (line.length > tty.chars) {
var sects = line.match(new RegExp('(.{1,'+tty.chars+'})','g'));
lines.push.apply(lines,sects);
return;
}
lines.push(line);
});
bottomLine = (lines.length-tty.lines);
showAt(0);
}
var fd = stdio.open(file,prepFile);
if (!fd) {
io.error('could not open file: '+file);
io.exit(1);
return;
}
var tty = term.createTTY();
tty.setRaw(false);
tty.handleKeys(function(e) {
switch (e.key) {
case 'Escape':
case 'q':
term.closeTTY(tty);
io.exit(0);
break;
case 'Up':
case 'ArrowUp':
if (topLine > 0) {
topLine--;
showAt(topLine);
}
break;
case 'Down':
case 'ArrowDown':
if (topLine < bottomLine) {
topLine++;
showAt(topLine);
}
break;
}
});
tty.draw('Loading...');
return null;
});
clite.commands.load('view',function(args,env,io) {
io.write('view is under development');
return 0;
});
clite.commands.load('edit',function(args,env,io) {
io.write('edit is under development');
return 0;
});
clite.commands.load('file',function(args,env,io) {
var short = '';
var file = null;
var stdlib = io.include('stdlib');
var stdio = io.include('stdio');
function help() {
io.write(`
file - determine type of FILE
Usage: touch [OPTION] [FILE]
Options:
-? Print this help information
`);
}
for (var i=1; i<args.length; i++) {
if (args[i][0] == '-') {
for (var j=1; j<args[i].length; j++) {
switch (args[i][j]) {
case '?':
help();
return 0;
break;
default:
io.error('unknown argument: -'+args[i][j]);
}
}
}else if (file == null) {
short = args[i];
file = stdlib.resolvePath(args[i],false);
}else{
io.error('unknown argument: '+args[i]);
}
}
if (file == null) {
io.error('no file specified');
return 1;
}
var fd = stdio.open(file,false);
if (!fd) {
io.error('cannot open file: '+file);
return 1;
}
var t = stdlib.getFileType(fd);
stdio.close(fd);
var txt = short+': ';
switch (t) {
case 1:
txt += 'Plain Text';
break;
case 2:
txt += 'CLIte Executable';
break;
case 3:
txt += 'Directory';
break;
case 4:
txt += 'Link';
break;
case 5:
txt += 'Device File';
break;
case 6:
txt += 'Unloaded Remote Data';
break;
case 7:
txt += 'Shell Script';
break;
case 8:
txt += 'Image';
break;
default:
txt += 'Unknown Data';
break;
}
io.write(txt);
return 0;
});
// insert commands above this line
}