Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backend support (in flush) for newline : false #654

Merged
merged 12 commits into from
Apr 17, 2021
95 changes: 94 additions & 1 deletion __tests__/terminal.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2651,12 +2651,36 @@ describe('extensions', function() {
var command = 'hello';
term.set_prompt(prompt);
term.echo('.', {newline: false});
expect(term.get_output()).toEqual('.');
term.echo('.', {newline: false});
expect(term.get_output()).toEqual('..');
term.echo('.', {newline: false});
expect(term.get_output()).toEqual('...');
enter(term, command);
expect(term.get_output()).toEqual('...' + prompt + command);
expect(term.get_prompt()).toEqual(prompt);
});
it('get_prompt and set_prompt work as expected', function() {
var prompt1 = '>>> ';
var prompt2 = '~~~ ';
var command = 'hello';
term.set_prompt(prompt1);
term.echo('.', {newline: false});
expect(term.get_prompt()).toEqual(prompt1);
term.echo('.', {newline: false});
expect(term.get_prompt()).toEqual(prompt1);
term.set_prompt(prompt2);
term.echo('.', {newline: false});
expect(term.get_prompt()).toEqual(prompt2);
enter(term, command);
expect(term.get_output()).toEqual('...' + prompt2 + command);
expect(term.get_prompt()).toEqual(prompt2);
});
it('finalize with newline : false', function() {
term.echo('foo', {finalize: (a) => a.children().children().css("color", "red"), newline : false});
var color = term[0].querySelector(`[data-index='${term.last_index()}`).firstChild.firstChild.style.color;
expect(color).toEqual("red");
});
});
describe('autocomplete_menu', function() {
function completion(term) {
Expand Down Expand Up @@ -5482,14 +5506,83 @@ describe('Terminal plugin', function() {
});
// missing methods after version
describe('flush', function() {
var term = $('<div/>').terminal($.noop, {greetings: false});
it('should echo stuff that was called with flush false', function() {
var term = $('<div/>').terminal($.noop, {greetings: false});
term.echo('foo', {flush: false});
term.echo('bar', {flush: false});
term.echo('baz', {flush: false});
term.flush();
expect(term.find('.terminal-output').text()).toEqual('foobarbaz');
});
it('should flush correctly with newline : false', function(){
var term = $('<div/>').terminal($.noop, {
greetings : "greet"
});
var cmd = term.find(".cmd");

expect(term.find(".partial")[0]).toEqual(undefined);
expect(term.find("[data-index='0']").text()).toEqual("greet");

function getLastLineRect(partial){
let child = partial[0].lastElementChild;
child.style.width = "";
let rect = child.getBoundingClientRect();
child.style.width = "100%";
return rect;
}

term.echo("###", {newline : false});

var prompt = term.find(".cmd-prompt");
var partial = term.find(".partial");
var partial_children = partial.children();
var last_line_rect = getLastLineRect(partial);
expect(partial.attr("data-index")).toEqual("1");
expect(partial_children.length).toEqual(1);
expect(cmd.css("top")).toEqual(`${-last_line_rect.height}px`)
expect(prompt[0].style.marginLeft).toEqual(`${last_line_rect.width}px`);
expect(partial_children.first().text()).toEqual("###");

term.echo("aaa\nbbb\nccc", {newline : false});

var prompt = term.find(".cmd-prompt");
var partial = term.find(".partial");
var partial_children = partial.children();
var last_line_rect = getLastLineRect(partial);
expect(partial.attr("data-index")).toEqual("1");
expect(partial_children.length).toEqual(3);
expect(cmd.css("top")).toEqual(`${-last_line_rect.height}px`)
expect(prompt[0].style.marginLeft).toEqual(`${last_line_rect.width}px`);
expect(partial_children.eq(0).text()).toEqual("###aaa");
expect(partial_children.eq(1).text()).toEqual("bbb");
expect(partial_children.eq(2).text()).toEqual("ccc");
term.refresh();

var prompt = term.find(".cmd-prompt");
var partial = term.find(".partial");
var partial_children = partial.children();
var last_line_rect = getLastLineRect(partial);
expect(partial.attr("data-index")).toEqual("1");
expect(partial_children.length).toEqual(3);
expect(cmd.css("top")).toEqual(`${-last_line_rect.height}px`)
expect(prompt[0].style.marginLeft).toEqual(`${last_line_rect.width}px`);
expect(partial_children.eq(0).text()).toEqual("###aaa");
expect(partial_children.eq(1).text()).toEqual("bbb");
expect(partial_children.eq(2).text()).toEqual("ccc");

enter(term, "!!!");

var prompt = term.find(".cmd-prompt");
expect(cmd.css("top")).toEqual(`0px`)
expect(prompt[0].style.marginLeft).toEqual(`0px`);
expect(term.find("[data-index='1']").length).toEqual(1);
expect(term.find("[data-index='1']").children().last().text()).toEqual(nbsp("ccc> !!!"));
expect(term.find(".partial")[0]).toEqual(undefined);

term.refresh();
expect(term.find("[data-index='1']").length).toEqual(1);
expect(term.find("[data-index='1']").children().last().text()).toEqual(nbsp("ccc> !!!"));
});
});
describe('last_index', function() {
var term = $('<div/>').terminal($.noop, {greetings: false});
Expand Down
19 changes: 19 additions & 0 deletions css/jquery.terminal-src.css
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ body.full-screen-terminal .terminal {
.terminal .terminal-output > div:not(.raw) div {
white-space: nowrap;
}

.cmd .cmd-prompt > span {
float: left;
}
Expand Down Expand Up @@ -315,6 +316,11 @@ terminal .terminal-output > div {
.cmd .cmd-prompt {
position: relative;
z-index: 200;
/* Make sure prompt margin takes up space so that echo with newline : false
* works when prompt is empty
*/
border: 0.01px solid transparent;
float: left;
}
.cmd [role="presentation"]:not(.cmd-cursor-line) {
overflow: hidden;
Expand Down Expand Up @@ -684,6 +690,19 @@ terminal .terminal-output > div {
margin-bottom: 10px;
position: relative;
}

.terminal .partial {
position: relative;
z-index: 400;
}

.terminal div.partial > div {
width: -moz-fit-content;
width: -webkit-fit-content;
width: fit-content;
}


@supports (--css: variables) {
.terminal,
.terminal-output > :not(.raw) span[data-text]:not(.token):not(.inverted):not(.terminal-inverted):not(.cmd-inverted):not(.terminal-error):not(.emoji),
Expand Down
98 changes: 1 addition & 97 deletions js/echo_newline.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,100 +49,4 @@
// istanbul ignore next
factory(root.jQuery);
}
})(function($) {
var init = $.fn.terminal;
$.fn.terminal = function(interpreter, options) {
return init.call(this, interpreter, patch_options(options)).each(function() {
patch_term($(this).data('terminal'), should_echo_command(options));
});
};
var last = null;
var prompt = null;
function should_echo_command(options) {
return options && options.echoCommand !== false || !options;
}
function patch_options(options) {
var keymap = {
'ENTER': function(e, original) {
var term = this;
if (last === null) {
if (should_echo_command(options)) {
term.echo_command();
}
} else {
this.__echo(last + prompt + this.get_command());
this.set_prompt(prompt);
last = null;
}
if (options && options.keymap && options.keymap.ENTER) {
options.keymap.ENTER.call(this, e, original);
} else {
original.call(this, e);
}
}
};
var settings = {
echoCommand: false,
keymap: $.extend({}, options && options.keymap || {}, keymap)
};
return $.extend({}, options || {}, settings);
}
function patch_term(term, echo_command) {
if (term.__echo) {
return term;
}
term.__echo = term.echo;
term.__exec = term.exec;
term.__set_prompt = term.set_prompt;
term.exec = function() {
last = null;
if (echo_command) {
this.settings().echoCommand = true;
}
var ret = term.__exec.apply(this, arguments);
if (echo_command) {
this.settings().echoCommand = false;
}
return ret;
};
term.echo = function(arg, options) {
var settings = $.extend({
newline: true
}, options);
function process(prompt) {
if (last === null) {
last = arg;
} else {
last += arg;
}
term.__set_prompt(last + prompt);
}
if (settings.newline === false) {
if (prompt === null) {
prompt = term.get_prompt();
}
if (typeof prompt === 'string') {
process(prompt);
} else {
prompt(process);
}
} else {
if (prompt !== null) {
term.__set_prompt(prompt);
}
if (last !== null) {
term.__echo(last + arg, options);
} else if (!arguments.length) {
// original echo check length to test if someone call echo
// with value that is undefined
term.__echo();
} else {
term.__echo(arg, options);
}
prompt = null;
last = null;
}
return term;
};
}
});
})(function() {}); // eslint-disable-line no-empty-function
Loading