Skip to content

Commit

Permalink
Consistent ~ support
Browse files Browse the repository at this point in the history
  • Loading branch information
unconed committed May 7, 2011
1 parent 1e93e18 commit d77b1ec
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 106 deletions.
19 changes: 18 additions & 1 deletion Node/misc.js
@@ -1,3 +1,5 @@
var exec = require('child_process').exec;

/**
* Process shortcut return values
*
Expand Down Expand Up @@ -106,4 +108,19 @@ exports.extend = function (a,b) {
a[i] = b[i];
}
return a;
}
}

/**
* Expand a local file path.
*/
exports.expandPath = function (path, callback) {
if (path[0] == '~') {
if (path.length == 1 || path[1] == '/') {
return callback(process.env.HOME + path.substring(1));
}
else {
// TODO: support ~user syntax. Need getpwnam bindings to work across BSD/Linux.
}
}
return callback(path);
}
193 changes: 100 additions & 93 deletions Node/shell/builtin.js
Expand Up @@ -4,7 +4,8 @@ var fs = require('fs'),
whenDone = require('misc').whenDone,
EventEmitter = require('events').EventEmitter,
async = require('misc').async,
meta = require('shell/meta');
meta = require('shell/meta'),
expandPath = require('misc').expandPath;

exports.shellCommands = {

Expand All @@ -28,54 +29,56 @@ exports.shellCommands = {
});

for (i in tokens) if (i > 0) (function (file) {
fs.stat(file, track(function (err, stats) {
if (err) {
errors++;
out.print("No such file (" + file + ")");
return;
}
fs.open(file, 'r', track(function (err, fd) {
expandPath(file, track(function (file) {
fs.stat(file, track(function (err, stats) {
if (err) {
errors++;
out.print("Unable to open file (" + file + ")");
out.print("No such file (" + file + ")");
return;
}

var position = 0;

(function read() {
var buffer = new Buffer(chunkSize);
fs.read(fd, buffer, 0, chunkSize, position, track(function (err, bytesRead) {
if (err) {
errors++;
out.print("Error reading file (" + file + ")");
return;
}

var slice = buffer.slice(0, bytesRead);

if (position == 0) {
var headers = new meta.headers();
headers.set({
'Content-Type': meta.sniff(file, slice),
'Content-Length': stats.size,
'Content-Disposition': [ 'attachment', { 'filename': file } ],
});

pipes.dataOut.write(headers.generate());
}

pipes.dataOut.write(slice);
position += bytesRead;

if (position < stats.size) {
read();
}
}));
})();
}));
}));
})(tokens[i]);
fs.open(file, 'r', track(function (err, fd) {
if (err) {
errors++;
out.print("Unable to open file (" + file + ")");
return;
}

var position = 0;

(function read() {
var buffer = new Buffer(chunkSize);
fs.read(fd, buffer, 0, chunkSize, position, track(function (err, bytesRead) {
if (err) {
errors++;
out.print("Error reading file (" + file + ")");
return;
}

var slice = buffer.slice(0, bytesRead);

if (position == 0) {
var headers = new meta.headers();
headers.set({
'Content-Type': meta.sniff(file, slice),
'Content-Length': stats.size,
'Content-Disposition': [ 'attachment', { 'filename': file } ],
});

pipes.dataOut.write(headers.generate());
}

pipes.dataOut.write(slice);
position += bytesRead;

if (position < stats.size) {
read();
}
})); // fs.read
})(); // read
})); // fs.open
})); // fs.stat
})); // expandPath
})(tokens[i]); // for i in tokens


},
Expand Down Expand Up @@ -107,21 +110,21 @@ exports.shellCommands = {
out.print('Usage: cd [dir]');
return exit(false);
}
var path = tokens[1] || process.env.HOME;
var path = tokens[1] || '~';

// Complete ~
path = path.replace(/^~(\/|$)/, process.env.HOME + '/');

// Try to change working dir.
try {
process.chdir(path);
}
catch (error) {
out.print(error.message + ' (' + path + ')');
return exit(false);
}
// Complete path
expandPath(path, function (path) {
// Try to change working dir.
try {
process.chdir(path);
}
catch (error) {
out.print(error.message + ' (' + path + ')');
return exit(false);
}

exit(true);
exit(true);
}); // expandPath
},

'ls': function (tokens, pipes, exit) {
Expand All @@ -148,47 +151,51 @@ exports.shellCommands = {
out.print(view.list(i, output[i]));
}
exit(errors == 0);
});
}); // whenDone

