Skip to content

Commit

Permalink
Merge branch 'master' into 1671_dom_renderer_stable
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyriar committed Sep 14, 2018
2 parents f204969 + 69a6c04 commit a19673d
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 61 deletions.
2 changes: 1 addition & 1 deletion README.md
@@ -1,6 +1,6 @@
# [![xterm.js logo](logo-full.png)](https://xtermjs.org)

[![VSTS Build status](https://xtermjs.visualstudio.com/_apis/public/build/definitions/3e323cf7-5760-460d-af64-ee5675baf366/1/badge)](https://xtermjs.visualstudio.com/xterm.js/_build/index?definitionId=1)
[![Build Status](https://dev.azure.com/xtermjs/xterm.js/_apis/build/status/xtermjs.xterm.js)](https://dev.azure.com/xtermjs/xterm.js/_build/latest?definitionId=3)
[![Coverage Status](https://coveralls.io/repos/github/xtermjs/xterm.js/badge.svg?branch=master)](https://coveralls.io/github/xtermjs/xterm.js?branch=master)
[![Gitter](https://badges.gitter.im/sourcelair/xterm.js.svg)](https://gitter.im/sourcelair/xterm.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![jsDelivr Hits](https://data.jsdelivr.com/v1/package/npm/xterm/badge?style=rounded)](https://www.jsdelivr.com/package/npm/xterm)
Expand Down
66 changes: 66 additions & 0 deletions azure-pipelines.yml
@@ -0,0 +1,66 @@
# Node.js
# Build a general Node.js application with npm.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/vsts/pipelines/languages/javascript

jobs:
- job: Linux
pool:
vmImage: 'ubuntu-16.04'
steps:
- task: NodeTool@0
inputs:
versionSpec: '8.x'
displayName: 'Install Node.js'
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.9.4"
displayName: 'Install Yarn'
- script: |
yarn
displayName: 'Install dependencies and build'
- script: |
yarn mocha
displayName: 'Test'
- script: |
yarn lint
displayName: 'Lint'
- script: |
yarn test-coverage
displayName: 'Generate and publish coverage'
- job: macOS
pool:
vmImage: 'xcode9-macos10.13'
steps:
- task: NodeTool@0
inputs:
versionSpec: '8.x'
displayName: 'Install Node.js'
- script: |
yarn
displayName: 'Install dependencies and build'
- script: |
yarn mocha
displayName: 'Test'
- script: |
yarn lint
displayName: 'Lint'
- job: Windows
pool:
vmImage: 'vs2017-win2016'
steps:
- task: NodeTool@0
inputs:
versionSpec: '8.x'
displayName: 'Install Node.js'
- script: |
yarn
displayName: 'Install dependencies and build'
- script: |
yarn mocha
displayName: 'Test'
- script: |
yarn lint
displayName: 'Lint'
20 changes: 10 additions & 10 deletions demo/client.ts
Expand Up @@ -8,12 +8,12 @@
/// <reference path="../typings/xterm.d.ts"/>

import { Terminal } from '../lib/public/Terminal';
import * as attach from '../build/addons/attach/attach';
import * as fit from '../build/addons/fit/fit';
import * as fullscreen from '../build/addons/fullscreen/fullscreen';
import * as search from '../build/addons/search/search';
import * as webLinks from '../build/addons/webLinks/webLinks';
import * as winptyCompat from '../build/addons/winptyCompat/winptyCompat';
import * as attach from '../lib/addons/attach/attach';
import * as fit from '../lib/addons/fit/fit';
import * as fullscreen from '../lib/addons/fullscreen/fullscreen';
import * as search from '../lib/addons/search/search';
import * as webLinks from '../lib/addons/webLinks/webLinks';
import * as winptyCompat from '../lib/addons/winptyCompat/winptyCompat';

// Pulling in the module's types relies on the <reference> above, it's looks a
// little weird here as we're importing "this" module
Expand Down Expand Up @@ -100,21 +100,21 @@ function createTerminal(): void {
addDomListener(actionElements.findNext, 'keypress', (e) => {
if (e.key === 'Enter') {
e.preventDefault();
let searchOptions = {
const searchOptions = {
regex: (document.getElementById('regex') as HTMLInputElement).checked,
wholeWord: false,
caseSensitive: false
caseSensitive: (document.getElementById('case-sensitive') as HTMLInputElement).checked
};
term.findNext(actionElements.findNext.value, searchOptions);
}
});
addDomListener(actionElements.findPrevious, 'keypress', (e) => {
if (e.key === 'Enter') {
e.preventDefault();
let searchOptions = {
const searchOptions = {
regex: (document.getElementById('regex') as HTMLInputElement).checked,
wholeWord: false,
caseSensitive: false
caseSensitive: (document.getElementById('case-sensitive') as HTMLInputElement).checked
};
term.findPrevious(actionElements.findPrevious.value, searchOptions);
}
Expand Down
1 change: 1 addition & 0 deletions demo/index.html
Expand Up @@ -17,6 +17,7 @@ <h3>Actions</h3>
<label>Find next <input id="find-next"/></label>
<label>Find previous <input id="find-previous"/></label>
<label>Use regex<input type="checkbox" id="regex"/></label>
<label>Case sensitive<input type="checkbox" id="case-sensitive"/></label>
</p>
</div>
<div>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -50,7 +50,7 @@
"scripts": {
"start": "node demo/start",
"start-zmodem": "node demo/zmodem/app",
"lint": "tslint 'src/**/*.ts'",
"lint": "tslint 'src/**/*.ts' './demo/**/*.ts'",
"test": "npm-run-all mocha lint",
"test-debug": "node --inspect-brk node_modules/.bin/gulp test",
"test-suite": "gulp mocha-suite --test",
Expand Down
54 changes: 46 additions & 8 deletions src/addons/search/SearchHelper.ts
Expand Up @@ -100,28 +100,44 @@ export class SearchHelper implements ISearchHelper {
}

/**
* Searches a line for a search term.
* @param term The search term.
* Searches a line for a search term. Takes the provided terminal line and searches the text line, which may contain
* subsequent terminal lines if the text is wrapped. If the provided line number is part of a wrapped text line that
* started on an earlier line then it is skipped since it will be properly searched when the terminal line that the
* text starts on is searched.
* @param term Tne search term.
* @param y The line to search.
* @param searchOptions Search options.
* @return The search result if it was found.
*/
protected _findInLine(term: string, y: number, searchOptions: ISearchOptions = {}): ISearchResult {
const lowerStringLine = this._terminal._core.buffer.translateBufferLineToString(y, true).toLowerCase();
const lowerTerm = term.toLowerCase();
if (this._terminal._core.buffer.lines.get(y).isWrapped) {
return;
}

const stringLine = this.translateBufferLineToStringWithWrap(y, true);
const searchStringLine = searchOptions.caseSensitive ? stringLine : stringLine.toLowerCase();
const searchTerm = searchOptions.caseSensitive ? term : term.toLowerCase();
let searchIndex = -1;

if (searchOptions.regex) {
const searchRegex = RegExp(lowerTerm, 'g');
const foundTerm = searchRegex.exec(lowerStringLine);
if (foundTerm) {
const searchRegex = RegExp(searchTerm, 'g');
const foundTerm = searchRegex.exec(searchStringLine);
if (foundTerm && foundTerm[0].length > 0) {
searchIndex = searchRegex.lastIndex - foundTerm[0].length;
term = foundTerm[0];
}
} else {
searchIndex = lowerStringLine.indexOf(lowerTerm);
searchIndex = searchStringLine.indexOf(searchTerm);
}

if (searchIndex >= 0) {
// Adjust the row number and search index if needed since a "line" of text can span multiple rows
if (searchIndex >= this._terminal.cols) {
y += Math.floor(searchIndex / this._terminal.cols);
searchIndex = searchIndex % this._terminal.cols;
}
const line = this._terminal._core.buffer.lines.get(y);

for (let i = 0; i < searchIndex; i++) {
const charData = line.get(i);
// Adjust the searchIndex to normalize emoji into single chars
Expand All @@ -144,6 +160,28 @@ export class SearchHelper implements ISearchHelper {
}
}

/**
* Translates a buffer line to a string, including subsequent lines if they are wraps.
* Wide characters will count as two columns in the resulting string. This
* function is useful for getting the actual text underneath the raw selection
* position.
* @param line The line being translated.
* @param trimRight Whether to trim whitespace to the right.
*/
public translateBufferLineToStringWithWrap(lineIndex: number, trimRight: boolean): string {
let lineString = '';
let lineWrapsToNext: boolean;

do {
const nextLine = this._terminal._core.buffer.lines.get(lineIndex + 1);
lineWrapsToNext = nextLine ? nextLine.isWrapped : false;
lineString += this._terminal._core.buffer.translateBufferLineToString(lineIndex, !lineWrapsToNext && trimRight);
lineIndex++;
} while (lineWrapsToNext);

return lineString;
}

/**
* Selects and scrolls to a result.
* @param result The result to select.
Expand Down

0 comments on commit a19673d

Please sign in to comment.