A web application, showing a terminal emulator, sitting on top of a virtual file system, with an "old-fashioned"-themed console.
Perfect for CV-oriented content!
I've set out a few goals with this
I want this project to be:
We can view the app in different ways!
As an MVC app
or
As a modular system
The core of the framework revolves around the VFS
wrapped up->(VFS = B+ Tree + Doubly Linked List
)
B+ Tree:
M-Tree:
This is the general form
We have 8 cases to handle
# if
ls
awards
education
experience
# then
cd ./awards/../awards/.././education
# we have this
/education /experience /experience/projects /experience/skills /awards
# mapped to this
/education/edu.txt /experience/projects/my_projects.txt
/experience/skills/soft_skills.txt /experience/skills/hard_skills.txt
/experience/skills/languages/langs.txt
Many, many commands
Since all of the data is text based and parsed only on a command based system there is no worry that someone might execute malicious scripts on the host!
No forkbomb!
No malware!
No rm -rf /
Everything developed with Emacs + xterm + Arch Linux with:
const express = require('express');
const port = 3000;
let app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.static(path.join(__dirname, '.')));
app.use(express.static(path.join(__dirname, 'html')));
app.use(express.static(path.join(__dirname, 'css')));
app.use(express.static(path.join(__dirname, 'src')));
I had a lot of problems with references!!
user.prototype.getDirs = function() {
return JSON.parse(JSON.stringify(this.dirs));
};
M-Tree navigation
mTree.prototype.moveTo = function(dir) {
let workingDir = dir.shift();
if (dir.length === 0) {
let nextSubtree = this.subtrees.find(s => s.name === workingDir);
if (!nextSubtree) {
throw Error('directory doesn\'t exist.');
}
return nextSubtree;
} else {
let nextSubtree = this.subtrees.find(s => s.name === workingDir);
return nextSubtree.moveTo(dir);
}
};
M-Tree directory creation
mTree.prototype.addSubtree = function(dir, parent) {
let workingDir = dir.shift();
if (this.subtrees.find(s => s.name === workingDir)) {
if (dir.length === 0) {
throw Error('File exists');
} else {
let nextSubtree = this.subtrees.find(x => x.name === workingDir);
nextSubtree.addSubtree(dir, nextSubtree);
}
} else {
this.subtrees.push(new mTree(workingDir));
let nextSubtree = this.subtrees.find(x => x.name === workingDir);
nextSubtree.parenttree = parent;
nextSubtree.fullpath = nextSubtree.getFullPath(nextSubtree);
if (dir.length > 0) {
nextSubtree.addSubtree(dir, nextSubtree);
}
}
};
Path resolution
for (let i = 0; i < d.length; i++) {
if (d[i] === '.') {
// do nothing
} else if (d[i] === '..') {
if (wdStree.parenttree.name === 'root' || wdStree.name === 'root') {
wd = ['/'];
wdStree = jvfs.getWdSubtree(wd);
} else {
wd = wdStree.parentree.fullpath.slice();
wdStree = jvfs.getWdSubtree(wd);
}
} else {
if (wdStree.subtrees.find(s => s.name === d[i])) {
wd = wdStree.fullpath.concat(d[i]);
} else {
wd.push(d[i]);
}
I was my own QA Engineer!
Tested each command combination on both a real terminal and compared with the applications terminal.
Some stress testing as well
// [TEST]
// Create 10 000 files
this.create10000();
// [TEST Implementation]
jayVFS.prototype.create10000 = function() {
for (let i = 0; i < 10000; i++) {
this.createFile(['awards', 'file' + i]);
}
};
// [TEST]
this.create1mil();
// [TEST Implementation]
jayVFS.prototype.create1mil = function() {
// Read complete documentation
let lines = fs.readFileSync('./README.md', 'utf8', function(){});
// Create 1000 directories
for (let j = 0; j < 10000; j++) {
this.mtree.addSubtree(['dir' + j], this.mtree);
// Create in each directory 1000 files
// all filed with the whole documentation
// of this project
for (let i = 0; i < 10000; i++) {
let f = this.createFile(['awards', 'file' + i]);
f.append(lines);
}
}
};
I think it was a success!