diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index 0db6c04f..722cc287 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -10,6 +10,7 @@ import { NULL_CELL_CHAR, NULL_CELL_CODE, NULL_CELL_WIDTH, CHAR_DATA_CHAR_INDEX } import { Terminal } from './Terminal'; import { IBufferLine } from './Types'; + // TODO: This and the sections related to this object in associated tests can be // removed safely after InputHandler refactors are finished class OldInputHandler extends InputHandler { @@ -445,4 +446,33 @@ describe('InputHandler', () => { expect(termContent(termNew)).eql(termContent(termOld)); }); }); + it('convertEol setting', function(): void { + // not converting + let s = ''; + const termNotConverting = new Terminal({cols: 15, rows: 10}); + (termNotConverting as any)._inputHandler.parse('Hello\nWorld'); + for (let i = 0; i < termNotConverting.cols; ++i) { + s += termNotConverting.buffer.lines.get(0).get(i)[CHAR_DATA_CHAR_INDEX]; + } + expect(s).equals('Hello '); + s = ''; + for (let i = 0; i < termNotConverting.cols; ++i) { + s += termNotConverting.buffer.lines.get(1).get(i)[CHAR_DATA_CHAR_INDEX]; + } + expect(s).equals(' World '); + + // converting + s = ''; + const termConverting = new Terminal({cols: 15, rows: 10, convertEol: true}); + (termConverting as any)._inputHandler.parse('Hello\nWorld'); + for (let i = 0; i < termConverting.cols; ++i) { + s += termConverting.buffer.lines.get(0).get(i)[CHAR_DATA_CHAR_INDEX]; + } + expect(s).equals('Hello '); + s = ''; + for (let i = 0; i < termConverting.cols; ++i) { + s += termConverting.buffer.lines.get(1).get(i)[CHAR_DATA_CHAR_INDEX]; + } + expect(s).equals('World '); + }); }); diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 3c6aae0f..ad5aad39 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -477,7 +477,7 @@ export class InputHandler extends Disposable implements IInputHandler { // make buffer local for faster access const buffer = this._terminal.buffer; - if (this._terminal.convertEol) { + if (this._terminal.options.convertEol) { buffer.x = 0; } buffer.y++; diff --git a/src/Terminal.ts b/src/Terminal.ts index 3a0ce0ed..3927d8b5 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -134,7 +134,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II // TODO: This can be changed to an enum or boolean, 0 and 1 seem to be the only options public cursorState: number; public cursorHidden: boolean; - public convertEol: boolean; private _customKeyEventHandler: CustomKeyEventHandler; diff --git a/src/Types.ts b/src/Types.ts index 5ea2024a..21c6c571 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -66,7 +66,6 @@ export interface IInputHandlingTerminal extends IEventEmitter { bell(): void; focus(): void; - convertEol: boolean; updateRange(y: number): void; scroll(isWrapped?: boolean): void; setgLevel(g: number): void; diff --git a/src/addons/search/SearchHelper.ts b/src/addons/search/SearchHelper.ts index 5ba81aa0..9b5c06f3 100644 --- a/src/addons/search/SearchHelper.ts +++ b/src/addons/search/SearchHelper.ts @@ -117,7 +117,7 @@ export class SearchHelper implements ISearchHelper { if (searchIndex >= 0) { const line = this._terminal._core.buffer.lines.get(y); for (let i = 0; i < searchIndex; i++) { - const charData = line[i]; + const charData = line.get(i); // Adjust the searchIndex to normalize emoji into single chars const char = charData[1/*CHAR_DATA_CHAR_INDEX*/]; if (char.length > 1) { diff --git a/src/addons/search/search.test.ts b/src/addons/search/search.test.ts new file mode 100644 index 00000000..91ecc4ef --- /dev/null +++ b/src/addons/search/search.test.ts @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert, expect } from 'chai'; +import * as search from './search'; +import { SearchHelper } from './SearchHelper'; +import { ISearchHelper } from './Interfaces'; + + +class MockTerminalPlain {} + +class MockTerminal { + private _core: any; + public searchHelper: ISearchHelper; + constructor(options: any) { + this._core = new (require('../../../lib/Terminal').Terminal)(options); + this.searchHelper = new SearchHelper(this as any); + } + get core(): any { + return this._core; + } + pushWriteData(): void { + this._core._innerWrite(); + } +} + +describe('search addon', function(): void { + describe('apply', () => { + it('should register findNext and findPrevious', () => { + search.apply(MockTerminalPlain); + assert.equal(typeof (MockTerminalPlain).prototype.findNext, 'function'); + assert.equal(typeof (MockTerminalPlain).prototype.findPrevious, 'function'); + }); + }); + it('Searchhelper - should find correct position', function(): void { + search.apply(MockTerminal); + const term = new MockTerminal({cols: 20, rows: 3}); + term.core.write('Hello World\r\ntest\n123....hello'); + term.pushWriteData(); + const hello0 = (term.searchHelper as any)._findInLine('Hello', 0); + const hello1 = (term.searchHelper as any)._findInLine('Hello', 1); + const hello2 = (term.searchHelper as any)._findInLine('Hello', 2); + expect(hello0).eql({col: 0, row: 0, term: 'Hello'}); + expect(hello1).eql(undefined); + expect(hello2).eql({col: 11, row: 2, term: 'Hello'}); + }); +}); diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index c8cc2cc6..80b41db5 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -39,6 +39,16 @@ declare module 'xterm' { */ bellStyle?: 'none' /*| 'visual'*/ | 'sound' /*| 'both'*/; + /** + * When enabled the cursor will be set to the beginning of the next line + * with every new line. This equivalent to sending '\r\n' for each '\n'. + * Normally the termios settings of the underlying PTY deals with the + * translation of '\n' to '\r\n' and this setting should not be used. If you + * deal with data from a non-PTY related source, this settings might be + * useful. + */ + convertEol?: boolean; + /** * The number of columns in the terminal. */