Merge pull request #492 from Tyriar/480_cursor_style

Implement CSI Ps SP q Set cursor style
This commit is contained in:
Daniel Imms
2017-01-20 07:26:36 -08:00
committed by GitHub
7 changed files with 127 additions and 8 deletions
-4
View File
@@ -20,7 +20,3 @@ h1 {
color: #fafafa;
padding: 2px;
}
#terminal-container .terminal:focus .terminal-cursor {
background-color: #fafafa;
}
+49
View File
@@ -0,0 +1,49 @@
import { assert } from 'chai';
import { InputHandler } from './InputHandler';
describe('InputHandler', () => {
describe('setCursorStyle', () => {
it('should call Terminal.setOption with correct params', () => {
let options = {};
let terminal = {
setOption: (option, value) => options[option] = value
};
let inputHandler = new InputHandler(terminal);
inputHandler.setCursorStyle([0]);
assert.equal(options['cursorStyle'], 'block');
assert.equal(options['cursorBlink'], true);
options = {};
inputHandler.setCursorStyle([1]);
assert.equal(options['cursorStyle'], 'block');
assert.equal(options['cursorBlink'], true);
options = {};
inputHandler.setCursorStyle([2]);
assert.equal(options['cursorStyle'], 'block');
assert.equal(options['cursorBlink'], false);
options = {};
inputHandler.setCursorStyle([3]);
assert.equal(options['cursorStyle'], 'underline');
assert.equal(options['cursorBlink'], true);
options = {};
inputHandler.setCursorStyle([4]);
assert.equal(options['cursorStyle'], 'underline');
assert.equal(options['cursorBlink'], false);
options = {};
inputHandler.setCursorStyle([5]);
assert.equal(options['cursorStyle'], 'bar');
assert.equal(options['cursorBlink'], true);
options = {};
inputHandler.setCursorStyle([6]);
assert.equal(options['cursorStyle'], 'bar');
assert.equal(options['cursorBlink'], false);
});
});
});
+30
View File
@@ -1392,6 +1392,36 @@ export class InputHandler implements IInputHandler {
this._terminal.charsets = [null]; // ??
}
/**
* CSI Ps SP q Set cursor style (DECSCUSR, VT520).
* Ps = 0 -> blinking block.
* Ps = 1 -> blinking block (default).
* Ps = 2 -> steady block.
* Ps = 3 -> blinking underline.
* Ps = 4 -> steady underline.
* Ps = 5 -> blinking bar (xterm).
* Ps = 6 -> steady bar (xterm).
*/
public setCursorStyle(params?: number[]): void {
const param = params[0] < 1 ? 1 : params[0];
switch (param) {
case 1:
case 2:
this._terminal.setOption('cursorStyle', 'block');
break;
case 3:
case 4:
this._terminal.setOption('cursorStyle', 'underline');
break;
case 5:
case 6:
this._terminal.setOption('cursorStyle', 'bar');
break;
}
const isBlinking = param % 2 === 1;
this._terminal.setOption('cursorBlink', isBlinking);
}
/**
* CSI Ps ; Ps r
* Set Scrolling Region [top;bottom] (default = full size of win-
+1
View File
@@ -79,6 +79,7 @@ export interface IInputHandler {
/** CSI m */ charAttributes(params?: number[]): void;
/** CSI n */ deviceStatus(params?: number[]): void;
/** CSI p */ softReset(params?: number[]): void;
/** CSI q */ setCursorStyle(params?: number[]): void;
/** CSI r */ setScrollRegion(params?: number[]): void;
/** CSI s */ saveCursor(params?: number[]): void;
/** CSI u */ restoreCursor(params?: number[]): void;
+7 -2
View File
@@ -95,7 +95,7 @@ csiParamStateHandler[' '] = (parser) => parser.setPostfix(' ');
csiParamStateHandler['\''] = (parser) => parser.setPostfix('\'');
csiParamStateHandler[';'] = (parser) => parser.finalizeParam();
const csiStateHandler: {[key: string]: (handler: IInputHandler, params: number[], prefix: string) => void} = {};
const csiStateHandler: {[key: string]: (handler: IInputHandler, params: number[], prefix: string, postfix: string) => void} = {};
csiStateHandler['@'] = (handler, params, prefix) => handler.insertChars(params);
csiStateHandler['A'] = (handler, params, prefix) => handler.cursorUp(params);
csiStateHandler['B'] = (handler, params, prefix) => handler.cursorDown(params);
@@ -136,6 +136,11 @@ csiStateHandler['p'] = (handler, params, prefix) => {
case '!': handler.softReset(params); break;
}
};
csiStateHandler['q'] = (handler, params, prefix, postfix) => {
if (postfix === ' ') {
handler.setCursorStyle(params);
}
};
csiStateHandler['r'] = (handler, params) => handler.setScrollRegion(params);
csiStateHandler['s'] = (handler, params) => handler.saveCursor(params);
csiStateHandler['u'] = (handler, params) => handler.restoreCursor(params);
@@ -472,7 +477,7 @@ export class Parser {
case ParserState.CSI:
if (ch in csiStateHandler) {
csiStateHandler[ch](this._inputHandler, this._terminal.params, this._terminal.prefix);
csiStateHandler[ch](this._inputHandler, this._terminal.params, this._terminal.prefix, this._terminal.postfix);
} else {
this._terminal.error('Unknown CSI code: %s.', ch);
}
+34 -2
View File
@@ -71,7 +71,7 @@
resize: none;
}
.terminal .terminal-cursor {
.terminal:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar) .terminal-cursor {
background-color: #fff;
color: #000;
}
@@ -82,7 +82,7 @@
background-color: transparent;
}
.terminal.focus.xterm-cursor-blink .terminal-cursor {
.terminal:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar).focus.xterm-cursor-blink .terminal-cursor {
animation: xterm-cursor-blink 1.2s infinite step-end;
}
@@ -97,6 +97,38 @@
}
}
.terminal.xterm-cursor-style-bar .terminal-cursor,
.terminal.xterm-cursor-style-underline .terminal-cursor {
position: relative;
}
.terminal.xterm-cursor-style-bar .terminal-cursor::before,
.terminal.xterm-cursor-style-underline .terminal-cursor::before {
content: "";
display: block;
position: absolute;
background-color: #fff;
}
.terminal.xterm-cursor-style-bar .terminal-cursor::before {
top: 0;
bottom: 0;
left: 0;
width: 1px;
}
.terminal.xterm-cursor-style-underline .terminal-cursor::before {
bottom: 0;
left: 0;
right: 0;
height: 1px;
}
.terminal.xterm-cursor-style-bar.focus.xterm-cursor-blink .terminal-cursor::before,
.terminal.xterm-cursor-style-underline.focus.xterm-cursor-blink .terminal-cursor::before {
animation: xterm-cursor-non-bar-blink 1.2s infinite step-end;
}
@keyframes xterm-cursor-non-bar-blink {
0% { background-color: #fff; }
50% { background-color: transparent; }
}
.terminal .composition-view {
background: #000;
color: #FFF;
+6
View File
@@ -353,6 +353,7 @@ Terminal.defaults = {
termName: 'xterm',
geometry: [80, 24],
cursorBlink: false,
cursorStyle: 'block',
visualBell: false,
popOnBell: false,
scrollback: 1000,
@@ -427,6 +428,11 @@ Terminal.prototype.setOption = function(key, value) {
this.options[key] = value;
switch (key) {
case 'cursorBlink': this.element.classList.toggle('xterm-cursor-blink', value); break;
case 'cursorStyle':
// Style 'block' applies with no class
this.element.classList.toggle(`xterm-cursor-style-underline`, value === 'underline');
this.element.classList.toggle(`xterm-cursor-style-bar`, value === 'bar');
break;
}
};