making command documentation more compact and tweaking how hints work
This commit is contained in:
parent
fc00e42b3e
commit
9e2e7336bd
6 changed files with 219 additions and 221 deletions
|
|
@ -495,7 +495,7 @@ oop.inherits(CliRequisition, Requisition);
|
||||||
CliRequisition.prototype.update = function(input) {
|
CliRequisition.prototype.update = function(input) {
|
||||||
this.input = input;
|
this.input = input;
|
||||||
// TODO: We only store this so getHints can work. Find a better way.
|
// TODO: We only store this so getHints can work. Find a better way.
|
||||||
this.localHints = [];
|
this.hints = [];
|
||||||
|
|
||||||
if (util.none(input.typed)) {
|
if (util.none(input.typed)) {
|
||||||
this.setCommand(null);
|
this.setCommand(null);
|
||||||
|
|
@ -508,44 +508,55 @@ oop.inherits(CliRequisition, Requisition);
|
||||||
// a complete novice a 'type help' message is very annoying, so we
|
// a complete novice a 'type help' message is very annoying, so we
|
||||||
// need to find a way to only display this message once, or for
|
// need to find a way to only display this message once, or for
|
||||||
// until the user click a 'close' button or similar
|
// until the user click a 'close' button or similar
|
||||||
this.localHints.push(new Hint(Status.INCOMPLETE, '', 0, 0));
|
this.hints.push(new Hint(Status.INCOMPLETE, '', 0, 0));
|
||||||
this.setCommand(null);
|
this.setCommand(null);
|
||||||
|
this._annotateHints();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var conversion = _split(args);
|
var conversion = _split(args);
|
||||||
if (!conversion.value) {
|
if (!conversion.value) {
|
||||||
// No command found - bail helpfully.
|
// No command found - bail helpfully.
|
||||||
this.localHints.push(new ConversionHint(conversion, conversion.arg));
|
this.hints.push(new ConversionHint(conversion, conversion.arg));
|
||||||
this.setCommand(null);
|
this.setCommand(null);
|
||||||
|
this._annotateHints();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
var message = documentCommand(conversion.value);
|
var message = documentCommand(conversion.value);
|
||||||
this.localHints.push(new Hint(Status.VALID, message, conversion.arg));
|
this.hints.push(new Hint(Status.VALID, message, conversion.arg));
|
||||||
|
|
||||||
this.setCommand(conversion.value);
|
this.setCommand(conversion.value);
|
||||||
this._assign(args);
|
this._assign(args);
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
CliRequisition.prototype.getHints = function() {
|
|
||||||
var hints = this.localHints.slice(0);
|
|
||||||
|
|
||||||
|
// Add the hints from the assignments to those already collected
|
||||||
Object.keys(this._assignments).map(function(name) {
|
Object.keys(this._assignments).map(function(name) {
|
||||||
// Only use assignments with an argument
|
// Only use assignments with an argument
|
||||||
var assignment = this._assignments[name];
|
var assignment = this._assignments[name];
|
||||||
if (assignment.arg) {
|
if (assignment.arg) {
|
||||||
hints.push.apply(hints, assignment.getHints());
|
this.hints.push.apply(this.hints, assignment.getHints());
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
|
this._annotateHints();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks up hints in a number of ways:
|
||||||
|
* - Makes INCOMPLETE hints that are not near the cursor INVALID since
|
||||||
|
* they can't be completed by typing
|
||||||
|
* - Finds the most severe hint, and annotates the array with it
|
||||||
|
* - Finds the hint to display, and also annotates the array with it
|
||||||
|
* TODO: I'm wondering if array annotation is evil and we should replace
|
||||||
|
* this with an object. Need to find out more.
|
||||||
|
*/
|
||||||
|
CliRequisition.prototype._annotateHints = function() {
|
||||||
// Not knowing about cursor positioning, the requisition and assignments
|
// Not knowing about cursor positioning, the requisition and assignments
|
||||||
// can't know this, but anything they mark as INCOMPLETE is actually
|
// can't know this, but anything they mark as INCOMPLETE is actually
|
||||||
// INVALID unless the cursor is actually inside that argument.
|
// INVALID unless the cursor is actually inside that argument.
|
||||||
var c = this.input.cursor;
|
var c = this.input.cursor;
|
||||||
hints.forEach(function(hint) {
|
this.hints.forEach(function(hint) {
|
||||||
var startInHint = c.start >= hint.start && c.start <= hint.end;
|
var startInHint = c.start >= hint.start && c.start <= hint.end;
|
||||||
var endInHint = c.end >= hint.start && c.end <= hint.end;
|
var endInHint = c.end >= hint.start && c.end <= hint.end;
|
||||||
var inHint = startInHint || endInHint;
|
var inHint = startInHint || endInHint;
|
||||||
|
|
@ -554,7 +565,35 @@ oop.inherits(CliRequisition, Requisition);
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
return Hint.sort(hints, this.input.cursor.start);
|
// Work out what the worst hint is (irrespective of the cursor). We
|
||||||
|
// return the hints in order of display importance - i.e. an INCOMPLETE
|
||||||
|
// hint under the cursor should be displayed before an INVALID hint
|
||||||
|
// somewhere else. That's good for displaying hints, but not good for
|
||||||
|
// deciding if we're good to go.
|
||||||
|
if (this.hints.length > 1) {
|
||||||
|
Hint.sort(this.hints);
|
||||||
|
this.hints.worst = this.hints[0];
|
||||||
|
}
|
||||||
|
else if (this.hints.length > 0) {
|
||||||
|
this.hints.worst = this.hints[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
Hint.sort(this.hints, this.input.cursor.start);
|
||||||
|
this.hints.display = this.hints[0];
|
||||||
|
|
||||||
|
return this.hints;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessor for the hints array.
|
||||||
|
* While we could just use the hints property, using getHints() is
|
||||||
|
* preferred for symmetry with Requisition where it needs a function due to
|
||||||
|
* lack of an atomic update system.
|
||||||
|
* TODO: When we use this properly (i.e. with a fancy UI) then
|
||||||
|
* CliRequisition will also not have an atomic update system. Hmmmmm
|
||||||
|
*/
|
||||||
|
CliRequisition.prototype.getHints = function() {
|
||||||
|
return this.hints;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -579,7 +618,7 @@ oop.inherits(CliRequisition, Requisition);
|
||||||
// TODO: previously we were doing some extra work to avoid this if
|
// TODO: previously we were doing some extra work to avoid this if
|
||||||
// we determined that we had args that were all whitespace, but
|
// we determined that we had args that were all whitespace, but
|
||||||
// probably given our tighter tokenize() this won't be an issue?
|
// probably given our tighter tokenize() this won't be an issue?
|
||||||
this.localHints.push(new Hint(Status.INVALID,
|
this.hints.push(new Hint(Status.INVALID,
|
||||||
this.command.name + ' does not take any parameters',
|
this.command.name + ' does not take any parameters',
|
||||||
Argument.merge(args)));
|
Argument.merge(args)));
|
||||||
return;
|
return;
|
||||||
|
|
@ -621,7 +660,7 @@ oop.inherits(CliRequisition, Requisition);
|
||||||
else {
|
else {
|
||||||
if (i + 1 < args.length) {
|
if (i + 1 < args.length) {
|
||||||
// Missing value portion of this named param
|
// Missing value portion of this named param
|
||||||
this.localHints.push(new Hint(Status.INCOMPLETE,
|
this.hints.push(new Hint(Status.INCOMPLETE,
|
||||||
'Missing value for: ' + namedArgText,
|
'Missing value for: ' + namedArgText,
|
||||||
args[i]));
|
args[i]));
|
||||||
}
|
}
|
||||||
|
|
@ -653,7 +692,7 @@ oop.inherits(CliRequisition, Requisition);
|
||||||
|
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
var remaining = Argument.merge(args);
|
var remaining = Argument.merge(args);
|
||||||
this.localHints.push(new Hint(Status.INVALID,
|
this.hints.push(new Hint(Status.INVALID,
|
||||||
'Input \'' + remaining.text + '\' makes no sense.',
|
'Input \'' + remaining.text + '\' makes no sense.',
|
||||||
remaining));
|
remaining));
|
||||||
}
|
}
|
||||||
|
|
@ -842,62 +881,41 @@ exports._split = _split;
|
||||||
*/
|
*/
|
||||||
function documentCommand(command) {
|
function documentCommand(command) {
|
||||||
var docs = [];
|
var docs = [];
|
||||||
docs.push('<h1>' + command.name + '</h1>');
|
docs.push('<strong><tt> > ');
|
||||||
docs.push('<h2>Summary</h2>');
|
|
||||||
docs.push('<p>' + command.description + '</p>');
|
|
||||||
|
|
||||||
if (command.manual) {
|
|
||||||
docs.push('<h2>Description</h2>');
|
|
||||||
docs.push('<p>' + command.description + '</p>');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command.params && command.params.length > 0) {
|
|
||||||
docs.push('<h2>Synopsis</h2>');
|
|
||||||
docs.push('<pre>');
|
|
||||||
docs.push(command.name);
|
docs.push(command.name);
|
||||||
var optionalParamCount = 0;
|
if (command.params && command.params.length > 0) {
|
||||||
command.params.forEach(function(param) {
|
command.params.forEach(function(param) {
|
||||||
if (param.defaultValue === undefined) {
|
if (param.defaultValue === undefined) {
|
||||||
docs.push(' <i>');
|
docs.push(' [' + param.name + ']');
|
||||||
docs.push(param.name);
|
}
|
||||||
docs.push('</i>');
|
else {
|
||||||
|
docs.push(' <em>[' + param.name + ']</em>');
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
docs.push('</tt></strong><br/>');
|
||||||
|
|
||||||
|
docs.push(command.description ? command.description : '(No description)');
|
||||||
|
docs.push('<br/>');
|
||||||
|
|
||||||
|
if (command.params && command.params.length > 0) {
|
||||||
|
docs.push('<ul>');
|
||||||
|
command.params.forEach(function(param) {
|
||||||
|
docs.push('<li>');
|
||||||
|
docs.push('<strong><tt>' + param.name + '</tt></strong>: ');
|
||||||
|
docs.push(param.description ? param.description : '(No description)');
|
||||||
|
if (param.defaultValue === undefined) {
|
||||||
|
docs.push(' <em>[Required]</em>');
|
||||||
}
|
}
|
||||||
else if (param.defaultValue === null) {
|
else if (param.defaultValue === null) {
|
||||||
docs.push(' <i>[');
|
docs.push(' <em>[Optional]</em>');
|
||||||
docs.push(param.name);
|
|
||||||
docs.push(']</i>');
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
optionalParamCount++;
|
docs.push(' <em>[Default: ' + param.defaultValue + ']</em>');
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
if (optionalParamCount > 3) {
|
|
||||||
docs.push(' [options]');
|
|
||||||
} else if (optionalParamCount > 0) {
|
|
||||||
command.params.forEach(function(param) {
|
|
||||||
if (param.defaultValue) {
|
|
||||||
docs.push(' [--<i>');
|
|
||||||
docs.push(param.name);
|
|
||||||
if (param.type.name === 'boolean') {
|
|
||||||
docs.push('</i>');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
docs.push('</i> ' + param.type.name);
|
|
||||||
}
|
|
||||||
docs.push(']');
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
docs.push('</pre>');
|
|
||||||
|
|
||||||
docs.push('<h2>Parameters</h2>');
|
|
||||||
command.params.forEach(function(param) {
|
|
||||||
docs.push('<h3 class="cmd_body"><i>' + param.name + '</i></h3>');
|
|
||||||
docs.push('<p>' + param.description + '</p>');
|
|
||||||
if (param.type.defaultValue) {
|
|
||||||
docs.push('<p>Default: ' + param.type.defaultValue + '</p>');
|
|
||||||
}
|
}
|
||||||
|
docs.push('</li>');
|
||||||
}, this);
|
}, this);
|
||||||
|
docs.push('</ul>');
|
||||||
}
|
}
|
||||||
|
|
||||||
return docs.join('');
|
return docs.join('');
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,37 @@
|
||||||
|
|
||||||
/* Command line completion */
|
#cockpit {
|
||||||
|
background: transparent;
|
||||||
|
border: none; outline: none;
|
||||||
|
font-family: consolas, courier, monospace;
|
||||||
|
font-size: 120%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cptOutput {
|
||||||
|
border: 1px solid #AAA;
|
||||||
|
-moz-border-radius-topleft: 10px;
|
||||||
|
-moz-border-radius-topright: 10px;
|
||||||
|
border-top-left-radius: 4px; border-top-right-radius: 4px;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0 15px;
|
||||||
|
background: #DDD; color: #000;
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 999;
|
||||||
|
font-family: consolas, courier, monospace;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cockpit:focus ~ .cptOutput {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.cptCompletion {
|
.cptCompletion {
|
||||||
color: #666;
|
color: #666;
|
||||||
padding: 0 0 5px 2px;
|
padding: 0 0 5px 2px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: -1000;
|
z-index: -1000;
|
||||||
|
font-family: consolas, courier, monospace;
|
||||||
|
font-size: 120%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cptHints {
|
.cptHints {
|
||||||
|
|
@ -17,6 +44,17 @@
|
||||||
border-top-left-radius: 10px; border-top-right-radius: 10px;
|
border-top-left-radius: 10px; border-top-right-radius: 10px;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cptHints ul { margin: 0; padding: 0 15px; }
|
||||||
|
|
||||||
|
#cockpit:focus ~ .cptHints {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cockpit:focus ~ .cptHints.cptNoHints {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cptCompletion.VALID { background: #FFF; }
|
.cptCompletion.VALID { background: #FFF; }
|
||||||
|
|
@ -24,34 +62,8 @@
|
||||||
.cptCompletion.INVALID { background: #DDD; }
|
.cptCompletion.INVALID { background: #DDD; }
|
||||||
|
|
||||||
.cptCompletion span { color: #FFF; }
|
.cptCompletion span { color: #FFF; }
|
||||||
.cptCompletion span.INCOMPLETE { text-shadow: 0px 0px 2px #F80; }
|
.cptCompletion span.INCOMPLETE { color: #DDD; border-bottom: 2px dotted #F80; }
|
||||||
.cptCompletion span.INVALID { text-shadow: 0px 0px 5px #F00; }
|
.cptCompletion span.INVALID { color: #DDD; border-bottom: 2px dotted #F00; }
|
||||||
|
|
||||||
|
|
||||||
#cockpit, .cptCompletion {
|
|
||||||
font-family: consolas, courier, monospace;
|
|
||||||
font-size: 120%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#cockpit {
|
|
||||||
background: transparent;
|
|
||||||
border: none; outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cptOutput {
|
|
||||||
border: 1px solid #AAA;
|
|
||||||
-moz-border-radius-topleft: 10px;
|
|
||||||
-moz-border-radius-topright: 10px;
|
|
||||||
border-top-left-radius: 4px; border-top-right-radius: 4px;
|
|
||||||
padding: 10px;
|
|
||||||
margin: 0 15px;
|
|
||||||
background: #DDD; color: #000;
|
|
||||||
font-family: consolas, courier, monospace;
|
|
||||||
font-size: 90%;
|
|
||||||
overflow: hidden;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 999;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,12 +81,11 @@ function CliView(data) {
|
||||||
this.cli = new CliRequisition();
|
this.cli = new CliRequisition();
|
||||||
|
|
||||||
this.settings = data.env.settings;
|
this.settings = data.env.settings;
|
||||||
this.showHint = this.settings.getSetting('showHint');
|
this.hintDirection = this.settings.getSetting('hintDirection');
|
||||||
|
this.outputDirection = this.settings.getSetting('outputDirection');
|
||||||
this.outputHeight = this.settings.getSetting('outputHeight');
|
this.outputHeight = this.settings.getSetting('outputHeight');
|
||||||
|
|
||||||
this.hints = [];
|
this.hints = [];
|
||||||
this.shownHint;
|
|
||||||
this.worstHint;
|
|
||||||
|
|
||||||
this.createElements();
|
this.createElements();
|
||||||
}
|
}
|
||||||
|
|
@ -95,29 +94,35 @@ CliView.prototype = {
|
||||||
* Create divs for completion, hints and output
|
* Create divs for completion, hints and output
|
||||||
*/
|
*/
|
||||||
createElements: function() {
|
createElements: function() {
|
||||||
|
var input = this.element;
|
||||||
|
|
||||||
this.completer = this.doc.createElement('div');
|
this.completer = this.doc.createElement('div');
|
||||||
this.completer.className = 'cptCompletion VALID';
|
this.completer.className = 'cptCompletion VALID';
|
||||||
this.element.parentNode.insertBefore(this.completer, this.element);
|
input.parentNode.insertBefore(this.completer, input.nextSibling);
|
||||||
|
|
||||||
this.hinter = this.doc.createElement('div');
|
this.hinter = this.doc.createElement('div');
|
||||||
this.hinter.className = 'cptHints';
|
this.hinter.className = 'cptHints';
|
||||||
this.element.parentNode.insertBefore(this.hinter, this.element);
|
input.parentNode.insertBefore(this.hinter, input.nextSibling);
|
||||||
|
|
||||||
this.output = this.doc.createElement('div');
|
this.output = this.doc.createElement('div');
|
||||||
this.output.className = 'cptOutput';
|
this.output.className = 'cptOutput';
|
||||||
this.element.parentNode.insertBefore(this.output, this.element);
|
input.parentNode.insertBefore(this.output, input.nextSibling);
|
||||||
|
|
||||||
this.win.addEventListener('resize', this.resizer.bind(this), false);
|
this.win.addEventListener('resize', this.resizer.bind(this), false);
|
||||||
|
this.hintDirection.addEventListener('change', this.resizer.bind(this));
|
||||||
|
this.outputDirection.addEventListener('change', this.resizer.bind(this));
|
||||||
this.resizer();
|
this.resizer();
|
||||||
|
|
||||||
canon.addEventListener('output', this.showOutput.bind(this));
|
canon.addEventListener('output', function(ev) {
|
||||||
|
new RequestView(ev.request, this);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
this.showHint.addEventListener('change', this.hintShower.bind(this));
|
keyutil.addKeyDownListener(input, this.onKeyDown.bind(this));
|
||||||
this.hintShower();
|
input.addEventListener('keyup', this.onKeyUp.bind(this), true);
|
||||||
|
// cursor position affects hint severity. TODO: shortcuts for speed
|
||||||
keyutil.addKeyDownListener(this.element, this.onKeyDown.bind(this));
|
input.addEventListener('mouseup', function(ev) {
|
||||||
this.element.addEventListener('mouseup', this.onMouseUp.bind(this), false);
|
this.update();
|
||||||
this.element.addEventListener('keyup', this.onKeyUp.bind(this), true);
|
}.bind(this), false);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -125,84 +130,34 @@ CliView.prototype = {
|
||||||
* with the input box.
|
* with the input box.
|
||||||
*/
|
*/
|
||||||
resizer: function() {
|
resizer: function() {
|
||||||
var top, height, left, width;
|
|
||||||
|
|
||||||
if (this.element.getClientRects) {
|
|
||||||
var rect = this.element.getClientRects()[0];
|
var rect = this.element.getClientRects()[0];
|
||||||
top = rect.top;
|
|
||||||
height = rect.height;
|
this.completer.style.top = rect.top + 'px';
|
||||||
left = rect.left;
|
this.completer.style.height = rect.height + 'px';
|
||||||
width = rect.width;
|
this.completer.style.left = rect.left + 'px';
|
||||||
|
this.completer.style.width = rect.width + 'px';
|
||||||
|
|
||||||
|
if (this.hintDirection.get() === 'below') {
|
||||||
|
this.hinter.style.top = rect.bottom + 'px';
|
||||||
|
this.hinter.style.bottom = 'auto';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var style = this.win.getComputedStyle(this.element, null);
|
this.hinter.style.top = 'auto';
|
||||||
top = parseInt(style.getPropertyValue('top'), 10);
|
this.hinter.style.bottom = (this.win.innerHeight - rect.top) + 'px';
|
||||||
height = parseInt(style.getPropertyValue('height'), 10);
|
|
||||||
left = parseInt(style.getPropertyValue('left'), 10);
|
|
||||||
width = parseInt(style.getPropertyValue('width'), 10);
|
|
||||||
}
|
}
|
||||||
|
this.hinter.style.left = (rect.left + 30) + 'px';
|
||||||
|
this.hinter.style.maxWidth = (rect.width - 90) + 'px';
|
||||||
|
|
||||||
this.completer.style.top = top + 'px';
|
if (this.outputDirection.get() === 'below') {
|
||||||
this.completer.style.height = height + 'px';
|
this.output.style.top = rect.bottom + 'px';
|
||||||
this.completer.style.left = left + 'px';
|
this.output.style.bottom = 'auto';
|
||||||
this.completer.style.width = width + 'px';
|
|
||||||
|
|
||||||
this.hinter.style.bottom = (this.win.innerHeight - top) + 'px';
|
|
||||||
this.hinter.style.left = (left + 30) + 'px';
|
|
||||||
|
|
||||||
this.output.style.bottom = (this.win.innerHeight - top) + 'px';
|
|
||||||
this.output.style.left = left + 'px';
|
|
||||||
this.output.style.width = (width - 60) + 'px';
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the display of executed commands
|
|
||||||
*/
|
|
||||||
showOutput: function(ev) {
|
|
||||||
var requestOutput = new RequestView(ev.request, this);
|
|
||||||
|
|
||||||
/*
|
|
||||||
// TODO: be less brutal in how we update this
|
|
||||||
this.output.innerHTML = '';
|
|
||||||
|
|
||||||
new RequestView(ev.request, this);
|
|
||||||
ev.requests.forEach(function(request) {
|
|
||||||
// this.duration.innerHTML = this.request.duration ?
|
|
||||||
// 'completed in ' + (this.request.duration / 1000) + ' sec ' :
|
|
||||||
// '';
|
|
||||||
// this.typed.innerHTML = this.request.typed;
|
|
||||||
|
|
||||||
request.outputs.forEach(function(output) {
|
|
||||||
var node;
|
|
||||||
if (typeof output == 'string') {
|
|
||||||
node = document.createElement('p');
|
|
||||||
node.innerHTML = output;
|
|
||||||
} else {
|
|
||||||
node = output;
|
|
||||||
}
|
|
||||||
this.output.appendChild(node);
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
// this.cliView.scrollToBottom();
|
|
||||||
// util.setClass(this.output, 'cmd_error', this.request.error);
|
|
||||||
// this.throb.style.display = this.request.completed ? 'none' : 'block';
|
|
||||||
}, this);
|
|
||||||
*/
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show/hide the hint line.
|
|
||||||
* It's not clear that this is actually useful, however it does help to
|
|
||||||
* highlight some features for right now.
|
|
||||||
* TODO: remove this?
|
|
||||||
*/
|
|
||||||
hintShower: function() {
|
|
||||||
if (this.showHint.get()) {
|
|
||||||
this.hinter.style.display = 'block';
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.hinter.style.display = 'none';
|
this.output.style.top = 'auto';
|
||||||
|
this.output.style.bottom = (this.win.innerHeight - rect.top) + 'px';
|
||||||
}
|
}
|
||||||
|
this.output.style.left = rect.left + 'px';
|
||||||
|
this.output.style.width = (rect.width - 60) + 'px';
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -231,21 +186,17 @@ CliView.prototype = {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ev.keyCode === keyutil.KeyHelper.KEY.RETURN) {
|
if (ev.keyCode === keyutil.KeyHelper.KEY.RETURN) {
|
||||||
if (this.worstHint && this.worstHint.status !== Status.VALID) {
|
if (this.hints.worst || this.hints.worst.status === Status.VALID) {
|
||||||
this.element.selectionStart = this.worstHint.start;
|
|
||||||
this.element.selectionEnd = this.worstHint.end;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.cli.exec();
|
this.cli.exec();
|
||||||
this.element.value = '';
|
this.element.value = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ev.keyCode === keyutil.KeyHelper.KEY.TAB && this.shownHint &&
|
if (ev.keyCode === keyutil.KeyHelper.KEY.TAB && this.hints.display &&
|
||||||
this.shownHint.predictions && this.shownHint.predictions.length > 0) {
|
this.hints.display.predictions && this.hints.display.predictions.length > 0) {
|
||||||
var prefix = this.element.value.substring(0, this.shownHint.start);
|
var prefix = this.element.value.substring(0, this.hints.display.start);
|
||||||
var suffix = this.element.value.substring(this.shownHint.end);
|
var suffix = this.element.value.substring(this.hints.display.end);
|
||||||
var insert = this.shownHint.predictions[0];
|
var insert = this.hints.display.predictions[0];
|
||||||
insert = typeof insert === 'string' ? insert : insert.name;
|
insert = typeof insert === 'string' ? insert : insert.name;
|
||||||
this.element.value = prefix + insert + suffix;
|
this.element.value = prefix + insert + suffix;
|
||||||
// Fix the cursor.
|
// Fix the cursor.
|
||||||
|
|
@ -256,15 +207,14 @@ CliView.prototype = {
|
||||||
|
|
||||||
this.update();
|
this.update();
|
||||||
|
|
||||||
return handled;
|
if (ev.keyCode === keyutil.KeyHelper.KEY.RETURN) {
|
||||||
},
|
if (this.hints.worst && this.hints.worst.status !== Status.VALID) {
|
||||||
|
this.element.selectionStart = this.hints.worst.start;
|
||||||
|
this.element.selectionEnd = this.hints.worst.end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
return handled;
|
||||||
* Cause an update if the cursor changes position due to a mouse click
|
|
||||||
* TODO: there are probably some performance wins here.
|
|
||||||
*/
|
|
||||||
onMouseUp: function(ev) {
|
|
||||||
this.update();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -289,15 +239,6 @@ CliView.prototype = {
|
||||||
|
|
||||||
this.hints = this.cli.getHints();
|
this.hints = this.cli.getHints();
|
||||||
|
|
||||||
// Those hints came in order of display importance - i.e. an INCOMPLETE
|
|
||||||
// hint under the cursor should be displayed before an INVALID hint
|
|
||||||
// somewhere else. That's good for displaying hints, but not good for
|
|
||||||
// deciding if we're good to go.
|
|
||||||
if (this.hints.length > 1) {
|
|
||||||
hintClone = this.hints.slice(0);
|
|
||||||
this.worstHint = Hint.sort(hintClone)[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a marked up version of the input
|
// Create a marked up version of the input
|
||||||
var highlightedInput = '';
|
var highlightedInput = '';
|
||||||
if (this.element.value.length > 0) {
|
if (this.element.value.length > 0) {
|
||||||
|
|
@ -335,11 +276,11 @@ CliView.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display the "-> prediction" at the end of the completer
|
// Display the "-> prediction" at the end of the completer
|
||||||
this.shownHint = (this.hints.length > 0) ? this.hints[0] : NO_HINT;
|
var display = this.hints.display || NO_HINT;
|
||||||
var message = this.shownHint.message;
|
var message = display.message;
|
||||||
if (this.shownHint.predictions && this.shownHint.predictions.length > 0) {
|
if (display.predictions && display.predictions.length > 0) {
|
||||||
message += ': [ ';
|
message += ': [ ';
|
||||||
this.shownHint.predictions.forEach(function(prediction) {
|
display.predictions.forEach(function(prediction) {
|
||||||
if (prediction.name) {
|
if (prediction.name) {
|
||||||
message += prediction.name + ' | ';
|
message += prediction.name + ' | ';
|
||||||
}
|
}
|
||||||
|
|
@ -349,16 +290,22 @@ CliView.prototype = {
|
||||||
}, this);
|
}, this);
|
||||||
message = message.replace(/\| $/, ']');
|
message = message.replace(/\| $/, ']');
|
||||||
|
|
||||||
var onTab = this.shownHint.predictions[0];
|
var onTab = display.predictions[0];
|
||||||
onTab = onTab.name ? onTab.name : onTab;
|
onTab = onTab.name ? onTab.name : onTab;
|
||||||
this.completer.innerHTML = highlightedInput + ' -> ' + onTab;
|
this.completer.innerHTML = highlightedInput + ' → ' + onTab;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.completer.innerHTML = highlightedInput;
|
this.completer.innerHTML = highlightedInput;
|
||||||
}
|
}
|
||||||
this.hinter.innerHTML = message;
|
this.hinter.innerHTML = message;
|
||||||
|
if (message.length === 0) {
|
||||||
|
this.hinter.classList.add('cptNoHints');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.hinter.classList.remove('cptNoHints');
|
||||||
|
}
|
||||||
|
|
||||||
var status = this.worstHint ? this.worstHint.status : Status.VALID;
|
var status = this.hints.worst ? this.hints.worst.status : Status.VALID;
|
||||||
this.completer.classList.add(status.toString());
|
this.completer.classList.add(status.toString());
|
||||||
// dom.addCssClass(input, status.toString());
|
// dom.addCssClass(input, status.toString());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ function RequestView(request, cliView) {
|
||||||
this.request = request;
|
this.request = request;
|
||||||
this.cliView = cliView;
|
this.cliView = cliView;
|
||||||
|
|
||||||
this.imagePath = '/plugins/ace/pluging/cockpit/ui';
|
this.imagePath = '/plugins/ace/plugins/cockpit/lib/ui/images';
|
||||||
|
|
||||||
// Elements attached to this by the templater. For info only
|
// Elements attached to this by the templater. For info only
|
||||||
this.rowin = null;
|
this.rowin = null;
|
||||||
|
|
@ -86,7 +86,7 @@ RequestView.prototype = {
|
||||||
* the command line
|
* the command line
|
||||||
*/
|
*/
|
||||||
copyToInput: function() {
|
copyToInput: function() {
|
||||||
this.cliView.input.value = this.request.typed;
|
this.cliView.element.value = this.request.typed;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -38,11 +38,26 @@
|
||||||
define(function(require, exports, module) {
|
define(function(require, exports, module) {
|
||||||
|
|
||||||
|
|
||||||
var showHintSetting = {
|
var types = require("pilot/types");
|
||||||
name: "showHint",
|
var SelectionType = require('pilot/types/basic').SelectionType;
|
||||||
description: "Do we display hints while we type?",
|
|
||||||
type: "bool",
|
var direction = new SelectionType({
|
||||||
defaultValue: true
|
name: 'direction',
|
||||||
|
data: [ 'above', 'below' ]
|
||||||
|
});
|
||||||
|
|
||||||
|
var hintDirectionSetting = {
|
||||||
|
name: "hintDirection",
|
||||||
|
description: "Are hints shown above or below the command line?",
|
||||||
|
type: "direction",
|
||||||
|
defaultValue: "above"
|
||||||
|
};
|
||||||
|
|
||||||
|
var outputDirectionSetting = {
|
||||||
|
name: "outputDirection",
|
||||||
|
description: "Is the output window shown above or below the command line?",
|
||||||
|
type: "direction",
|
||||||
|
defaultValue: "above"
|
||||||
};
|
};
|
||||||
|
|
||||||
var outputHeightSetting = {
|
var outputHeightSetting = {
|
||||||
|
|
@ -53,12 +68,16 @@ var outputHeightSetting = {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.startup = function(data, reason) {
|
exports.startup = function(data, reason) {
|
||||||
data.env.settings.addSetting(showHintSetting);
|
types.registerType(direction);
|
||||||
|
data.env.settings.addSetting(hintDirectionSetting);
|
||||||
|
data.env.settings.addSetting(outputDirectionSetting);
|
||||||
data.env.settings.addSetting(outputHeightSetting);
|
data.env.settings.addSetting(outputHeightSetting);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.shutdown = function(data, reason) {
|
exports.shutdown = function(data, reason) {
|
||||||
data.env.settings.removeSetting(showHintSetting);
|
types.unregisterType(direction);
|
||||||
|
data.env.settings.removeSetting(hintDirectionSetting);
|
||||||
|
data.env.settings.removeSetting(outputDirectionSetting);
|
||||||
data.env.settings.removeSetting(outputHeightSetting);
|
data.env.settings.removeSetting(outputHeightSetting);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@ var deps = [
|
||||||
"pilot/types/command",
|
"pilot/types/command",
|
||||||
"pilot/types/settings",
|
"pilot/types/settings",
|
||||||
"pilot/commands/settings",
|
"pilot/commands/settings",
|
||||||
|
"pilot/commands/basic",
|
||||||
|
// "pilot/commands/history",
|
||||||
"pilot/settings/canon",
|
"pilot/settings/canon",
|
||||||
"pilot/canon"
|
"pilot/canon"
|
||||||
];
|
];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue