Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e9ea29f

Browse filesBrowse files
committed
working on unix filesystem example using pathhandler helpers
1 parent ba65ded commit e9ea29f
Copy full SHA for e9ea29f

File tree

Expand file treeCollapse file tree

6 files changed

+327
-179
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+327
-179
lines changed

‎index.html

Copy file name to clipboardExpand all lines: index.html
+151-54Lines changed: 151 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,62 +4,159 @@
44
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
55
<title>Shell testbed</title>
66

7-
<link href='http://fonts.googleapis.com/css?family=Source+Code+Pro' rel='stylesheet' type='text/css'>
8-
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
9-
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.2/underscore-min.js"></script>
10-
<script src="js/readline.js"></script>
11-
<script src="js/shell.js"></script>
12-
<style type="text/css">
13-
#shell-panel {
14-
display: none;
15-
height: 400px;
16-
width: 100%;
17-
opacity: 0.9;
18-
background-color: #002f05;
19-
color: #00fe00;
20-
position: fixed;
21-
padding: 20px 20px 20px 20px;
22-
top: 0;
23-
z-index: 1000;
24-
font-family: 'Source Code Pro', sans-serif;
25-
font-size: 0.9em;
26-
overflow: hidden;
27-
}</style>
28-
<script type="text/javascript">
29-
var dir = {
30-
"Guide-Admin": {
31-
"AccessControlPanel": {},
32-
"AddingUsers": {},
33-
"GettingStarted": {}
34-
},
35-
"Guide-User": {
36-
"GettingStarted": {},
37-
"ContentCreation": {},
38-
"ContentManagement": {}
39-
},
40-
Reference: {}
41-
};
42-
var history = ReadLine.History({storage: localStorage});
43-
var shell = Shell({history: history});
44-
$(document).ready(function() {
45-
var console = $('#shell-panel');
46-
shell.onActivate(function() {
47-
showConsole();
48-
});
49-
shell.onDeactivate(function() {
50-
hideConsole();
51-
});
52-
function showConsole() {
53-
console.slideDown();
54-
console.focus();
7+
<link href='http://fonts.googleapis.com/css?family=Source+Code+Pro' rel='stylesheet' type='text/css'>
8+
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
9+
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.2/underscore-min.js"></script>
10+
<script src="js/readline.js"></script>
11+
<script src="js/shell.js"></script>
12+
<script src="js/pathhandler.js"></script>
13+
<style type="text/css">
14+
#shell-panel {
15+
display: none;
16+
height: 400px;
17+
width: 100%;
18+
opacity: 0.9;
19+
background-color: #002f05;
20+
color: #00fe00;
21+
position: fixed;
22+
padding: 20px 20px 20px 20px;
23+
top: 0;
24+
z-index: 1000;
25+
font-family: 'Source Code Pro', sans-serif;
26+
font-size: 0.9em;
27+
overflow: hidden;
28+
}</style>
29+
<script type="text/javascript">
30+
var fs = {
31+
bin: {},
32+
boot: {},
33+
dev: {},
34+
etc: {
35+
default: {},
36+
'rc.d': {},
37+
sysconfig: {},
38+
x11: {}
39+
},
40+
home: {
41+
bob: {},
42+
jane: {}
43+
},
44+
lib: {},
45+
'lost+found': {},
46+
misc: {},
47+
mnt: {
48+
cdrom: {},
49+
sysimage: {}
50+
},
51+
net: {},
52+
opt: {},
53+
proc: {},
54+
root: {},
55+
sbin: {},
56+
usr: {
57+
x11: {},
58+
bin: {},
59+
include: {},
60+
lib: {},
61+
local: {},
62+
man: {},
63+
sbin: {},
64+
share: {
65+
doc: {}
66+
},
67+
src: {}
68+
},
69+
var: {
70+
lib: {},
71+
lock: {},
72+
run: {},
73+
log: {
74+
httpd: {
75+
access_log: {},
76+
error_log: {}
77+
},
78+
'boot.log': {},
79+
cron: {},
80+
messages: {}
81+
}
82+
}
83+
};
84+
function buildTree(parent, node) {
85+
parent.childnodes = _.map(_.pairs(node), function(pair) {
86+
var child = {
87+
name: pair[0],
88+
path: parent.path + "/" + pair[0],
89+
parent: parent
90+
};
91+
buildTree(child, pair[1]);
92+
return child;
93+
});
94+
parent.children = _.keys(node);
95+
return parent;
5596
}
56-
function hideConsole() {
57-
console.slideUp();
58-
console.blur();
97+
function findNode(current, parts, callback) {
98+
if(!parts || parts.length == 0) {
99+
return callback(current);
100+
}
101+
if(parts[0] == ".") {
102+
// do nothing
103+
} else if(parts[0] == "..") {
104+
current = current.parent;
105+
} else {
106+
current = _.first(_.filter(current.childnodes, function(node) {
107+
return node.name == parts[0];
108+
}));
109+
}
110+
if(!current) {
111+
return callback();
112+
}
113+
return findNode(current, _.rest(parts), callback);
59114
}
60-
shell.activate();
61-
});
62-
</script>
115+
var root = buildTree({
116+
name: "",
117+
path: ""
118+
},
119+
fs
120+
);
121+
root.path = '/';
122+
var history = ReadLine.History({storage: localStorage});
123+
var shell = Shell({history: history});
124+
var pathhandler = Josh.PathHandler();
125+
pathhandler.current = root;
126+
pathhandler.attach(shell);
127+
pathhandler.getNode = function(path, callback) {
128+
if(!path) {
129+
return callback();
130+
}
131+
var parts = path.split('/');
132+
return findNode(pathhandler.current, parts, callback);
133+
};
134+
pathhandler.getChildNodes = function(node, callback) {
135+
console.log("children for "+node.name);
136+
callback(node.childnodes);
137+
};
138+
139+
$(document).ready(function() {
140+
var console = $('#shell-panel');
141+
shell.onActivate(function() {
142+
showConsole();
143+
});
144+
shell.onDeactivate(function() {
145+
hideConsole();
146+
});
147+
function showConsole() {
148+
console.slideDown();
149+
console.focus();
150+
}
151+
152+
function hideConsole() {
153+
console.slideUp();
154+
console.blur();
155+
}
156+
157+
shell.activate();
158+
});
159+
</script>
63160
</head>
64161
<body>
65162
<div id="shell-panel">

‎js/pathhandler.js

Copy file name to clipboard
+168Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
var Josh = Josh || {};
2+
(function(root, $) {
3+
Josh.PathHandler = function() {
4+
var self = {
5+
attach: function(shell) {
6+
shell.onCompletion(completionHandler);
7+
shell.setCommandHandler("ls", ls);
8+
shell.setCommandHandler("pwd", pwd);
9+
shell.setCommandHandler("cd", cd);
10+
shell.setCommandHandler("_default", exec);
11+
shell.setPrompt(self.getPrompt());
12+
},
13+
handlers: {
14+
ls: ls,
15+
exec: exec,
16+
cd: cd,
17+
pwd: pwd
18+
},
19+
templates: {
20+
not_found: _.template("<div><%=cmd%>: <%=path%>: No such file or directory</div>"),
21+
ls: _.template("<div><% _.each(nodes, function(node) { %><span><%=node.name%>&nbsp;</span><% }); %></div>"),
22+
pwd: _.template("<div><%=node.path %>&nbsp;</div>"),
23+
prompt: _.template("<%= node.path %> $")
24+
},
25+
getNode: function(path, callback) {
26+
callback();
27+
},
28+
getChildNodes: function(node, callback) {
29+
callback([]);
30+
},
31+
getPrompt: function() {
32+
return self.templates.prompt({node: self.current});
33+
},
34+
withPrompt: function(output, prompt, cmdtext) {
35+
var callback = _.last(arguments);
36+
if(output == callback) {
37+
output = null;
38+
}
39+
if(prompt == callback) {
40+
prompt = null;
41+
}
42+
if(cmdtext == callback) {
43+
cmdtext = null;
44+
}
45+
if(!prompt) {
46+
prompt = self.getPrompt();
47+
}
48+
callback(output, prompt, cmdtext);
49+
},
50+
current: null
51+
};
52+
53+
function exec(cmd, args, callback) {
54+
self.withPrompt(callback);
55+
}
56+
57+
function cd(cmd, args, callback) {
58+
self.getNode(args[0], function(node) {
59+
if(!node) {
60+
return callback(self.templates.not_found({cmd: 'cd', path: args[0]}));
61+
}
62+
self.current = node;
63+
return self.withPrompt(callback);
64+
});
65+
}
66+
67+
function pwd(cmd, args, callback) {
68+
self.withPrompt(self.templates.pwd({node: self.current}), callback);
69+
}
70+
71+
function ls(cmd, args, callback) {
72+
console.log('ls');
73+
if(!args || !args[0]) {
74+
return render_ls(self.current, callback);
75+
}
76+
return self.getNode(args[0], function(node) {
77+
render_ls(node, callback);
78+
});
79+
}
80+
81+
function render_ls(node, callback) {
82+
if(!node) {
83+
return callback(template.not_found({cmd: 'ls', path: node.path}));
84+
}
85+
return self.getChildNodes(node, function(children) {
86+
console.log("finish render: "+node.name);
87+
self.withPrompt(self.templates.ls({nodes: children}), callback);
88+
});
89+
}
90+
91+
function completionHandler(line, callback) {
92+
var partial = line.text.substr(0, line.cursor);
93+
var parts = split(partial);
94+
console.log(parts);
95+
if(parts.length == 0) {
96+
return callback({suggestions: _commandList});
97+
}
98+
if(parts.length == 1) {
99+
var cmd = parts[0];
100+
if(startsWith(cmd, ".") || startsWith(cmd, "/")) {
101+
return completePath(cmd, callback);
102+
}
103+
return callback(bestMatch(cmd, _commandList));
104+
}
105+
return completePath(parts[1], callback);
106+
}
107+
108+
function completePath(path, callback) {
109+
var uri = "/@api/deki/console/matches?path=" + encodeURIComponent(path);
110+
if(_current) {
111+
uri = uri + "&current=" + _current.Id;
112+
}
113+
$.getJSON(uri, function(data) {
114+
console.log(data);
115+
callback(bestMatch(path, data.Matches));
116+
});
117+
}
118+
119+
function split(str) {
120+
var parts = str.split(/\s+/);
121+
if(parts.length > 0 && !parts[parts.length - 1]) {
122+
parts.pop();
123+
}
124+
return parts;
125+
}
126+
127+
function startsWith(str1, str2) {
128+
return str1.slice(0, str2.length) == str2;
129+
}
130+
131+
function bestMatch(partial, possible) {
132+
var completions = [];
133+
var common = '';
134+
for(var i = 0; i < possible.length; i++) {
135+
var option = possible[i];
136+
if(option.slice(0, partial.length) == partial) {
137+
completions.push(option);
138+
if(!common) {
139+
common = option;
140+
console.log("initial common:" + common);
141+
} else if(option.slice(0, common.length) != common) {
142+
console.log("find common stem for '" + common + "' and '" + option + "'");
143+
var j = partial.length;
144+
while(j < common.length && j < option.length) {
145+
if(common[j] != option[j]) {
146+
common = common.substr(0, j);
147+
break;
148+
}
149+
j++;
150+
}
151+
}
152+
}
153+
}
154+
if(completions.length == 0) {
155+
return;
156+
}
157+
if(completions.length == 1) {
158+
completions = null;
159+
}
160+
return {
161+
result: common.substr(partial.length),
162+
suggestions: completions
163+
};
164+
}
165+
166+
return self;
167+
};
168+
})(this, $, _);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.