// Process arguments (list of paths).
for (var i in items) (function (i, path) {

output[i] = [];

// Stat the requested files / directories.
fs.stat(path, track(function (error, stats) {

// Iterate valid directories.
if (stats && stats.isDirectory()) {

// Scan contents of found directories.
fs.readdir(path, track(function (error, files) {
if (!error) {

var children = [];
files.sort(function (a, b) {
return a.localeCompare(b);
});

for (var j in files) (function (j, child) {
// Stat each child.
fs.stat(composePath(child, path), track(function (error, stats) {
if (!error) {
output[i][j] = view.file(child, path, stats);
}
})); // fs.stat
})(j, files[j]); // for j in files
} // !error
})); // fs.readdir
} // isDirectory
else {
// Count errors.
errors += +error;

// Output message.
out.print(error.message);
}
})); // fs.stat
// Expand path
expandPath(path, track(function (path) {
// Stat the requested files / directories.
fs.stat(path, track(function (error, stats) {

// Iterate valid directories.
if (stats && stats.isDirectory()) {

// Scan contents of found directories.
fs.readdir(path, track(function (error, files) {
if (!error) {

var children = [];
files.sort(function (a, b) {
return a.localeCompare(b);
});

for (var j in files) (function (j, child) {
// Stat each child.
fs.stat(composePath(child, path), track(function (error, stats) {
if (!error) {
output[i][j] = view.file(child, path, stats);
}
})); // fs.stat
})(j, files[j]); // for j in files
} // !error
})); // fs.readdir
} // isDirectory
else {
// Count errors.
errors += +error;

// Output message.
out.print(error.message);
}
})); // fs.stat
})); // expandPath

})(i, items[i]); // for i in items

},
Expand Down
3 changes: 2 additions & 1 deletion termkit.txt
Expand Up @@ -58,10 +58,11 @@ Good desktop citizen:
[X] Redesign message protocol
[X] Viewstream integration
[X] 5-pipe command execution
[ ] fix tokenfield
[X] fix tokenfield
[ ] unix command execution
[.] filesystem autocomplete
[ ] http get/post data piping
[ ] code syntax highlighting
[ ] command decoration
[ ] interactive execution
[ ] inline man-pages tips
Expand Down
22 changes: 11 additions & 11 deletions todo.txt
@@ -1,8 +1,7 @@
Tasks:
[:] filesystem autocomplete
[.] Viewstream integration
[ ] run unix
[ ] run pipeline test
+[ ] run unix
+ [ ] run pipeline test
[ ] cat/echo Piping + progress bar
[ ] 5-pipe command execution
[ ] unix command execution
Expand Down Expand Up @@ -31,21 +30,21 @@ Prototype:
[X] fix event bindings lost when clicking inside textfield
[X] Unify tokenlist and commandlist into collection class, derive from.
[X] fix backspacing around edges of tokens
! [ ] add icon/spinner support to tokens
[ ] caret positions around allowempty tokens and ^/$
[ ] | and >> token support
[ ] caret.remove() shouldn't need to touch tokenList when pruning empties -> let triggers do it
[ ] mouseclick caret is off by ~8px, but only in first token
[ ] add icon/spinner support to tokens
[ ] switch between inline and block tokens -> input vs textarea.
[ ] fix wrapping of tokens
[ ] | and >> token support

[:] inline autocomplete
[X] panel overlayed on token
[X] alignment
[X] keyboard controls up/down
[X] hit enter after autocomplete in empty token -> undefined
[X] escape to close popup
[ ] autocomplete icons, markup, widgets, etc
! [ ] autocomplete icons, markup, widgets, etc

[:] command view
[X] list of collapsible sections
Expand All @@ -69,8 +68,8 @@ Prototype:
[X] autocomplete commands
[X] autocomplete filesystem
+ [ ] autocomplete label / contents / icon
+ [ ] autocomplete dir / file distinction
+ [ ] badge tokens with one/many/command icons
! [ ] autocomplete dir / file distinction
! [ ] badge tokens with one/many/command icons

3) Smart output with selectable things
[X] research FastCGI socket protocol
Expand Down Expand Up @@ -98,22 +97,23 @@ Prototype:
[X] keep state of sessions
[X] export environment
[X] allow path navigation
+ [X] worker process
! [X] worker process
[X] refactor processor.js handler/return handling
[X] spawn process
[X] stream in/out json packets
[X] view proxy object on worker side
[X] make ls / cd commands
[X] simplify message format to raw json
[X] viewstream integration
[ ] arrange pipes for command/view for unix processes
+ [X] output formatter
! [ ] arrange pipes for command/view for unix processes
! [X] output formatter
[X] full mime header parser/generator
[ ] handle encodings
[ ] smart binary output
[ ] sudo support (askpass env?)

5) Command Suite
![:] code syntax highlighter
[ ] make a script for git (arguments, file/dir, ...)
[ ] basic top/w infographs + live update
[ ] robust unix basics
Expand Down

0 comments on commit d77b1ec

Please sign in to comment.