351 lines
9.2 KiB
JavaScript
351 lines
9.2 KiB
JavaScript
var UserInterface = function(terminal) {
|
|
|
|
this.terminal = terminal;
|
|
|
|
this.view = document.createElement('div');
|
|
this.view.style.whiteSpace = 'pre-wrap';
|
|
this.view.style.wordWrap = 'break-word';
|
|
this.view.style.wordBreak = 'break-all';
|
|
|
|
this.code = document.createElement('code');
|
|
|
|
this.completion = document.createElement('span');
|
|
this.completion.style.color = '#d09050';
|
|
|
|
this.prompt = document.createElement('span');
|
|
|
|
this.input = document.createElement('input');
|
|
this.input.type = 'text';
|
|
this.DEFAULT_INPUT_SIZE = this.input.size;
|
|
|
|
this.view.appendChild(this.code);
|
|
this.code.appendChild(this.completion);
|
|
this.code.appendChild(this.prompt);
|
|
this.code.appendChild(this.input);
|
|
|
|
this.parser = new Parser();
|
|
|
|
this.inputHistory = [];
|
|
this.inputHistoryIndex = this.inputHistory.length;
|
|
|
|
var self = this;
|
|
|
|
this.splitPath = function(path) {
|
|
var slash = path.lastIndexOf('/');
|
|
if (slash == -1) {
|
|
return [ '', path ];
|
|
} else if (path.length > 1 && slash == path.length - 1) {
|
|
return [ path, '' ];
|
|
} else if (slash == 0) {
|
|
return [ '/', path.substr(1) ];
|
|
} else {
|
|
return [ path.substr(0, slash), path.substr(slash + 1) ];
|
|
}
|
|
};
|
|
|
|
this.headCompletionCallback = function(packet, args) {
|
|
if (packet.opcode == 'StringList') {
|
|
self.parser.setLine(self.input.value);
|
|
self.parser.parse();
|
|
var elements = self.parser.tokens;
|
|
var originalElements = self.parser.originalTokens;
|
|
|
|
var length = 0;
|
|
var index;
|
|
if (originalElements.length < 1) {
|
|
index = -1;
|
|
} else {
|
|
for (index = 0; index < originalElements.length; index++) {
|
|
if (length + originalElements[index].length >= self.input.selectionStart) {
|
|
break;
|
|
}
|
|
length += originalElements[index].length;
|
|
}
|
|
}
|
|
|
|
var word = '';
|
|
if (index >= 0 && index < elements.length) {
|
|
word = elements[index];
|
|
}
|
|
|
|
var list = args.concat(self.createCompletionList(packet.list, word));
|
|
|
|
if (list.length < 2) {
|
|
if (index >= 0) {
|
|
if (index < 1) {
|
|
originalElements[index] = list[0];
|
|
} else {
|
|
originalElements[index] = ' ' + list[0];
|
|
}
|
|
self.input.value = originalElements.join('') + ' ';
|
|
self.completion.textContent = '';
|
|
}
|
|
} else {
|
|
self.completion.textContent = list.join(' ') + '\n';
|
|
self.scrollToBottom();
|
|
}
|
|
} else {
|
|
self.println(packet.opcode);
|
|
}
|
|
};
|
|
|
|
this.completionCallback = function(packet, args) {
|
|
var list = [];
|
|
var i;
|
|
if (packet.opcode == 'FileException') {
|
|
if (packet.type == 'IS_FILE') {
|
|
list.push({ name: args[1], type: 'FILE' });
|
|
return;
|
|
} else {
|
|
self.completion.textContent = packet.type;
|
|
return;
|
|
}
|
|
} else if (packet.opcode == 'FileList') {
|
|
for (i = 0; i < packet.list.length; i++) {
|
|
if (packet.list[i].name.indexOf(args[1]) == 0) {
|
|
list.push(packet.list[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (list.length < 1) {
|
|
self.completion.textContent = '';
|
|
} else if (list.length < 2) {
|
|
self.parser.setLine(self.input.value);
|
|
self.parser.parse();
|
|
var elements = self.parser.tokens;
|
|
var originalElements = self.parser.originalTokens;
|
|
|
|
var length = 0;
|
|
var index;
|
|
if (originalElements.length < 1) {
|
|
index = -1;
|
|
} else {
|
|
for (index = 0; index < originalElements.length; index++) {
|
|
if (length + originalElements[index].length >= self.input.selectionStart) {
|
|
break;
|
|
}
|
|
length += originalElements[index].length;
|
|
}
|
|
}
|
|
|
|
if (index >= 0) {
|
|
var filename;
|
|
if (args[0].length < 1) {
|
|
filename = list[0].name;
|
|
} else {
|
|
if (args[0] == '/') {
|
|
filename = '/' + list[0].name;
|
|
} else {
|
|
if (args[0].charAt(args[0].length - 1) == '/') {
|
|
filename = args[0] + list[0].name;
|
|
} else {
|
|
filename = args[0] + '/' + list[0].name;
|
|
}
|
|
}
|
|
}
|
|
if (filename.indexOf(' ') >= 0) {
|
|
filename = '"' + filename + '"';
|
|
}
|
|
originalElements[index] = ' ' + filename;
|
|
if (list[0].type == 'DIRECTORY') {
|
|
self.input.value = originalElements.join('') + '/';
|
|
} else {
|
|
self.input.value = originalElements.join('') + ' ';
|
|
}
|
|
self.completion.textContent = '';
|
|
if (self.input.value.length < self.DEFAULT_INPUT_SIZE) {
|
|
self.input.size = self.DEFAULT_INPUT_SIZE;
|
|
} else {
|
|
self.input.size = self.input.value.length;
|
|
}
|
|
}
|
|
} else {
|
|
var names = [];
|
|
for (i = 0; i < list.length; i++) {
|
|
names.push(list[i].name);
|
|
}
|
|
self.completion.textContent = names.join(' ') + '\n';
|
|
self.scrollToBottom();
|
|
}
|
|
};
|
|
|
|
this.handleInput = function(e) {
|
|
if (e.keyCode == 13) { // ENTER
|
|
var value = self.input.value;
|
|
self.input.value = '';
|
|
self.addHistory(value);
|
|
self.inputHistoryIndex = self.inputHistory.length;
|
|
self.completion.textContent = '';
|
|
} else if (e.keyCode == 9) { // TAB
|
|
e.preventDefault();
|
|
|
|
self.parser.setLine(self.input.value);
|
|
self.parser.parse();
|
|
var elements = self.parser.tokens;
|
|
var originalElements = self.parser.originalTokens;
|
|
|
|
var length = 0;
|
|
var index;
|
|
if (originalElements.length < 1) {
|
|
index = -1;
|
|
} else {
|
|
for (index = 0; index < originalElements.length; index++) {
|
|
if (length + originalElements[index].length >= self.input.selectionStart) {
|
|
break;
|
|
}
|
|
length += originalElements[index].length;
|
|
}
|
|
}
|
|
var word = '';
|
|
if (index >= 0 && index < elements.length) {
|
|
word = elements[index];
|
|
}
|
|
|
|
if (index < 1) {
|
|
var list = self.createCompletionList(self.completionListHead, word);
|
|
self.terminal.api.commandList(self.headCompletionCallback, list);
|
|
} else {
|
|
var sp = self.splitPath(word);
|
|
var absolutePath = self.terminal.session.toAbsolutePath(sp[0]);
|
|
self.terminal.fileAPI.list(self.completionCallback, sp, absolutePath);
|
|
}
|
|
} else if (e.keyCode == 38) { // UP
|
|
if (self.inputHistoryIndex < 0) {
|
|
self.input.value = '';
|
|
} else {
|
|
self.inputHistoryIndex--;
|
|
if (self.inputHistoryIndex < 0) {
|
|
self.input.value = '';
|
|
} else {
|
|
self.input.value = self.inputHistory[self.inputHistoryIndex];
|
|
}
|
|
}
|
|
} else if (e.keyCode == 40) { // DOWN
|
|
if (self.inputHistoryIndex >= self.inputHistory.length) {
|
|
self.input.value = '';
|
|
} else {
|
|
self.inputHistoryIndex++;
|
|
if (self.inputHistoryIndex >= self.inputHistory.length) {
|
|
self.input.value = '';
|
|
} else {
|
|
self.input.value = self.inputHistory[self.inputHistoryIndex];
|
|
}
|
|
}
|
|
}
|
|
if (self.input.value.length < self.DEFAULT_INPUT_SIZE) {
|
|
self.input.size = self.DEFAULT_INPUT_SIZE;
|
|
} else {
|
|
self.input.size = self.input.value.length;
|
|
}
|
|
if (e.keyCode == 13) { // ENTER
|
|
self.input.onkeydown = null;
|
|
self.inputCallback(value);
|
|
}
|
|
};
|
|
|
|
this.handleTemporalInput = function(e) {
|
|
if (e.keyCode == 13) { // ENTER
|
|
var value = self.input.value;
|
|
self.input.value = '';
|
|
}
|
|
if (self.input.value.length < self.DEFAULT_INPUT_SIZE) {
|
|
self.input.size = self.DEFAULT_INPUT_SIZE;
|
|
} else {
|
|
self.input.size = self.input.value.length;
|
|
}
|
|
if (e.keyCode == 13) { // ENTER
|
|
self.input.onkeydown = null;
|
|
self.temporalInputCallback(value);
|
|
}
|
|
};
|
|
|
|
this.login2 = function(line) {
|
|
self.account = line;
|
|
self.print(self.prompt.textContent);
|
|
self.println(line);
|
|
self.temporalInputCallback = self.login3;
|
|
self.prompt.textContent = 'Password: ';
|
|
self.input.type = 'password';
|
|
self.input.onkeydown = self.handleTemporalInput;
|
|
};
|
|
|
|
this.login3 = function(line) {
|
|
self.println(self.prompt.textContent);
|
|
self.prompt.textContent = self.terminal.promptString;
|
|
self.temporalInputCallback = null;
|
|
self.input.type = 'text';
|
|
var account = self.account;
|
|
self.account = null;
|
|
self.inputCallback(account, line);
|
|
};
|
|
|
|
};
|
|
|
|
UserInterface.prototype.addHistory = function(s) {
|
|
if (s.length < 1) {
|
|
return;
|
|
}
|
|
for (var i = this.inputHistory.length - 1; i >= 0; i--) {
|
|
if (this.inputHistory[i] == s) {
|
|
this.inputHistory.splice(i, 1);
|
|
break;
|
|
}
|
|
}
|
|
this.inputHistory.push(s);
|
|
};
|
|
|
|
UserInterface.prototype.createCompletionList = function(list, word) {
|
|
var result = [];
|
|
for (var i = 0; i < list.length; i++) {
|
|
if (list[i].indexOf(word) == 0) {
|
|
result.push(list[i]);
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
|
|
UserInterface.prototype.scrollToBottom = function() {
|
|
window.scrollTo(0, document.body.scrollHeight);
|
|
};
|
|
|
|
UserInterface.prototype.clear = function() {
|
|
while (this.code.firstChild != this.completion) {
|
|
this.code.removeChild(this.code.firstChild);
|
|
}
|
|
};
|
|
|
|
UserInterface.prototype.print = function(s, color, background) {
|
|
var output = document.createElement('span');
|
|
output.textContent = s;
|
|
output.style.color = color;
|
|
output.style.background = background;
|
|
this.code.insertBefore(output, this.completion);
|
|
this.scrollToBottom();
|
|
};
|
|
|
|
UserInterface.prototype.println = function(s, color, background) {
|
|
this.print(s + '\n', color, background);
|
|
};
|
|
|
|
UserInterface.prototype.append = function(node) {
|
|
this.code.insertBefore(node, this.prompt);
|
|
this.scrollToBottom();
|
|
};
|
|
|
|
UserInterface.prototype.readLine = function(callback, headList) {
|
|
this.inputCallback = callback;
|
|
this.completionListHead = headList;
|
|
this.input.onkeydown = this.handleInput;
|
|
this.input.focus();
|
|
};
|
|
|
|
UserInterface.prototype.login = function(callback) {
|
|
this.terminal.command.inputCallback = null;
|
|
this.inputCallback = callback;
|
|
this.temporalInputCallback = this.login2;
|
|
this.prompt.textContent = 'Account: ';
|
|
this.input.onkeydown = this.handleTemporalInput;
|
|
this.input.focus();
|
|
};
|