Merge branch 'master' into aeschli/html-extension
This commit is contained in:
commit
0aefa275cb
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
@ -19,7 +19,7 @@
|
|||
"lcov.path": ["./.build/coverage/lcov.info", "./.build/coverage-single/lcov.info"],
|
||||
"lcov.watch": [{
|
||||
"pattern": "**/*.test.js",
|
||||
"command": "${workspaceRoot}\\scripts\\test.sh --coverage --run ${file}",
|
||||
"command": "${workspaceRoot}/scripts/test.sh --coverage --run ${file}",
|
||||
"windows": {
|
||||
"command": "${workspaceRoot}\\scripts\\test.bat --coverage --run ${file}"
|
||||
}
|
||||
|
|
|
@ -23,9 +23,6 @@ function log(prefix, message) {
|
|||
gulpUtil.log(gulpUtil.colors.cyan('[' + prefix + ']'), message);
|
||||
}
|
||||
|
||||
const root = path.dirname(__dirname);
|
||||
const commit = util.getVersion(root);
|
||||
|
||||
exports.loaderConfig = function (emptyPaths) {
|
||||
const result = {
|
||||
paths: {
|
||||
|
@ -236,19 +233,16 @@ function uglifyWithCopyrights() {
|
|||
const uglifyStream = uglify({ preserveComments });
|
||||
|
||||
return es.through(function (data) {
|
||||
const _this = this;
|
||||
|
||||
onNewFile();
|
||||
|
||||
uglifyStream.once('data', function(data) {
|
||||
_this.emit('data', data);
|
||||
})
|
||||
uglifyStream.once('data', data => this.emit('data', data));
|
||||
uglifyStream.write(data);
|
||||
},
|
||||
function () { this.emit('end'); });
|
||||
}
|
||||
|
||||
exports.minifyTask = function (src, addSourceMapsComment) {
|
||||
exports.minifyTask = function (src, sourceMapBaseUrl) {
|
||||
const sourceMappingURL = sourceMapBaseUrl && (f => `${ sourceMapBaseUrl }/${ f.relative }.map`);
|
||||
|
||||
return function() {
|
||||
const jsFilter = filter('**/*.js', { restore: true });
|
||||
const cssFilter = filter('**/*.css', { restore: true });
|
||||
|
@ -262,12 +256,10 @@ exports.minifyTask = function (src, addSourceMapsComment) {
|
|||
.pipe(minifyCSS({ reduceIdents: false }))
|
||||
.pipe(cssFilter.restore)
|
||||
.pipe(sourcemaps.write('./', {
|
||||
sourceMappingURL: function (file) {
|
||||
return 'https://ticino.blob.core.windows.net/sourcemaps/' + commit + '/' + file.relative + '.map';
|
||||
},
|
||||
sourceMappingURL,
|
||||
sourceRoot: null,
|
||||
includeContent: true,
|
||||
addComment: addSourceMapsComment
|
||||
addComment: true
|
||||
}))
|
||||
.pipe(gulp.dest(src + '-min'));
|
||||
};
|
||||
|
|
|
@ -10,7 +10,6 @@ var buildfile = require('../src/buildfile');
|
|||
var util = require('./lib/util');
|
||||
var common = require('./gulpfile.common');
|
||||
var es = require('event-stream');
|
||||
var fs = require('fs');
|
||||
var File = require('vinyl');
|
||||
|
||||
var root = path.dirname(__dirname);
|
||||
|
@ -78,7 +77,7 @@ gulp.task('optimize-editor', ['clean-optimized-editor', 'compile-build'], common
|
|||
}));
|
||||
|
||||
gulp.task('clean-minified-editor', util.rimraf('out-editor-min'));
|
||||
gulp.task('minify-editor', ['clean-minified-editor', 'optimize-editor'], common.minifyTask('out-editor', true));
|
||||
gulp.task('minify-editor', ['clean-minified-editor', 'optimize-editor'], common.minifyTask('out-editor'));
|
||||
|
||||
gulp.task('clean-editor-distro', util.rimraf('out-monaco-editor-core'));
|
||||
gulp.task('editor-distro', ['clean-editor-distro', 'minify-editor', 'optimize-editor'], function() {
|
||||
|
|
|
@ -6,59 +6,63 @@
|
|||
// Increase max listeners for event emitters
|
||||
require('events').EventEmitter.defaultMaxListeners = 100;
|
||||
|
||||
var gulp = require('gulp');
|
||||
var path = require('path');
|
||||
var tsb = require('gulp-tsb');
|
||||
var es = require('event-stream');
|
||||
var filter = require('gulp-filter');
|
||||
var rimraf = require('rimraf');
|
||||
var util = require('./lib/util');
|
||||
var watcher = require('./lib/watch');
|
||||
var createReporter = require('./lib/reporter');
|
||||
var glob = require('glob');
|
||||
var sourcemaps = require('gulp-sourcemaps');
|
||||
var nlsDev = require('vscode-nls-dev');
|
||||
const gulp = require('gulp');
|
||||
const path = require('path');
|
||||
const tsb = require('gulp-tsb');
|
||||
const es = require('event-stream');
|
||||
const filter = require('gulp-filter');
|
||||
const rimraf = require('rimraf');
|
||||
const util = require('./lib/util');
|
||||
const watcher = require('./lib/watch');
|
||||
const createReporter = require('./lib/reporter');
|
||||
const glob = require('glob');
|
||||
const sourcemaps = require('gulp-sourcemaps');
|
||||
const nlsDev = require('vscode-nls-dev');
|
||||
const root = path.dirname(__dirname);
|
||||
const commit = util.getVersion(root);
|
||||
|
||||
var extensionsPath = path.join(path.dirname(__dirname), 'extensions');
|
||||
const extensionsPath = path.join(path.dirname(__dirname), 'extensions');
|
||||
|
||||
var compilations = glob.sync('**/tsconfig.json', {
|
||||
const compilations = glob.sync('**/tsconfig.json', {
|
||||
cwd: extensionsPath,
|
||||
ignore: ['**/out/**', '**/node_modules/**']
|
||||
});
|
||||
|
||||
var languages = ['chs', 'cht', 'jpn', 'kor', 'deu', 'fra', 'esn', 'rus', 'ita'];
|
||||
const getBaseUrl = out => `https://ticino.blob.core.windows.net/sourcemaps/${ commit }/${ out }`;
|
||||
const languages = ['chs', 'cht', 'jpn', 'kor', 'deu', 'fra', 'esn', 'rus', 'ita'];
|
||||
|
||||
var tasks = compilations.map(function(tsconfigFile) {
|
||||
var absolutePath = path.join(extensionsPath, tsconfigFile);
|
||||
var relativeDirname = path.dirname(tsconfigFile);
|
||||
const tasks = compilations.map(function(tsconfigFile) {
|
||||
const absolutePath = path.join(extensionsPath, tsconfigFile);
|
||||
const relativeDirname = path.dirname(tsconfigFile);
|
||||
|
||||
var tsOptions = require(absolutePath).compilerOptions;
|
||||
const tsOptions = require(absolutePath).compilerOptions;
|
||||
tsOptions.verbose = false;
|
||||
tsOptions.sourceMap = true;
|
||||
|
||||
var name = relativeDirname.replace(/\//g, '-');
|
||||
const name = relativeDirname.replace(/\//g, '-');
|
||||
|
||||
// Tasks
|
||||
var clean = 'clean-extension:' + name;
|
||||
var compile = 'compile-extension:' + name;
|
||||
var watch = 'watch-extension:' + name;
|
||||
const clean = 'clean-extension:' + name;
|
||||
const compile = 'compile-extension:' + name;
|
||||
const watch = 'watch-extension:' + name;
|
||||
|
||||
// Build Tasks
|
||||
var cleanBuild = 'clean-extension-build:' + name;
|
||||
var compileBuild = 'compile-extension-build:' + name;
|
||||
var watchBuild = 'watch-extension-build:' + name;
|
||||
const cleanBuild = 'clean-extension-build:' + name;
|
||||
const compileBuild = 'compile-extension-build:' + name;
|
||||
const watchBuild = 'watch-extension-build:' + name;
|
||||
|
||||
var root = path.join('extensions', relativeDirname);
|
||||
var srcBase = path.join(root, 'src');
|
||||
var src = path.join(srcBase, '**');
|
||||
var out = path.join(root, 'out');
|
||||
var i18n = path.join(__dirname, '..', 'i18n');
|
||||
const root = path.join('extensions', relativeDirname);
|
||||
const srcBase = path.join(root, 'src');
|
||||
const src = path.join(srcBase, '**');
|
||||
const out = path.join(root, 'out');
|
||||
const i18n = path.join(__dirname, '..', 'i18n');
|
||||
const baseUrl = getBaseUrl(out);
|
||||
|
||||
function createPipeline(build) {
|
||||
var reporter = createReporter();
|
||||
const reporter = createReporter();
|
||||
|
||||
tsOptions.inlineSources = !!build;
|
||||
var compilation = tsb.create(tsOptions, null, null, err => reporter(err.toString()));
|
||||
const compilation = tsb.create(tsOptions, null, null, err => reporter(err.toString()));
|
||||
|
||||
return function () {
|
||||
const input = es.through();
|
||||
|
@ -68,13 +72,12 @@ var tasks = compilations.map(function(tsconfigFile) {
|
|||
.pipe(util.loadSourcemaps())
|
||||
.pipe(compilation())
|
||||
.pipe(build ? nlsDev.rewriteLocalizeCalls() : es.through())
|
||||
.pipe(build ? util.stripSourceMappingURL() : es.through())
|
||||
.pipe(sourcemaps.write('.', {
|
||||
addComment: false,
|
||||
sourceMappingURL: !build ? null : f => `${ baseUrl }/${ f.relative }.map`,
|
||||
addComment: !!build,
|
||||
includeContent: !!build,
|
||||
sourceRoot: function(file) {
|
||||
const levels = file.relative.split(path.sep).length;
|
||||
return '../'.repeat(levels) + 'src';
|
||||
}
|
||||
sourceRoot: file => '../'.repeat(file.relative.split(path.sep).length) + 'src'
|
||||
}))
|
||||
.pipe(tsFilter.restore)
|
||||
.pipe(build ? nlsDev.createAdditionalLanguageFiles(languages, i18n, out) : es.through())
|
||||
|
@ -86,11 +89,9 @@ var tasks = compilations.map(function(tsconfigFile) {
|
|||
|
||||
const srcOpts = { cwd: path.dirname(__dirname), base: srcBase };
|
||||
|
||||
gulp.task(clean, function (cb) {
|
||||
rimraf(out, cb);
|
||||
});
|
||||
gulp.task(clean, cb => rimraf(out, cb));
|
||||
|
||||
gulp.task(compile, [clean], function () {
|
||||
gulp.task(compile, [clean], () => {
|
||||
const pipeline = createPipeline(false);
|
||||
const input = gulp.src(src, srcOpts);
|
||||
|
||||
|
@ -99,7 +100,7 @@ var tasks = compilations.map(function(tsconfigFile) {
|
|||
.pipe(gulp.dest(out));
|
||||
});
|
||||
|
||||
gulp.task(watch, [clean], function () {
|
||||
gulp.task(watch, [clean], () => {
|
||||
const pipeline = createPipeline(false);
|
||||
const input = gulp.src(src, srcOpts);
|
||||
const watchInput = watcher(src, srcOpts);
|
||||
|
@ -109,11 +110,9 @@ var tasks = compilations.map(function(tsconfigFile) {
|
|||
.pipe(gulp.dest(out));
|
||||
});
|
||||
|
||||
gulp.task(cleanBuild, function (cb) {
|
||||
rimraf(out, cb);
|
||||
});
|
||||
gulp.task(cleanBuild, cb => rimraf(out, cb));
|
||||
|
||||
gulp.task(compileBuild, [clean], function () {
|
||||
gulp.task(compileBuild, [clean], () => {
|
||||
const pipeline = createPipeline(true);
|
||||
const input = gulp.src(src, srcOpts);
|
||||
|
||||
|
@ -122,13 +121,13 @@ var tasks = compilations.map(function(tsconfigFile) {
|
|||
.pipe(gulp.dest(out));
|
||||
});
|
||||
|
||||
gulp.task(watchBuild, [clean], function () {
|
||||
gulp.task(watchBuild, [clean], () => {
|
||||
const pipeline = createPipeline(true);
|
||||
const input = gulp.src(src, srcOpts);
|
||||
const watchInput = watcher(src, srcOpts);
|
||||
|
||||
return watchInput
|
||||
.pipe(util.incremental(function () { return pipeline(true); }, input))
|
||||
.pipe(util.incremental(() => pipeline(true), input))
|
||||
.pipe(gulp.dest(out));
|
||||
});
|
||||
|
||||
|
@ -142,10 +141,10 @@ var tasks = compilations.map(function(tsconfigFile) {
|
|||
};
|
||||
});
|
||||
|
||||
gulp.task('clean-extensions', tasks.map(function (t) { return t.clean; }));
|
||||
gulp.task('compile-extensions', tasks.map(function (t) { return t.compile; }));
|
||||
gulp.task('watch-extensions', tasks.map(function (t) { return t.watch; }));
|
||||
gulp.task('clean-extensions', tasks.map(t => t.clean));
|
||||
gulp.task('compile-extensions', tasks.map(t => t.compile));
|
||||
gulp.task('watch-extensions', tasks.map(t => t.watch));
|
||||
|
||||
gulp.task('clean-extensions-build', tasks.map(function (t) { return t.cleanBuild; }));
|
||||
gulp.task('compile-extensions-build', tasks.map(function (t) { return t.compileBuild; }));
|
||||
gulp.task('watch-extensions-build', tasks.map(function (t) { return t.watchBuild; }));
|
||||
gulp.task('clean-extensions-build', tasks.map(t => t.cleanBuild));
|
||||
gulp.task('compile-extensions-build', tasks.map(t => t.compileBuild));
|
||||
gulp.task('watch-extensions-build', tasks.map(t => t.watchBuild));
|
|
@ -86,8 +86,9 @@ gulp.task('optimize-vscode', ['clean-optimized-vscode', 'compile-build', 'compil
|
|||
out: 'out-vscode'
|
||||
}));
|
||||
|
||||
const baseUrl = `https://ticino.blob.core.windows.net/sourcemaps/${ commit }/core`;
|
||||
gulp.task('clean-minified-vscode', util.rimraf('out-vscode-min'));
|
||||
gulp.task('minify-vscode', ['clean-minified-vscode', 'optimize-vscode'], common.minifyTask('out-vscode', true));
|
||||
gulp.task('minify-vscode', ['clean-minified-vscode', 'optimize-vscode'], common.minifyTask('out-vscode', baseUrl));
|
||||
|
||||
// Package
|
||||
const darwinCreditsTemplate = product.darwinCredits && _.template(fs.readFileSync(path.join(root, product.darwinCredits), 'utf8'));
|
||||
|
@ -269,8 +270,16 @@ gulp.task('vscode-linux-arm-min', ['minify-vscode', 'clean-vscode-linux-arm'], p
|
|||
|
||||
// Sourcemaps
|
||||
|
||||
gulp.task('upload-vscode-sourcemaps', ['minify-vscode'], function () {
|
||||
return gulp.src('out-vscode-min/**/*.map')
|
||||
gulp.task('upload-vscode-sourcemaps', ['minify-vscode'], () => {
|
||||
const vs = gulp.src('out-vscode-min/**/*.map', { base: 'out-vscode-min' })
|
||||
.pipe(es.mapSync(f => {
|
||||
f.path = `${ f.base }/core/${ f.relative }`;
|
||||
return f;
|
||||
}));
|
||||
|
||||
const extensions = gulp.src('extensions/**/out/**/*.map', { base: '.' });
|
||||
|
||||
return es.merge(vs, extensions)
|
||||
.pipe(azure.upload({
|
||||
account: process.env.AZURE_STORAGE_ACCOUNT,
|
||||
key: process.env.AZURE_STORAGE_ACCESS_KEY,
|
||||
|
|
|
@ -154,18 +154,6 @@ exports.toFileUri = filePath => {
|
|||
return 'file://' + filePath.replace(/\\/g, '/');
|
||||
};
|
||||
|
||||
exports.rebase = (base, append) => {
|
||||
return es.mapSync(f => {
|
||||
if (append) {
|
||||
f.base = path.join(f.base, base);
|
||||
} else {
|
||||
f.base = base;
|
||||
}
|
||||
|
||||
return f;
|
||||
});
|
||||
};
|
||||
|
||||
exports.skipDirectories = () => {
|
||||
return es.mapSync(f => {
|
||||
if (!f.isDirectory()) {
|
||||
|
@ -241,6 +229,19 @@ exports.loadSourcemaps = () => {
|
|||
return es.duplex(input, output);
|
||||
};
|
||||
|
||||
exports.stripSourceMappingURL = () => {
|
||||
const input = es.through();
|
||||
|
||||
const output = input
|
||||
.pipe(es.mapSync(f => {
|
||||
const contents = f.contents.toString('utf8');
|
||||
f.contents = new Buffer(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, ''), 'utf8');
|
||||
return f;
|
||||
}));
|
||||
|
||||
return es.duplex(input, output);
|
||||
};
|
||||
|
||||
exports.rimraf = dir => {
|
||||
let retries = 0;
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ declare module monaco {
|
|||
#include(vs/base/common/winjs.base.d.ts): TValueCallback, ProgressCallback, TPromise
|
||||
#include(vs/base/common/cancellation): CancellationTokenSource, CancellationToken
|
||||
#include(vs/base/common/uri): URI
|
||||
#include(vs/base/common/keyCodes): KeyCode, KeyMod
|
||||
#include(vs/editor/common/standalone/standaloneBase): KeyCode, KeyMod
|
||||
#include(vs/base/common/htmlContent): MarkedString
|
||||
#include(vs/base/browser/keyboardEvent): IKeyboardEvent
|
||||
#include(vs/base/browser/mouseEvent): IMouseEvent
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
var win = "Please run '.\\scripts\\npm.bat install' instead."
|
||||
var nix = "Please run './scripts/npm.sh install' instead."
|
||||
var win = "Please run '.\\scripts\\npm.bat install' instead.";
|
||||
var nix = "Please run './scripts/npm.sh install' instead.";
|
||||
|
||||
if (process.env['npm_config_disturl'] !== 'https://atom.io/download/atom-shell') {
|
||||
console.error("You can't use plain npm to install Code's dependencies.");
|
||||
console.error(/^win/.test(process.platform) ? win : nix);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -758,9 +758,9 @@ Root: HKCU; Subkey: "Environment"; ValueType: expandsz; ValueName: "Path"; Value
|
|||
Root: HKCU; Subkey: "SOFTWARE\Classes\*\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "Open with {#NameShort}"; Tasks: addcontextmenufiles; Flags: uninsdeletekey
|
||||
Root: HKCU; Subkey: "SOFTWARE\Classes\*\shell\{#RegValueName}"; ValueType: expandsz; ValueName: "Icon"; ValueData: "{app}\{#ExeBasename}.exe"; Tasks: addcontextmenufiles
|
||||
Root: HKCU; Subkey: "SOFTWARE\Classes\*\shell\{#RegValueName}\command"; ValueType: expandsz; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""; Tasks: addcontextmenufiles
|
||||
Root: HKCU; Subkey: "SOFTWARE\Classes\directory\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "Open with {#NameShort}"; Tasks: addcontextmenufolders; Flags: uninsdeletekey
|
||||
Root: HKCU; Subkey: "SOFTWARE\Classes\directory\shell\{#RegValueName}"; ValueType: expandsz; ValueName: "Icon"; ValueData: "{app}\{#ExeBasename}.exe"; Tasks: addcontextmenufolders
|
||||
Root: HKCU; Subkey: "SOFTWARE\Classes\directory\shell\{#RegValueName}\command"; ValueType: expandsz; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%V"""; Tasks: addcontextmenufolders
|
||||
Root: HKCU; Subkey: "SOFTWARE\Classes\Folder\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "Open with {#NameShort}"; Tasks: addcontextmenufolders; Flags: uninsdeletekey
|
||||
Root: HKCU; Subkey: "SOFTWARE\Classes\Folder\shell\{#RegValueName}"; ValueType: expandsz; ValueName: "Icon"; ValueData: "{app}\{#ExeBasename}.exe"; Tasks: addcontextmenufolders
|
||||
Root: HKCU; Subkey: "SOFTWARE\Classes\Folder\shell\{#RegValueName}\command"; ValueType: expandsz; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%V"""; Tasks: addcontextmenufolders
|
||||
Root: HKCU; Subkey: "SOFTWARE\Classes\directory\background\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "Open with {#NameShort}"; Tasks: addcontextmenufolders; Flags: uninsdeletekey
|
||||
Root: HKCU; Subkey: "SOFTWARE\Classes\directory\background\shell\{#RegValueName}"; ValueType: expandsz; ValueName: "Icon"; ValueData: "{app}\{#ExeBasename}.exe"; Tasks: addcontextmenufolders
|
||||
Root: HKCU; Subkey: "SOFTWARE\Classes\directory\background\shell\{#RegValueName}\command"; ValueType: expandsz; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%V"""; Tasks: addcontextmenufolders
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
import {window, workspace, DecorationOptions, DecorationRenderOptions, Disposable, Range, TextDocument, TextEditor} from 'vscode';
|
||||
|
||||
const MAX_DECORATORS = 500;
|
||||
|
||||
let decorationType: DecorationRenderOptions = {
|
||||
before: {
|
||||
contentText: ' ',
|
||||
|
@ -76,7 +78,7 @@ export function activateColorDecorations(decoratorProvider: (uri: string) => The
|
|||
let document = editor.document;
|
||||
if (supportedLanguages[document.languageId]) {
|
||||
decoratorProvider(document.uri.toString()).then(ranges => {
|
||||
let decorations = ranges.map(range => {
|
||||
let decorations = ranges.slice(0, MAX_DECORATORS).map(range => {
|
||||
let color = document.getText(range);
|
||||
return <DecorationOptions>{
|
||||
range: range,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"comments": {
|
||||
"lineComment": "//",
|
||||
"blockComment": [ "/*", "*/" ]
|
||||
"lineComment": "#",
|
||||
"blockComment": [ "#", " " ]
|
||||
},
|
||||
"brackets": [
|
||||
["{", "}"],
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"comments": {
|
||||
"lineComment": "//",
|
||||
"blockComment": [ "/*", "*/" ]
|
||||
"lineComment": "#",
|
||||
"blockComment": [ "#", " " ]
|
||||
},
|
||||
"brackets": [
|
||||
["{", "}"],
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"account": "monacobuild",
|
||||
"container": "debuggers",
|
||||
"zip": "864e0bd/node-debug.zip",
|
||||
"zip": "d643199/node-debug.zip",
|
||||
"output": ""
|
||||
}
|
||||
|
|
|
@ -54,6 +54,35 @@ function invertColor(color) {
|
|||
return res;
|
||||
}
|
||||
|
||||
function getLanguageMappings() {
|
||||
var langToExt = {
|
||||
'csharp': ['cs', 'csx']
|
||||
};
|
||||
|
||||
var allExtensions = fs.readdirSync('..');
|
||||
for (var i= 0; i < allExtensions.length; i++) {
|
||||
let dirPath = path.join('..', allExtensions[i], 'package.json');
|
||||
if (!fs.lstatSync(path.join('..', allExtensions[i])).isDirectory() || !fs.lstatSync(dirPath).isFile()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let content = fs.readFileSync(dirPath).toString();
|
||||
let jsonContent = JSON.parse(content);
|
||||
let languages = jsonContent.contributes && jsonContent.contributes.languages;
|
||||
if (Array.isArray(languages)) {
|
||||
for (var k = 0; k < languages.length; k++) {
|
||||
var extensions = languages[k].extensions;
|
||||
var languageId = languages[k].id;
|
||||
if (Array.isArray(extensions) && languageId) {
|
||||
langToExt[languageId] = extensions.map(function (e) { return e.substr(1); });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return langToExt;
|
||||
}
|
||||
|
||||
|
||||
exports.update = function () {
|
||||
var fontMappings = 'https://raw.githubusercontent.com/jesseweed/seti-ui/master/styles/_fonts/seti.less';
|
||||
|
@ -63,6 +92,7 @@ exports.update = function () {
|
|||
var fileName2Def = {};
|
||||
var def2ColorId = {};
|
||||
var colorId2Value = {};
|
||||
var lang2Def = {};
|
||||
|
||||
function writeFileIconContent(info) {
|
||||
var iconDefinitions = {};
|
||||
|
@ -106,14 +136,16 @@ exports.update = function () {
|
|||
file: "_default",
|
||||
fileExtensions: ext2Def,
|
||||
fileNames: fileName2Def,
|
||||
languageIds: lang2Def,
|
||||
light: {
|
||||
file: "_default_light",
|
||||
fileExtensions: getInvertSet(ext2Def),
|
||||
languageIds: getInvertSet(lang2Def),
|
||||
fileNames: getInvertSet(fileName2Def)
|
||||
},
|
||||
version: 'https://github.com/jesseweed/seti-ui/commit/' + info.commitSha,
|
||||
};
|
||||
fs.writeFileSync('./icons/seti-icon-theme.json', JSON.stringify(res, null, '\t'));
|
||||
fs.writeFileSync('./icons/vs-seti-icon-theme.json', JSON.stringify(res, null, '\t'));
|
||||
|
||||
}
|
||||
|
||||
|
@ -140,6 +172,26 @@ exports.update = function () {
|
|||
}
|
||||
def2ColorId[def] = colorId;
|
||||
}
|
||||
// replace extensions for languageId
|
||||
var langToExt = getLanguageMappings();
|
||||
for (var lang in langToExt) {
|
||||
var exts = langToExt[lang];
|
||||
var preferredDef = null;
|
||||
// use the first file association for the preferred definition
|
||||
for (var i1 = 0; i1 < exts.length && !preferredDef; i1++) {
|
||||
preferredDef = ext2Def[exts[i1]];
|
||||
}
|
||||
if (preferredDef) {
|
||||
lang2Def[lang] = preferredDef;
|
||||
for (var i1 = 0; i1 < exts.length; i1++) {
|
||||
// remove the extention association, unless it is different from the preferred
|
||||
if (ext2Def[exts[i1]] === preferredDef) {
|
||||
delete ext2Def[exts[i1]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var colors = 'https://raw.githubusercontent.com/jesseweed/seti-ui/master/styles/ui-variables.less';
|
||||
return download(colors).then(function (content) {
|
||||
var regex3 = /(@[\w-]+):\s*(#[0-9a-z]+)/g;
|
||||
|
@ -156,7 +208,7 @@ exports.update = function () {
|
|||
console.error(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}, console.error);
|
||||
}
|
||||
|
|
|
@ -701,16 +701,9 @@
|
|||
},
|
||||
"file": "_default",
|
||||
"fileExtensions": {
|
||||
"cpp": "_cpp",
|
||||
"c": "_c",
|
||||
"cs": "_c-sharp",
|
||||
"cc": "_cpp",
|
||||
"cfc": "_coldfusion",
|
||||
"cfm": "_coldfusion",
|
||||
"coffee": "_coffee",
|
||||
"config": "_config",
|
||||
"cson": "_json",
|
||||
"css": "_css",
|
||||
"css.map": "_css",
|
||||
"sss": "_css",
|
||||
"csv": "_csv",
|
||||
|
@ -719,14 +712,11 @@
|
|||
"elm": "_elm",
|
||||
"ico": "_favicon",
|
||||
"gitignore": "_github",
|
||||
"gitconfig": "_github",
|
||||
"gitkeep": "_github",
|
||||
"gitattributes": "_github",
|
||||
"go": "_go2",
|
||||
"slide": "_go",
|
||||
"article": "_go",
|
||||
"gradle": "_gradle",
|
||||
"groovy": "_grails",
|
||||
"gsp": "_grails",
|
||||
"hh": "_hacklang",
|
||||
"haml": "_haml",
|
||||
|
@ -735,57 +725,37 @@
|
|||
"hjs": "_mustache",
|
||||
"hs": "_haskell",
|
||||
"lhs": "_haskell",
|
||||
"html": "_html",
|
||||
"jade": "_jade",
|
||||
"java": "_java",
|
||||
"class": "_java",
|
||||
"classpath": "_java",
|
||||
"js": "_javascript",
|
||||
"js.map": "_javascript",
|
||||
"es": "_javascript",
|
||||
"es5": "_javascript",
|
||||
"es6": "_javascript",
|
||||
"es7": "_javascript",
|
||||
"json": "_json",
|
||||
"jl": "_julia",
|
||||
"less": "_less",
|
||||
"liquid": "_liquid",
|
||||
"ls": "_livescript",
|
||||
"lua": "_lua",
|
||||
"markdown": "_markdown",
|
||||
"md": "_markdown",
|
||||
"mustache": "_mustache",
|
||||
"stache": "_mustache",
|
||||
"npm-debug.log": "_npm",
|
||||
"npmignore": "_npm",
|
||||
"h": "_c",
|
||||
"m": "_c",
|
||||
"ml": "_ocaml",
|
||||
"mli": "_ocaml",
|
||||
"cmx": "_ocaml",
|
||||
"cmxa": "_ocaml",
|
||||
"pl": "_perl",
|
||||
"php": "_php",
|
||||
"php.inc": "_php",
|
||||
"pug": "_pug",
|
||||
"pp": "_puppet",
|
||||
"py": "_python",
|
||||
"jsx": "_react",
|
||||
"cjsx": "_react",
|
||||
"tsx": "_react",
|
||||
"rb": "_ruby",
|
||||
"erb": "_ruby",
|
||||
"erb.html": "_ruby",
|
||||
"html.erb": "_ruby",
|
||||
"rs": "_rust",
|
||||
"sass": "_sass",
|
||||
"scss": "_sass",
|
||||
"slim": "_slim",
|
||||
"smarty.tpl": "_smarty",
|
||||
"sbt": "_sbt",
|
||||
"scala": "_scala",
|
||||
"styl": "_stylus",
|
||||
"swift": "_swift",
|
||||
"tf": "_terraform",
|
||||
"tf.json": "_terraform",
|
||||
"tex": "_tex",
|
||||
|
@ -795,12 +765,9 @@
|
|||
"ins": "_tex",
|
||||
"txt": "_default",
|
||||
"twig": "_twig",
|
||||
"ts": "_typescript",
|
||||
"vala": "_vala",
|
||||
"vapi": "_vala",
|
||||
"xml": "_xml",
|
||||
"yml": "_yml",
|
||||
"yaml": "_yml",
|
||||
"ai": "_illustrator",
|
||||
"psd": "_photoshop",
|
||||
"pdf": "_pdf",
|
||||
|
@ -814,11 +781,7 @@
|
|||
"jpeg": "_image",
|
||||
"svg": "_svg",
|
||||
"svgx": "_image",
|
||||
"cmd": "_shell",
|
||||
"sh": "_shell",
|
||||
"zsh": "_shell",
|
||||
"fish": "_shell",
|
||||
"zshrc": "_shell",
|
||||
"mov": "_video",
|
||||
"ogv": "_video",
|
||||
"webm": "_video",
|
||||
|
@ -865,19 +828,45 @@
|
|||
"TODO": "_todo",
|
||||
"npm-debug.log": "_npm_ignored"
|
||||
},
|
||||
"languageIds": {
|
||||
"csharp": "_c-sharp",
|
||||
"bat": "_shell",
|
||||
"coffeescript": "_coffee",
|
||||
"c": "_c",
|
||||
"cpp": "_cpp",
|
||||
"css": "_css",
|
||||
"go": "_go2",
|
||||
"groovy": "_grails",
|
||||
"html": "_html",
|
||||
"ini": "_github",
|
||||
"jade": "_jade",
|
||||
"java": "_java",
|
||||
"javascriptreact": "_react",
|
||||
"javascript": "_javascript",
|
||||
"json": "_json",
|
||||
"less": "_less",
|
||||
"lua": "_lua",
|
||||
"markdown": "_markdown",
|
||||
"objective-c": "_c",
|
||||
"perl": "_perl",
|
||||
"php": "_php",
|
||||
"python": "_python",
|
||||
"ruby": "_ruby",
|
||||
"rust": "_rust",
|
||||
"scss": "_sass",
|
||||
"shellscript": "_shell",
|
||||
"swift": "_swift",
|
||||
"typescript": "_typescript",
|
||||
"typescriptreact": "_react",
|
||||
"xml": "_config",
|
||||
"yaml": "_yml"
|
||||
},
|
||||
"light": {
|
||||
"file": "_default_light",
|
||||
"fileExtensions": {
|
||||
"cpp": "_cpp_light",
|
||||
"c": "_c_light",
|
||||
"cs": "_c-sharp_light",
|
||||
"cc": "_cpp_light",
|
||||
"cfc": "_coldfusion_light",
|
||||
"cfm": "_coldfusion_light",
|
||||
"coffee": "_coffee_light",
|
||||
"config": "_config_light",
|
||||
"cson": "_json_light",
|
||||
"css": "_css_light",
|
||||
"css.map": "_css_light",
|
||||
"sss": "_css_light",
|
||||
"csv": "_csv_light",
|
||||
|
@ -886,14 +875,11 @@
|
|||
"elm": "_elm_light",
|
||||
"ico": "_favicon_light",
|
||||
"gitignore": "_github_light",
|
||||
"gitconfig": "_github_light",
|
||||
"gitkeep": "_github_light",
|
||||
"gitattributes": "_github_light",
|
||||
"go": "_go2_light",
|
||||
"slide": "_go_light",
|
||||
"article": "_go_light",
|
||||
"gradle": "_gradle_light",
|
||||
"groovy": "_grails_light",
|
||||
"gsp": "_grails_light",
|
||||
"hh": "_hacklang_light",
|
||||
"haml": "_haml_light",
|
||||
|
@ -902,57 +888,37 @@
|
|||
"hjs": "_mustache_light",
|
||||
"hs": "_haskell_light",
|
||||
"lhs": "_haskell_light",
|
||||
"html": "_html_light",
|
||||
"jade": "_jade_light",
|
||||
"java": "_java_light",
|
||||
"class": "_java_light",
|
||||
"classpath": "_java_light",
|
||||
"js": "_javascript_light",
|
||||
"js.map": "_javascript_light",
|
||||
"es": "_javascript_light",
|
||||
"es5": "_javascript_light",
|
||||
"es6": "_javascript_light",
|
||||
"es7": "_javascript_light",
|
||||
"json": "_json_light",
|
||||
"jl": "_julia_light",
|
||||
"less": "_less_light",
|
||||
"liquid": "_liquid_light",
|
||||
"ls": "_livescript_light",
|
||||
"lua": "_lua_light",
|
||||
"markdown": "_markdown_light",
|
||||
"md": "_markdown_light",
|
||||
"mustache": "_mustache_light",
|
||||
"stache": "_mustache_light",
|
||||
"npm-debug.log": "_npm_light",
|
||||
"npmignore": "_npm_light",
|
||||
"h": "_c_light",
|
||||
"m": "_c_light",
|
||||
"ml": "_ocaml_light",
|
||||
"mli": "_ocaml_light",
|
||||
"cmx": "_ocaml_light",
|
||||
"cmxa": "_ocaml_light",
|
||||
"pl": "_perl_light",
|
||||
"php": "_php_light",
|
||||
"php.inc": "_php_light",
|
||||
"pug": "_pug_light",
|
||||
"pp": "_puppet_light",
|
||||
"py": "_python_light",
|
||||
"jsx": "_react_light",
|
||||
"cjsx": "_react_light",
|
||||
"tsx": "_react_light",
|
||||
"rb": "_ruby_light",
|
||||
"erb": "_ruby_light",
|
||||
"erb.html": "_ruby_light",
|
||||
"html.erb": "_ruby_light",
|
||||
"rs": "_rust_light",
|
||||
"sass": "_sass_light",
|
||||
"scss": "_sass_light",
|
||||
"slim": "_slim_light",
|
||||
"smarty.tpl": "_smarty_light",
|
||||
"sbt": "_sbt_light",
|
||||
"scala": "_scala_light",
|
||||
"styl": "_stylus_light",
|
||||
"swift": "_swift_light",
|
||||
"tf": "_terraform_light",
|
||||
"tf.json": "_terraform_light",
|
||||
"tex": "_tex_light",
|
||||
|
@ -962,12 +928,9 @@
|
|||
"ins": "_tex_light",
|
||||
"txt": "_default_light",
|
||||
"twig": "_twig_light",
|
||||
"ts": "_typescript_light",
|
||||
"vala": "_vala_light",
|
||||
"vapi": "_vala_light",
|
||||
"xml": "_xml_light",
|
||||
"yml": "_yml_light",
|
||||
"yaml": "_yml_light",
|
||||
"ai": "_illustrator_light",
|
||||
"psd": "_photoshop_light",
|
||||
"pdf": "_pdf_light",
|
||||
|
@ -981,11 +944,7 @@
|
|||
"jpeg": "_image_light",
|
||||
"svg": "_svg_light",
|
||||
"svgx": "_image_light",
|
||||
"cmd": "_shell_light",
|
||||
"sh": "_shell_light",
|
||||
"zsh": "_shell_light",
|
||||
"fish": "_shell_light",
|
||||
"zshrc": "_shell_light",
|
||||
"mov": "_video_light",
|
||||
"ogv": "_video_light",
|
||||
"webm": "_video_light",
|
||||
|
@ -1006,6 +965,39 @@
|
|||
"tmp": "_clock_light",
|
||||
"DS_Store": "_ignored_light"
|
||||
},
|
||||
"languageIds": {
|
||||
"csharp": "_c-sharp_light",
|
||||
"bat": "_shell_light",
|
||||
"coffeescript": "_coffee_light",
|
||||
"c": "_c_light",
|
||||
"cpp": "_cpp_light",
|
||||
"css": "_css_light",
|
||||
"go": "_go2_light",
|
||||
"groovy": "_grails_light",
|
||||
"html": "_html_light",
|
||||
"ini": "_github_light",
|
||||
"jade": "_jade_light",
|
||||
"java": "_java_light",
|
||||
"javascriptreact": "_react_light",
|
||||
"javascript": "_javascript_light",
|
||||
"json": "_json_light",
|
||||
"less": "_less_light",
|
||||
"lua": "_lua_light",
|
||||
"markdown": "_markdown_light",
|
||||
"objective-c": "_c_light",
|
||||
"perl": "_perl_light",
|
||||
"php": "_php_light",
|
||||
"python": "_python_light",
|
||||
"ruby": "_ruby_light",
|
||||
"rust": "_rust_light",
|
||||
"scss": "_sass_light",
|
||||
"shellscript": "_shell_light",
|
||||
"swift": "_swift_light",
|
||||
"typescript": "_typescript_light",
|
||||
"typescriptreact": "_react_light",
|
||||
"xml": "_config_light",
|
||||
"yaml": "_yml_light"
|
||||
},
|
||||
"fileNames": {
|
||||
"karma.conf.js": "_karma_light",
|
||||
"karma.conf.coffee": "_karma_light",
|
||||
|
|
|
@ -232,6 +232,20 @@ suite('window namespace tests', () => {
|
|||
return result;
|
||||
});
|
||||
|
||||
test('showQuickPick, native promise - #11754', function () {
|
||||
|
||||
const data = new Promise<string[]>(resolve => {
|
||||
resolve(['a', 'b', 'c']);
|
||||
});
|
||||
|
||||
const source = new CancellationTokenSource();
|
||||
const result = window.showQuickPick(data, undefined, source.token);
|
||||
source.cancel();
|
||||
return result.then(value => {
|
||||
assert.equal(value, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
test('editor, selection change kind', () => {
|
||||
return workspace.openTextDocument(join(workspace.rootPath, './far.js')).then(doc => window.showTextDocument(doc)).then(editor => {
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "code-oss-dev",
|
||||
"version": "1.6.0",
|
||||
"electronVersion": "0.37.6",
|
||||
"distro": "221e07c30a60acb4752cc6ba35e5ac4481d8b9d5",
|
||||
"distro": "3d44b35db8d394d6d7b2bc224675735a0a8f2704",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
|
@ -107,6 +107,7 @@
|
|||
}
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"windows-mutex": "^0.2.0"
|
||||
"windows-mutex": "^0.2.0",
|
||||
"fsevents": "0.3.8"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ try {
|
|||
}
|
||||
|
||||
// Set userData path before app 'ready' event
|
||||
var userData = args['user-data-dir'] || paths.getDefaultUserDataPath(process.platform);
|
||||
var userData = path.resolve(args['user-data-dir'] || paths.getDefaultUserDataPath(process.platform));
|
||||
app.setPath('userData', userData);
|
||||
|
||||
// Mac: when someone drops a file to the not-yet running VSCode, the open-file event fires even before
|
||||
|
|
21
src/typings/thenable.d.ts
vendored
Normal file
21
src/typings/thenable.d.ts
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Thenable is a common denominator between ES6 promises, Q, jquery.Deferred, WinJS.Promise,
|
||||
* and others. This API makes no assumption about what promise libary is being used which
|
||||
* enables reusing existing code without migrating to a specific promise implementation. Still,
|
||||
* we recommend the use of native promises which are available in VS Code.
|
||||
*/
|
||||
interface Thenable<R> {
|
||||
/**
|
||||
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
||||
* @param onfulfilled The callback to execute when the Promise is resolved.
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of which ever callback is executed.
|
||||
*/
|
||||
then<TResult>(onfulfilled?: (value: R) => TResult | Thenable<TResult>, onrejected?: (reason: any) => TResult | Thenable<TResult>): Thenable<TResult>;
|
||||
then<TResult>(onfulfilled?: (value: R) => TResult | Thenable<TResult>, onrejected?: (reason: any) => void): Thenable<TResult>;
|
||||
}
|
|
@ -13,6 +13,7 @@ import {isObject} from 'vs/base/common/types';
|
|||
import {isChrome, isWebKit} from 'vs/base/browser/browser';
|
||||
import {IKeyboardEvent, StandardKeyboardEvent} from 'vs/base/browser/keyboardEvent';
|
||||
import {IMouseEvent, StandardMouseEvent} from 'vs/base/browser/mouseEvent';
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
|
||||
export function clearNode(node: HTMLElement) {
|
||||
while (node.firstChild) {
|
||||
|
@ -55,7 +56,6 @@ export function isInDOM(node: Node): boolean {
|
|||
return false;
|
||||
}
|
||||
|
||||
const _blank = ' '.charCodeAt(0);
|
||||
let lastStart: number, lastEnd: number;
|
||||
|
||||
function _findClassName(node: HTMLElement, className: string): void {
|
||||
|
@ -95,14 +95,14 @@ function _findClassName(node: HTMLElement, className: string): void {
|
|||
idxEnd = idx + classLen;
|
||||
|
||||
// a class that is followed by another class
|
||||
if ((idx === 0 || classes.charCodeAt(idx - 1) === _blank) && classes.charCodeAt(idxEnd) === _blank) {
|
||||
if ((idx === 0 || classes.charCodeAt(idx - 1) === CharCode.Space) && classes.charCodeAt(idxEnd) === CharCode.Space) {
|
||||
lastStart = idx;
|
||||
lastEnd = idxEnd + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// last class
|
||||
if (idx > 0 && classes.charCodeAt(idx - 1) === _blank && idxEnd === classesLen) {
|
||||
if (idx > 0 && classes.charCodeAt(idx - 1) === CharCode.Space && idxEnd === classesLen) {
|
||||
lastStart = idx - 1;
|
||||
lastEnd = idxEnd;
|
||||
return;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import _Event, { Emitter } from 'vs/base/common/event';
|
||||
import _Event, { Emitter, mapEvent } from 'vs/base/common/event';
|
||||
|
||||
export type EventHandler = HTMLElement | HTMLDocument | Window;
|
||||
|
||||
|
@ -127,3 +127,11 @@ export const domEvent: IDomEvent = (element: EventHandler, type: string, useCapt
|
|||
|
||||
return emitter.event;
|
||||
};
|
||||
|
||||
export function stop<T extends Event>(event: _Event<T>): _Event<T> {
|
||||
return mapEvent(event, e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return e;
|
||||
});
|
||||
}
|
|
@ -214,7 +214,7 @@ class StringStream {
|
|||
}
|
||||
}
|
||||
|
||||
enum FormatType {
|
||||
const enum FormatType {
|
||||
Invalid,
|
||||
Root,
|
||||
Text,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
import {KeyCode, KeyMod} from 'vs/base/common/keyCodes';
|
||||
import {KeyCode, KeyCodeUtils, KeyMod} from 'vs/base/common/keyCodes';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import * as browser from 'vs/base/browser/browser';
|
||||
|
||||
|
@ -161,7 +161,7 @@ let extractKeyCode = function extractKeyCode(e:KeyboardEvent): KeyCode {
|
|||
if (e.charCode) {
|
||||
// "keypress" events mostly
|
||||
let char = String.fromCharCode(e.charCode).toUpperCase();
|
||||
return KeyCode.fromString(char);
|
||||
return KeyCodeUtils.fromString(char);
|
||||
}
|
||||
return lookupKeyCode(e);
|
||||
};
|
||||
|
|
|
@ -18,7 +18,7 @@ import types = require('vs/base/common/types');
|
|||
import {IEventEmitter, EventEmitter} from 'vs/base/common/eventEmitter';
|
||||
import {Gesture, EventType} from 'vs/base/browser/touch';
|
||||
import {StandardKeyboardEvent} from 'vs/base/browser/keyboardEvent';
|
||||
import {CommonKeybindings} from 'vs/base/common/keyCodes';
|
||||
import {KeyCode, KeyMod} from 'vs/base/common/keyCodes';
|
||||
|
||||
export interface IActionItem extends IEventEmitter {
|
||||
actionRunner: IActionRunner;
|
||||
|
@ -388,13 +388,13 @@ export class ActionBar extends EventEmitter implements IActionRunner {
|
|||
let event = new StandardKeyboardEvent(e);
|
||||
let eventHandled = true;
|
||||
|
||||
if (event.equals(isVertical ? CommonKeybindings.UP_ARROW : CommonKeybindings.LEFT_ARROW)) {
|
||||
if (event.equals(isVertical ? KeyCode.UpArrow : KeyCode.LeftArrow)) {
|
||||
this.focusPrevious();
|
||||
} else if (event.equals(isVertical ? CommonKeybindings.DOWN_ARROW : CommonKeybindings.RIGHT_ARROW)) {
|
||||
} else if (event.equals(isVertical ? KeyCode.DownArrow : KeyCode.RightArrow)) {
|
||||
this.focusNext();
|
||||
} else if (event.equals(CommonKeybindings.ESCAPE)) {
|
||||
} else if (event.equals(KeyCode.Escape)) {
|
||||
this.cancel();
|
||||
} else if (event.equals(CommonKeybindings.ENTER) || event.equals(CommonKeybindings.SPACE)) {
|
||||
} else if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {
|
||||
// Nothing, just staying out of the else branch
|
||||
} else {
|
||||
eventHandled = false;
|
||||
|
@ -416,14 +416,14 @@ export class ActionBar extends EventEmitter implements IActionRunner {
|
|||
let event = new StandardKeyboardEvent(e);
|
||||
|
||||
// Run action on Enter/Space
|
||||
if (event.equals(CommonKeybindings.ENTER) || event.equals(CommonKeybindings.SPACE)) {
|
||||
if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {
|
||||
this.doTrigger(event);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
// Recompute focused item
|
||||
else if (event.equals(CommonKeybindings.TAB) || event.equals(CommonKeybindings.SHIFT_TAB)) {
|
||||
else if (event.equals(KeyCode.Tab) || event.equals(KeyMod.Shift | KeyCode.Tab)) {
|
||||
this.updateFocusedItem();
|
||||
}
|
||||
});
|
||||
|
@ -706,6 +706,10 @@ export class SelectActionItem extends BaseActionItem {
|
|||
}
|
||||
}
|
||||
|
||||
public set enabled(value: boolean) {
|
||||
this.select.disabled = !value;
|
||||
}
|
||||
|
||||
public blur(): void {
|
||||
if (this.select) {
|
||||
this.select.blur();
|
||||
|
|
|
@ -10,7 +10,7 @@ import {EventEmitter} from 'vs/base/common/eventEmitter';
|
|||
import DOM = require('vs/base/browser/dom');
|
||||
import {Builder, $} from 'vs/base/browser/builder';
|
||||
import {StandardKeyboardEvent} from 'vs/base/browser/keyboardEvent';
|
||||
import {CommonKeybindings} from 'vs/base/common/keyCodes';
|
||||
import {KeyCode} from 'vs/base/common/keyCodes';
|
||||
|
||||
export class Button extends EventEmitter {
|
||||
|
||||
|
@ -38,10 +38,10 @@ export class Button extends EventEmitter {
|
|||
this.$el.on(DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => {
|
||||
let event = new StandardKeyboardEvent(e);
|
||||
let eventHandled = false;
|
||||
if (this.enabled && event.equals(CommonKeybindings.ENTER) || event.equals(CommonKeybindings.SPACE)) {
|
||||
if (this.enabled && event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {
|
||||
this.emit(DOM.EventType.CLICK, e);
|
||||
eventHandled = true;
|
||||
} else if (event.equals(CommonKeybindings.ESCAPE)) {
|
||||
} else if (event.equals(KeyCode.Escape)) {
|
||||
this.$el.domBlur();
|
||||
eventHandled = true;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import {IContextViewProvider} from 'vs/base/browser/ui/contextview/contextview';
|
|||
import {Widget} from 'vs/base/browser/ui/widget';
|
||||
import Event, {Emitter} from 'vs/base/common/event';
|
||||
import {IKeyboardEvent} from 'vs/base/browser/keyboardEvent';
|
||||
import {CommonKeybindings} from 'vs/base/common/keyCodes';
|
||||
import {KeyCode} from 'vs/base/common/keyCodes';
|
||||
|
||||
export interface IFindInputOptions {
|
||||
placeholder?:string;
|
||||
|
@ -239,13 +239,13 @@ export class FindInput extends Widget {
|
|||
// Arrow-Key support to navigate between options
|
||||
let indexes = [this.caseSensitive.domNode, this.wholeWords.domNode, this.regex.domNode];
|
||||
this.onkeydown(this.domNode, (event: IKeyboardEvent) => {
|
||||
if (event.equals(CommonKeybindings.LEFT_ARROW) || event.equals(CommonKeybindings.RIGHT_ARROW) || event.equals(CommonKeybindings.ESCAPE)) {
|
||||
if (event.equals(KeyCode.LeftArrow) || event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Escape)) {
|
||||
let index = indexes.indexOf(<HTMLElement>document.activeElement);
|
||||
if (index >= 0) {
|
||||
let newIndex: number;
|
||||
if (event.equals(CommonKeybindings.RIGHT_ARROW)) {
|
||||
if (event.equals(KeyCode.RightArrow)) {
|
||||
newIndex = (index + 1) % indexes.length;
|
||||
} else if (event.equals(CommonKeybindings.LEFT_ARROW)) {
|
||||
} else if (event.equals(KeyCode.LeftArrow)) {
|
||||
if (index === 0) {
|
||||
newIndex = indexes.length - 1;
|
||||
} else {
|
||||
|
@ -253,7 +253,7 @@ export class FindInput extends Widget {
|
|||
}
|
||||
}
|
||||
|
||||
if (event.equals(CommonKeybindings.ESCAPE)) {
|
||||
if (event.equals(KeyCode.Escape)) {
|
||||
indexes[index].blur();
|
||||
} else if (newIndex >= 0) {
|
||||
indexes[newIndex].focus();
|
||||
|
|
|
@ -10,7 +10,7 @@ import * as DOM from 'vs/base/browser/dom';
|
|||
import { EventType as TouchEventType } from 'vs/base/browser/touch';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import Event, { Emitter, mapEvent, EventBufferer, filterEvent } from 'vs/base/common/event';
|
||||
import Event, { Emitter, EventBufferer, chain, mapEvent } from 'vs/base/common/event';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { IDelegate, IRenderer, IListMouseEvent, IFocusChangeEvent, ISelectionChangeEvent } from './list';
|
||||
import { ListView, IListViewOptions } from './listView';
|
||||
|
@ -134,13 +134,14 @@ class Controller<T> implements IDisposable {
|
|||
this.disposables.push(view.addListener('click', e => this.onPointer(e)));
|
||||
this.disposables.push(view.addListener(TouchEventType.Tap, e => this.onPointer(e)));
|
||||
|
||||
const onRawKeyDown = domEvent(view.domNode, 'keydown');
|
||||
const onKeyDown = mapEvent(onRawKeyDown, e => new StandardKeyboardEvent(e));
|
||||
filterEvent(onKeyDown, e => e.keyCode === KeyCode.Enter)(this.onEnter, this, this.disposables);
|
||||
filterEvent(onKeyDown, e => e.keyCode === KeyCode.UpArrow)(this.onUpArrow, this, this.disposables);
|
||||
filterEvent(onKeyDown, e => e.keyCode === KeyCode.DownArrow)(this.onDownArrow, this, this.disposables);
|
||||
filterEvent(onKeyDown, e => e.keyCode === KeyCode.PageUp)(this.onPageUpArrow, this, this.disposables);
|
||||
filterEvent(onKeyDown, e => e.keyCode === KeyCode.PageDown)(this.onPageDownArrow, this, this.disposables);
|
||||
const onKeyDown = chain(domEvent(view.domNode, 'keydown'))
|
||||
.map(e => new StandardKeyboardEvent(e));
|
||||
|
||||
onKeyDown.filter(e => e.keyCode === KeyCode.Enter).on(this.onEnter, this, this.disposables);
|
||||
onKeyDown.filter(e => e.keyCode === KeyCode.UpArrow).on(this.onUpArrow, this, this.disposables);
|
||||
onKeyDown.filter(e => e.keyCode === KeyCode.DownArrow).on(this.onDownArrow, this, this.disposables);
|
||||
onKeyDown.filter(e => e.keyCode === KeyCode.PageUp).on(this.onPageUpArrow, this, this.disposables);
|
||||
onKeyDown.filter(e => e.keyCode === KeyCode.PageDown).on(this.onPageDownArrow, this, this.disposables);
|
||||
}
|
||||
|
||||
private onMouseDown(e: IListMouseEvent<T>) {
|
||||
|
|
|
@ -14,7 +14,7 @@ import dom = require('vs/base/browser/dom');
|
|||
import numbers = require('vs/base/common/numbers');
|
||||
import sash = require('vs/base/browser/ui/sash/sash');
|
||||
import {StandardKeyboardEvent} from 'vs/base/browser/keyboardEvent';
|
||||
import {CommonKeybindings} from 'vs/base/common/keyCodes';
|
||||
import {KeyCode} from 'vs/base/common/keyCodes';
|
||||
import Event, {Emitter} from 'vs/base/common/event';
|
||||
|
||||
export enum Orientation {
|
||||
|
@ -113,7 +113,7 @@ export abstract class HeaderView extends View {
|
|||
|
||||
constructor(opts: IHeaderViewOptions) {
|
||||
super(opts);
|
||||
|
||||
|
||||
this.headerSize = types.isUndefined(opts.headerSize) ? 22 : opts.headerSize;
|
||||
}
|
||||
|
||||
|
@ -214,16 +214,16 @@ export abstract class AbstractCollapsibleView extends HeaderView {
|
|||
this.headerKeyListener = dom.addDisposableListener(this.header, dom.EventType.KEY_DOWN, (e) => {
|
||||
let event = new StandardKeyboardEvent(e);
|
||||
let eventHandled = false;
|
||||
if (event.equals(CommonKeybindings.ENTER) || event.equals(CommonKeybindings.SPACE) || (event.equals(CommonKeybindings.LEFT_ARROW) && this.state === CollapsibleState.EXPANDED) || (event.equals(CommonKeybindings.RIGHT_ARROW) && this.state === CollapsibleState.COLLAPSED)) {
|
||||
if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space) || (event.equals(KeyCode.LeftArrow) && this.state === CollapsibleState.EXPANDED) || (event.equals(KeyCode.RightArrow) && this.state === CollapsibleState.COLLAPSED)) {
|
||||
this.toggleExpansion();
|
||||
eventHandled = true;
|
||||
} else if (event.equals(CommonKeybindings.ESCAPE)) {
|
||||
} else if (event.equals(KeyCode.Escape)) {
|
||||
this.header.blur();
|
||||
eventHandled = true;
|
||||
} else if (event.equals(CommonKeybindings.UP_ARROW)) {
|
||||
} else if (event.equals(KeyCode.UpArrow)) {
|
||||
this.emit('focusPrevious');
|
||||
eventHandled = true;
|
||||
} else if (event.equals(CommonKeybindings.DOWN_ARROW)) {
|
||||
} else if (event.equals(KeyCode.DownArrow)) {
|
||||
this.emit('focusNext');
|
||||
eventHandled = true;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ export function asWinJsPromise<T>(callback: (token: CancellationToken) => T | TP
|
|||
let source = new CancellationTokenSource();
|
||||
return new TPromise<T>((resolve, reject, progress) => {
|
||||
let item = callback(source.token);
|
||||
if (TPromise.is(item)) {
|
||||
if (item instanceof TPromise) {
|
||||
item.then(resolve, reject, progress);
|
||||
} else if (isThenable<T>(item)) {
|
||||
item.then(resolve, reject);
|
||||
|
|
237
src/vs/base/common/charCode.ts
Normal file
237
src/vs/base/common/charCode.ts
Normal file
|
@ -0,0 +1,237 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
// Names from https://blog.codinghorror.com/ascii-pronunciation-rules-for-programmers/
|
||||
|
||||
/**
|
||||
* An inlined enum containing useful character codes (to be used with String.charCodeAt).
|
||||
* Please leave the const keyword such that it gets inlined when compiled to JavaScript!
|
||||
*/
|
||||
export const enum CharCode {
|
||||
Null = 0,
|
||||
/**
|
||||
* The `\t` character.
|
||||
*/
|
||||
Tab = 9,
|
||||
/**
|
||||
* The `\n` character.
|
||||
*/
|
||||
LineFeed = 10,
|
||||
/**
|
||||
* The `\r` character.
|
||||
*/
|
||||
CarriageReturn = 13,
|
||||
Space = 32,
|
||||
/**
|
||||
* The `!` character.
|
||||
*/
|
||||
ExclamationMark = 33,
|
||||
/**
|
||||
* The `"` character.
|
||||
*/
|
||||
DoubleQuote = 34,
|
||||
/**
|
||||
* The `#` character.
|
||||
*/
|
||||
Hash = 35,
|
||||
/**
|
||||
* The `$` character.
|
||||
*/
|
||||
DollarSign = 36,
|
||||
/**
|
||||
* The `%` character.
|
||||
*/
|
||||
PercentSign = 37,
|
||||
/**
|
||||
* The `&` character.
|
||||
*/
|
||||
Ampersand = 38,
|
||||
/**
|
||||
* The `'` character.
|
||||
*/
|
||||
SingleQuote = 39,
|
||||
/**
|
||||
* The `(` character.
|
||||
*/
|
||||
OpenParen = 40,
|
||||
/**
|
||||
* The `)` character.
|
||||
*/
|
||||
CloseParen = 41,
|
||||
/**
|
||||
* The `*` character.
|
||||
*/
|
||||
Asterisk = 42,
|
||||
/**
|
||||
* The `+` character.
|
||||
*/
|
||||
Plus = 43,
|
||||
/**
|
||||
* The `,` character.
|
||||
*/
|
||||
Comma = 44,
|
||||
/**
|
||||
* The `-` character.
|
||||
*/
|
||||
Dash = 45,
|
||||
/**
|
||||
* The `.` character.
|
||||
*/
|
||||
Period = 46,
|
||||
/**
|
||||
* The `/` character.
|
||||
*/
|
||||
Slash = 47,
|
||||
|
||||
Digit0 = 48,
|
||||
Digit1 = 49,
|
||||
Digit2 = 50,
|
||||
Digit3 = 51,
|
||||
Digit4 = 52,
|
||||
Digit5 = 53,
|
||||
Digit6 = 54,
|
||||
Digit7 = 55,
|
||||
Digit8 = 56,
|
||||
Digit9 = 57,
|
||||
|
||||
/**
|
||||
* The `:` character.
|
||||
*/
|
||||
Colon = 58,
|
||||
/**
|
||||
* The `;` character.
|
||||
*/
|
||||
Semicolon = 59,
|
||||
/**
|
||||
* The `<` character.
|
||||
*/
|
||||
LessThan = 60,
|
||||
/**
|
||||
* The `=` character.
|
||||
*/
|
||||
Equals = 61,
|
||||
/**
|
||||
* The `>` character.
|
||||
*/
|
||||
GreaterThan = 62,
|
||||
/**
|
||||
* The `?` character.
|
||||
*/
|
||||
QuestionMark = 63,
|
||||
/**
|
||||
* The `@` character.
|
||||
*/
|
||||
AtSign = 64,
|
||||
|
||||
A = 65,
|
||||
B = 66,
|
||||
C = 67,
|
||||
D = 68,
|
||||
E = 69,
|
||||
F = 70,
|
||||
G = 71,
|
||||
H = 72,
|
||||
I = 73,
|
||||
J = 74,
|
||||
K = 75,
|
||||
L = 76,
|
||||
M = 77,
|
||||
N = 78,
|
||||
O = 79,
|
||||
P = 80,
|
||||
Q = 81,
|
||||
R = 82,
|
||||
S = 83,
|
||||
T = 84,
|
||||
U = 85,
|
||||
V = 86,
|
||||
W = 87,
|
||||
X = 88,
|
||||
Y = 89,
|
||||
Z = 90,
|
||||
|
||||
/**
|
||||
* The `[` character.
|
||||
*/
|
||||
OpenSquareBracket = 91,
|
||||
/**
|
||||
* The `\` character.
|
||||
*/
|
||||
Backslash = 92,
|
||||
/**
|
||||
* The `]` character.
|
||||
*/
|
||||
CloseSquareBracket = 93,
|
||||
/**
|
||||
* The `^` character.
|
||||
*/
|
||||
Caret = 94,
|
||||
/**
|
||||
* The `_` character.
|
||||
*/
|
||||
Underline = 95,
|
||||
/**
|
||||
* The ``(`)`` character.
|
||||
*/
|
||||
BackTick = 96,
|
||||
|
||||
a = 97,
|
||||
b = 98,
|
||||
c = 99,
|
||||
d = 100,
|
||||
e = 101,
|
||||
f = 102,
|
||||
g = 103,
|
||||
h = 104,
|
||||
i = 105,
|
||||
j = 106,
|
||||
k = 107,
|
||||
l = 108,
|
||||
m = 109,
|
||||
n = 110,
|
||||
o = 111,
|
||||
p = 112,
|
||||
q = 113,
|
||||
r = 114,
|
||||
s = 115,
|
||||
t = 116,
|
||||
u = 117,
|
||||
v = 118,
|
||||
w = 119,
|
||||
x = 120,
|
||||
y = 121,
|
||||
z = 122,
|
||||
|
||||
/**
|
||||
* The `{` character.
|
||||
*/
|
||||
OpenCurlyBrace = 123,
|
||||
/**
|
||||
* The `|` character.
|
||||
*/
|
||||
Pipe = 124,
|
||||
/**
|
||||
* The `}` character.
|
||||
*/
|
||||
CloseCurlyBrace = 125,
|
||||
/**
|
||||
* The `~` character.
|
||||
*/
|
||||
Tilde = 126,
|
||||
|
||||
/**
|
||||
* Unicode Character 'LINE SEPARATOR' (U+2028)
|
||||
* http://www.fileformat.info/info/unicode/char/2028/index.htm
|
||||
*/
|
||||
LINE_SEPARATOR_2028 = 8232,
|
||||
|
||||
/**
|
||||
* UTF-8 BOM
|
||||
* Unicode Character 'ZERO WIDTH NO-BREAK SPACE' (U+FEFF)
|
||||
* http://www.fileformat.info/info/unicode/char/feff/index.htm
|
||||
*/
|
||||
UTF8_BOM = 65279
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import {IDisposable} from 'vs/base/common/lifecycle';
|
||||
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
|
||||
import CallbackList from 'vs/base/common/callbackList';
|
||||
import {EventEmitter} from 'vs/base/common/eventEmitter';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
|
@ -152,7 +152,25 @@ export function fromEventEmitter<T>(emitter: EventEmitter, eventType: string): E
|
|||
};
|
||||
}
|
||||
|
||||
export function fromPromise<T>(promise: TPromise<Event<T>>): Event<T> {
|
||||
export function fromPromise(promise: TPromise<any>): Event<void> {
|
||||
const emitter = new Emitter<void>();
|
||||
let shouldEmit = false;
|
||||
|
||||
promise
|
||||
.then(null, () => null)
|
||||
.then(() => {
|
||||
if (!shouldEmit) {
|
||||
setTimeout(() => emitter.fire(), 0);
|
||||
} else {
|
||||
emitter.fire();
|
||||
}
|
||||
});
|
||||
|
||||
shouldEmit = true;
|
||||
return emitter.event;
|
||||
}
|
||||
|
||||
export function delayed<T>(promise: TPromise<Event<T>>): Event<T> {
|
||||
let toCancel: TPromise<any> = null;
|
||||
let listener: IDisposable = null;
|
||||
|
||||
|
@ -190,12 +208,19 @@ export function once<T>(event: Event<T>): Event<T> {
|
|||
};
|
||||
}
|
||||
|
||||
export function mapEvent<I,O>(event: Event<I>, map: (i:I)=>O): Event<O> {
|
||||
return (listener, thisArgs = null, disposables?) => event(i => listener.call(thisArgs, map(i)), null, disposables);
|
||||
}
|
||||
export function any(...events: Event<any>[]): Event<void> {
|
||||
let listeners = [];
|
||||
|
||||
export function filterEvent<T>(event: Event<T>, filter: (e:T)=>boolean): Event<T> {
|
||||
return (listener, thisArgs = null, disposables?) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables);
|
||||
const emitter = new Emitter<void>({
|
||||
onFirstListenerAdd() {
|
||||
listeners = events.map(e => e(() => emitter.fire(), null));
|
||||
},
|
||||
onLastListenerRemove() {
|
||||
listeners = dispose(listeners);
|
||||
}
|
||||
});
|
||||
|
||||
return emitter.event;
|
||||
}
|
||||
|
||||
export function debounceEvent<I, O>(event: Event<I>, merger: (last: O, event: I) => O, delay: number = 100): Event<O> {
|
||||
|
@ -275,3 +300,46 @@ export class EventBufferer {
|
|||
buffer.forEach(flush => flush());
|
||||
}
|
||||
}
|
||||
|
||||
export interface IChainableEvent<T> {
|
||||
event: Event<T>;
|
||||
map<O>(fn: (i: T) => O): IChainableEvent<O>;
|
||||
filter(fn: (e: T) => boolean): IChainableEvent<T>;
|
||||
on(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable;
|
||||
}
|
||||
|
||||
export function mapEvent<I,O>(event: Event<I>, map: (i:I)=>O): Event<O> {
|
||||
return (listener, thisArgs = null, disposables?) => event(i => listener.call(thisArgs, map(i)), null, disposables);
|
||||
}
|
||||
|
||||
export function filterEvent<T>(event: Event<T>, filter: (e:T)=>boolean): Event<T> {
|
||||
return (listener, thisArgs = null, disposables?) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables);
|
||||
}
|
||||
|
||||
class ChainableEvent<T> implements IChainableEvent<T> {
|
||||
|
||||
get event(): Event<T> { return this._event; }
|
||||
|
||||
constructor(private _event: Event<T>) {}
|
||||
|
||||
map(fn) {
|
||||
return new ChainableEvent(mapEvent(this._event, fn));
|
||||
}
|
||||
|
||||
filter(fn) {
|
||||
return new ChainableEvent(filterEvent(this._event, fn));
|
||||
}
|
||||
|
||||
on(listener, thisArgs, disposables) {
|
||||
return this._event(listener, thisArgs, disposables);
|
||||
}
|
||||
}
|
||||
|
||||
export function chain<T>(event: Event<T>): IChainableEvent<T> {
|
||||
return new ChainableEvent(event);
|
||||
}
|
||||
|
||||
export function stopwatch<T>(event: Event<T>): Event<number> {
|
||||
const start = new Date().getTime();
|
||||
return mapEvent(once(event), _ => new Date().getTime() - start);
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import strings = require('vs/base/common/strings');
|
||||
import {BoundedLinkedMap} from 'vs/base/common/map';
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
|
||||
export interface IFilter {
|
||||
// Returns null if word doesn't match.
|
||||
|
@ -114,19 +115,24 @@ function _matchesSubString(word: string, wordToMatchAgainst: string, i: number,
|
|||
// CamelCase
|
||||
|
||||
function isLower(code: number): boolean {
|
||||
return 97 <= code && code <= 122;
|
||||
return CharCode.a <= code && code <= CharCode.z;
|
||||
}
|
||||
|
||||
function isUpper(code: number): boolean {
|
||||
return 65 <= code && code <= 90;
|
||||
return CharCode.A <= code && code <= CharCode.Z;
|
||||
}
|
||||
|
||||
function isNumber(code: number): boolean {
|
||||
return 48 <= code && code <= 57;
|
||||
return CharCode.Digit0 <= code && code <= CharCode.Digit9;
|
||||
}
|
||||
|
||||
function isWhitespace(code: number): boolean {
|
||||
return [32, 9, 10, 13].indexOf(code) > -1;
|
||||
return (
|
||||
code === CharCode.Space
|
||||
|| code === CharCode.Tab
|
||||
|| code === CharCode.LineFeed
|
||||
|| code === CharCode.CarriageReturn
|
||||
);
|
||||
}
|
||||
|
||||
function isAlphanumeric(code: number): boolean {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import strings = require('vs/base/common/strings');
|
||||
import paths = require('vs/base/common/paths');
|
||||
import {BoundedLinkedMap} from 'vs/base/common/map';
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
|
||||
export interface IExpression {
|
||||
[pattern: string]: boolean | SiblingClause | any;
|
||||
|
@ -467,9 +468,6 @@ function parseExpressionPattern(pattern: string, value: any): (ParsedStringPatte
|
|||
return parsedPattern;
|
||||
}
|
||||
|
||||
const SLASH = '/'.charCodeAt(0);
|
||||
const BACKSLASH = '\\'.charCodeAt(0);
|
||||
|
||||
function aggregateBasenameMatches(parsedPatterns: (ParsedStringPattern | ParsedExpressionPattern)[], result?: string): (ParsedStringPattern | ParsedExpressionPattern)[] {
|
||||
const basenamePatterns = parsedPatterns.filter(parsedPattern => !!(<ParsedStringPattern>parsedPattern).basenames);
|
||||
if (basenamePatterns.length < 2) {
|
||||
|
@ -494,7 +492,7 @@ function aggregateBasenameMatches(parsedPatterns: (ParsedStringPattern | ParsedE
|
|||
let i: number;
|
||||
for (i = path.length; i > 0; i--) {
|
||||
const ch = path.charCodeAt(i - 1);
|
||||
if (ch === SLASH || ch === BACKSLASH) {
|
||||
if (ch === CharCode.Slash || ch === CharCode.Backslash) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
70
src/vs/base/common/history.ts
Normal file
70
src/vs/base/common/history.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ArraySet } from 'vs/base/common/set';
|
||||
import { INavigator, ArrayNavigator } from 'vs/base/common/iterator';
|
||||
|
||||
export class HistoryNavigator<T> implements INavigator<T> {
|
||||
|
||||
private _history: ArraySet<T>;
|
||||
private _limit: number;
|
||||
private _navigator: ArrayNavigator<T>;
|
||||
|
||||
constructor(history: T[] = [], limit: number = 10) {
|
||||
this._history = new ArraySet(history);
|
||||
this._limit = limit;
|
||||
this._onChange();
|
||||
}
|
||||
|
||||
public add(t: T) {
|
||||
this._history.set(t);
|
||||
this._onChange();
|
||||
}
|
||||
|
||||
public next(): T {
|
||||
if (this._navigator.next()) {
|
||||
return this._navigator.current();
|
||||
}
|
||||
this.last();
|
||||
return null;
|
||||
}
|
||||
|
||||
public previous(): T {
|
||||
if (this._navigator.previous()) {
|
||||
return this._navigator.current();
|
||||
}
|
||||
this.first();
|
||||
return null;
|
||||
}
|
||||
|
||||
public current(): T {
|
||||
return this._navigator.current();
|
||||
}
|
||||
|
||||
public parent(): T {
|
||||
return null;
|
||||
}
|
||||
|
||||
public first(): T {
|
||||
return this._navigator.first();
|
||||
}
|
||||
|
||||
public last(): T {
|
||||
return this._navigator.last();
|
||||
}
|
||||
|
||||
private _onChange() {
|
||||
this._reduceToLimit();
|
||||
this._navigator = new ArrayNavigator(this._history.elements);
|
||||
this._navigator.last();
|
||||
}
|
||||
|
||||
private _reduceToLimit() {
|
||||
let data = this._history.elements;
|
||||
if (data.length > this._limit) {
|
||||
this._history = new ArraySet<T>(data.slice(data.length - this._limit));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,9 +12,9 @@ export interface IIterator<T> {
|
|||
export class ArrayIterator<T> implements IIterator<T> {
|
||||
|
||||
private items: T[];
|
||||
private start: number;
|
||||
private end: number;
|
||||
private index: number;
|
||||
protected start: number;
|
||||
protected end: number;
|
||||
protected index: number;
|
||||
|
||||
constructor(items: T[], start: number = 0, end: number = items.length) {
|
||||
this.items = items;
|
||||
|
@ -25,8 +25,11 @@ export class ArrayIterator<T> implements IIterator<T> {
|
|||
|
||||
public next(): T {
|
||||
this.index = Math.min(this.index + 1, this.end);
|
||||
return this.current();
|
||||
}
|
||||
|
||||
if (this.index === this.end) {
|
||||
protected current(): T {
|
||||
if (this.index === this.start - 1 || this.index === this.end) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -34,6 +37,37 @@ export class ArrayIterator<T> implements IIterator<T> {
|
|||
}
|
||||
}
|
||||
|
||||
export class ArrayNavigator<T> extends ArrayIterator<T> implements INavigator<T> {
|
||||
|
||||
constructor(items: T[], start: number = 0, end: number = items.length) {
|
||||
super(items, start, end);
|
||||
}
|
||||
|
||||
public current(): T {
|
||||
return super.current();
|
||||
}
|
||||
|
||||
public previous(): T {
|
||||
this.index = Math.max(this.index - 1, this.start - 1);
|
||||
return this.current();
|
||||
}
|
||||
|
||||
public first(): T {
|
||||
this.index = this.start;
|
||||
return this.current();
|
||||
}
|
||||
|
||||
public last(): T {
|
||||
this.index = this.end - 1;
|
||||
return this.current();
|
||||
}
|
||||
|
||||
public parent(): T {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class MappedIterator<T, R> implements IIterator<R> {
|
||||
|
||||
constructor(protected iterator: IIterator<T>, protected fn: (item:T)=>R) {
|
||||
|
|
|
@ -443,7 +443,7 @@ function isDigit(ch: number): boolean {
|
|||
return ch >= CharacterCodes._0 && ch <= CharacterCodes._9;
|
||||
}
|
||||
|
||||
enum CharacterCodes {
|
||||
const enum CharacterCodes {
|
||||
nullCharacter = 0,
|
||||
maxAsciiCharacter = 0x7F,
|
||||
|
||||
|
|
|
@ -19,181 +19,182 @@ export interface ISimplifiedPlatform {
|
|||
* Inspired somewhat from https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
|
||||
* But these are "more general", as they should work across browsers & OS`s.
|
||||
*/
|
||||
export enum KeyCode {
|
||||
export const enum KeyCode {
|
||||
/**
|
||||
* Placed first to cover the 0 value of the enum.
|
||||
*/
|
||||
Unknown,
|
||||
Unknown = 0,
|
||||
|
||||
Backspace,
|
||||
Tab,
|
||||
Enter,
|
||||
Shift,
|
||||
Ctrl,
|
||||
Alt,
|
||||
PauseBreak,
|
||||
CapsLock,
|
||||
Escape,
|
||||
Space,
|
||||
PageUp,
|
||||
PageDown,
|
||||
End,
|
||||
Home,
|
||||
LeftArrow,
|
||||
UpArrow,
|
||||
RightArrow,
|
||||
DownArrow,
|
||||
Insert,
|
||||
Delete,
|
||||
Backspace = 1,
|
||||
Tab = 2,
|
||||
Enter = 3,
|
||||
Shift = 4,
|
||||
Ctrl = 5,
|
||||
Alt = 6,
|
||||
PauseBreak = 7,
|
||||
CapsLock = 8,
|
||||
Escape = 9,
|
||||
Space = 10,
|
||||
PageUp = 11,
|
||||
PageDown = 12,
|
||||
End = 13,
|
||||
Home = 14,
|
||||
LeftArrow = 15,
|
||||
UpArrow = 16,
|
||||
RightArrow = 17,
|
||||
DownArrow = 18,
|
||||
Insert = 19,
|
||||
Delete = 20,
|
||||
|
||||
KEY_0,
|
||||
KEY_1,
|
||||
KEY_2,
|
||||
KEY_3,
|
||||
KEY_4,
|
||||
KEY_5,
|
||||
KEY_6,
|
||||
KEY_7,
|
||||
KEY_8,
|
||||
KEY_9,
|
||||
KEY_0 = 21,
|
||||
KEY_1 = 22,
|
||||
KEY_2 = 23,
|
||||
KEY_3 = 24,
|
||||
KEY_4 = 25,
|
||||
KEY_5 = 26,
|
||||
KEY_6 = 27,
|
||||
KEY_7 = 28,
|
||||
KEY_8 = 29,
|
||||
KEY_9 = 30,
|
||||
|
||||
KEY_A,
|
||||
KEY_B,
|
||||
KEY_C,
|
||||
KEY_D,
|
||||
KEY_E,
|
||||
KEY_F,
|
||||
KEY_G,
|
||||
KEY_H,
|
||||
KEY_I,
|
||||
KEY_J,
|
||||
KEY_K,
|
||||
KEY_L,
|
||||
KEY_M,
|
||||
KEY_N,
|
||||
KEY_O,
|
||||
KEY_P,
|
||||
KEY_Q,
|
||||
KEY_R,
|
||||
KEY_S,
|
||||
KEY_T,
|
||||
KEY_U,
|
||||
KEY_V,
|
||||
KEY_W,
|
||||
KEY_X,
|
||||
KEY_Y,
|
||||
KEY_Z,
|
||||
KEY_A = 31,
|
||||
KEY_B = 32,
|
||||
KEY_C = 33,
|
||||
KEY_D = 34,
|
||||
KEY_E = 35,
|
||||
KEY_F = 36,
|
||||
KEY_G = 37,
|
||||
KEY_H = 38,
|
||||
KEY_I = 39,
|
||||
KEY_J = 40,
|
||||
KEY_K = 41,
|
||||
KEY_L = 42,
|
||||
KEY_M = 43,
|
||||
KEY_N = 44,
|
||||
KEY_O = 45,
|
||||
KEY_P = 46,
|
||||
KEY_Q = 47,
|
||||
KEY_R = 48,
|
||||
KEY_S = 49,
|
||||
KEY_T = 50,
|
||||
KEY_U = 51,
|
||||
KEY_V = 52,
|
||||
KEY_W = 53,
|
||||
KEY_X = 54,
|
||||
KEY_Y = 55,
|
||||
KEY_Z = 56,
|
||||
|
||||
Meta,
|
||||
ContextMenu,
|
||||
Meta = 57,
|
||||
ContextMenu = 58,
|
||||
|
||||
F1,
|
||||
F2,
|
||||
F3,
|
||||
F4,
|
||||
F5,
|
||||
F6,
|
||||
F7,
|
||||
F8,
|
||||
F9,
|
||||
F10,
|
||||
F11,
|
||||
F12,
|
||||
F13,
|
||||
F14,
|
||||
F15,
|
||||
F16,
|
||||
F17,
|
||||
F18,
|
||||
F19,
|
||||
F1 = 59,
|
||||
F2 = 60,
|
||||
F3 = 61,
|
||||
F4 = 62,
|
||||
F5 = 63,
|
||||
F6 = 64,
|
||||
F7 = 65,
|
||||
F8 = 66,
|
||||
F9 = 67,
|
||||
F10 = 68,
|
||||
F11 = 69,
|
||||
F12 = 70,
|
||||
F13 = 71,
|
||||
F14 = 72,
|
||||
F15 = 73,
|
||||
F16 = 74,
|
||||
F17 = 75,
|
||||
F18 = 76,
|
||||
F19 = 77,
|
||||
|
||||
NumLock,
|
||||
ScrollLock,
|
||||
NumLock = 78,
|
||||
ScrollLock = 79,
|
||||
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
* For the US standard keyboard, the ';:' key
|
||||
*/
|
||||
US_SEMICOLON,
|
||||
US_SEMICOLON = 80,
|
||||
/**
|
||||
* For any country/region, the '+' key
|
||||
* For the US standard keyboard, the '=+' key
|
||||
*/
|
||||
US_EQUAL,
|
||||
US_EQUAL = 81,
|
||||
/**
|
||||
* For any country/region, the ',' key
|
||||
* For the US standard keyboard, the ',<' key
|
||||
*/
|
||||
US_COMMA,
|
||||
US_COMMA = 82,
|
||||
/**
|
||||
* For any country/region, the '-' key
|
||||
* For the US standard keyboard, the '-_' key
|
||||
*/
|
||||
US_MINUS,
|
||||
US_MINUS = 83,
|
||||
/**
|
||||
* For any country/region, the '.' key
|
||||
* For the US standard keyboard, the '.>' key
|
||||
*/
|
||||
US_DOT,
|
||||
US_DOT = 84,
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
* For the US standard keyboard, the '/?' key
|
||||
*/
|
||||
US_SLASH,
|
||||
US_SLASH = 85,
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
* For the US standard keyboard, the '`~' key
|
||||
*/
|
||||
US_BACKTICK,
|
||||
US_BACKTICK = 86,
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
* For the US standard keyboard, the '[{' key
|
||||
*/
|
||||
US_OPEN_SQUARE_BRACKET,
|
||||
US_OPEN_SQUARE_BRACKET = 87,
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
* For the US standard keyboard, the '\|' key
|
||||
*/
|
||||
US_BACKSLASH,
|
||||
US_BACKSLASH = 88,
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
* For the US standard keyboard, the ']}' key
|
||||
*/
|
||||
US_CLOSE_SQUARE_BRACKET,
|
||||
US_CLOSE_SQUARE_BRACKET = 89,
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
* For the US standard keyboard, the ''"' key
|
||||
*/
|
||||
US_QUOTE,
|
||||
US_QUOTE = 90,
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
*/
|
||||
OEM_8,
|
||||
OEM_8 = 91,
|
||||
/**
|
||||
* Either the angle bracket key or the backslash key on the RT 102-key keyboard.
|
||||
*/
|
||||
OEM_102,
|
||||
OEM_102 = 92,
|
||||
|
||||
NUMPAD_0, // VK_NUMPAD0, 0x60, Numeric keypad 0 key
|
||||
NUMPAD_1, // VK_NUMPAD1, 0x61, Numeric keypad 1 key
|
||||
NUMPAD_2, // VK_NUMPAD2, 0x62, Numeric keypad 2 key
|
||||
NUMPAD_3, // VK_NUMPAD3, 0x63, Numeric keypad 3 key
|
||||
NUMPAD_4, // VK_NUMPAD4, 0x64, Numeric keypad 4 key
|
||||
NUMPAD_5, // VK_NUMPAD5, 0x65, Numeric keypad 5 key
|
||||
NUMPAD_6, // VK_NUMPAD6, 0x66, Numeric keypad 6 key
|
||||
NUMPAD_7, // VK_NUMPAD7, 0x67, Numeric keypad 7 key
|
||||
NUMPAD_8, // VK_NUMPAD8, 0x68, Numeric keypad 8 key
|
||||
NUMPAD_9, // VK_NUMPAD9, 0x69, Numeric keypad 9 key
|
||||
NUMPAD_0 = 93, // VK_NUMPAD0, 0x60, Numeric keypad 0 key
|
||||
NUMPAD_1 = 94, // VK_NUMPAD1, 0x61, Numeric keypad 1 key
|
||||
NUMPAD_2 = 95, // VK_NUMPAD2, 0x62, Numeric keypad 2 key
|
||||
NUMPAD_3 = 96, // VK_NUMPAD3, 0x63, Numeric keypad 3 key
|
||||
NUMPAD_4 = 97, // VK_NUMPAD4, 0x64, Numeric keypad 4 key
|
||||
NUMPAD_5 = 98, // VK_NUMPAD5, 0x65, Numeric keypad 5 key
|
||||
NUMPAD_6 = 99, // VK_NUMPAD6, 0x66, Numeric keypad 6 key
|
||||
NUMPAD_7 = 100, // VK_NUMPAD7, 0x67, Numeric keypad 7 key
|
||||
NUMPAD_8 = 101, // VK_NUMPAD8, 0x68, Numeric keypad 8 key
|
||||
NUMPAD_9 = 102, // VK_NUMPAD9, 0x69, Numeric keypad 9 key
|
||||
|
||||
NUMPAD_MULTIPLY, // VK_MULTIPLY, 0x6A, Multiply key
|
||||
NUMPAD_ADD, // VK_ADD, 0x6B, Add key
|
||||
NUMPAD_SEPARATOR, // VK_SEPARATOR, 0x6C, Separator key
|
||||
NUMPAD_SUBTRACT, // VK_SUBTRACT, 0x6D, Subtract key
|
||||
NUMPAD_DECIMAL, // VK_DECIMAL, 0x6E, Decimal key
|
||||
NUMPAD_DIVIDE, // VK_DIVIDE, 0x6F,
|
||||
NUMPAD_MULTIPLY = 103, // VK_MULTIPLY, 0x6A, Multiply key
|
||||
NUMPAD_ADD = 104, // VK_ADD, 0x6B, Add key
|
||||
NUMPAD_SEPARATOR = 105, // VK_SEPARATOR, 0x6C, Separator key
|
||||
NUMPAD_SUBTRACT = 106, // VK_SUBTRACT, 0x6D, Subtract key
|
||||
NUMPAD_DECIMAL = 107, // VK_DECIMAL, 0x6E, Decimal key
|
||||
NUMPAD_DIVIDE = 108, // VK_DIVIDE, 0x6F,
|
||||
|
||||
/**
|
||||
* Placed last to cover the length of the enum.
|
||||
* Please do not depend on this value!
|
||||
*/
|
||||
MAX_VALUE
|
||||
}
|
||||
|
@ -403,7 +404,7 @@ let USER_SETTINGS = createMapping((TO_USER_SETTINGS_MAP) => {
|
|||
FROM_USER_SETTINGS_MAP['OEM_102'] = KeyCode.OEM_102;
|
||||
});
|
||||
|
||||
export namespace KeyCode {
|
||||
export namespace KeyCodeUtils {
|
||||
export function toString(key:KeyCode): string {
|
||||
return STRING.fromKeyCode(key);
|
||||
}
|
||||
|
@ -418,12 +419,24 @@ export namespace KeyCode {
|
|||
// 13: 1 bit for alt
|
||||
// 12: 1 bit for winCtrl
|
||||
// 0: 12 bits for keyCode (up to a maximum keyCode of 4096. Given we have 83 at this point thats good enough)
|
||||
const enum BinaryKeybindingsMask {
|
||||
CtrlCmd = 1 << 15,
|
||||
Shift = 1 << 14,
|
||||
Alt = 1 << 13,
|
||||
WinCtrl = 1 << 12,
|
||||
KeyCode = 0x00000fff
|
||||
}
|
||||
|
||||
const BIN_CTRLCMD_MASK = 1 << 15;
|
||||
const BIN_SHIFT_MASK = 1 << 14;
|
||||
const BIN_ALT_MASK = 1 << 13;
|
||||
const BIN_WINCTRL_MASK = 1 << 12;
|
||||
const BIN_KEYCODE_MASK = 0x00000fff;
|
||||
export const enum KeyMod {
|
||||
CtrlCmd = 1 << 15,
|
||||
Shift = 1 << 14,
|
||||
Alt = 1 << 13,
|
||||
WinCtrl = 1 << 12,
|
||||
}
|
||||
|
||||
export function KeyChord(firstPart:number, secondPart:number): number {
|
||||
return firstPart | ((secondPart & 0x0000ffff) << 16);
|
||||
}
|
||||
|
||||
export class BinaryKeybindings {
|
||||
|
||||
|
@ -440,85 +453,26 @@ export class BinaryKeybindings {
|
|||
}
|
||||
|
||||
public static hasCtrlCmd(keybinding:number): boolean {
|
||||
return (keybinding & BIN_CTRLCMD_MASK ? true : false);
|
||||
return (keybinding & BinaryKeybindingsMask.CtrlCmd ? true : false);
|
||||
}
|
||||
|
||||
public static hasShift(keybinding:number): boolean {
|
||||
return (keybinding & BIN_SHIFT_MASK ? true : false);
|
||||
return (keybinding & BinaryKeybindingsMask.Shift ? true : false);
|
||||
}
|
||||
|
||||
public static hasAlt(keybinding:number): boolean {
|
||||
return (keybinding & BIN_ALT_MASK ? true : false);
|
||||
return (keybinding & BinaryKeybindingsMask.Alt ? true : false);
|
||||
}
|
||||
|
||||
public static hasWinCtrl(keybinding:number): boolean {
|
||||
return (keybinding & BIN_WINCTRL_MASK ? true : false);
|
||||
return (keybinding & BinaryKeybindingsMask.WinCtrl ? true : false);
|
||||
}
|
||||
|
||||
public static extractKeyCode(keybinding:number): KeyCode {
|
||||
return (keybinding & BIN_KEYCODE_MASK);
|
||||
return (keybinding & BinaryKeybindingsMask.KeyCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export class KeyMod {
|
||||
public static CtrlCmd = BIN_CTRLCMD_MASK;
|
||||
public static Shift = BIN_SHIFT_MASK;
|
||||
public static Alt = BIN_ALT_MASK;
|
||||
public static WinCtrl = BIN_WINCTRL_MASK;
|
||||
|
||||
public static chord(firstPart:number, secondPart:number): number {
|
||||
return firstPart | ((secondPart & 0x0000ffff) << 16);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A set of usual keybindings that can be reused in code
|
||||
*/
|
||||
export class CommonKeybindings {
|
||||
|
||||
public static ENTER: number = KeyCode.Enter;
|
||||
public static SHIFT_ENTER: number = KeyMod.Shift | KeyCode.Enter;
|
||||
public static CTRLCMD_ENTER: number = KeyMod.CtrlCmd | KeyCode.Enter;
|
||||
public static WINCTRL_ENTER: number = KeyMod.WinCtrl | KeyCode.Enter;
|
||||
|
||||
public static TAB: number = KeyCode.Tab;
|
||||
public static SHIFT_TAB: number = KeyMod.Shift | KeyCode.Tab;
|
||||
public static ESCAPE: number = KeyCode.Escape;
|
||||
public static SPACE: number = KeyCode.Space;
|
||||
public static DELETE: number = KeyCode.Delete;
|
||||
public static SHIFT_DELETE: number = KeyMod.Shift | KeyCode.Delete;
|
||||
public static CTRLCMD_BACKSPACE: number = KeyMod.CtrlCmd | KeyCode.Backspace;
|
||||
|
||||
public static UP_ARROW: number = KeyCode.UpArrow;
|
||||
public static SHIFT_UP_ARROW: number = KeyMod.Shift | KeyCode.UpArrow;
|
||||
public static CTRLCMD_UP_ARROW: number = KeyMod.CtrlCmd | KeyCode.UpArrow;
|
||||
|
||||
public static DOWN_ARROW: number = KeyCode.DownArrow;
|
||||
public static SHIFT_DOWN_ARROW: number = KeyMod.Shift | KeyCode.DownArrow;
|
||||
public static CTRLCMD_DOWN_ARROW: number = KeyMod.CtrlCmd | KeyCode.DownArrow;
|
||||
|
||||
public static LEFT_ARROW: number = KeyCode.LeftArrow;
|
||||
|
||||
public static RIGHT_ARROW: number = KeyCode.RightArrow;
|
||||
|
||||
public static HOME: number = KeyCode.Home;
|
||||
public static END: number = KeyCode.End;
|
||||
|
||||
public static PAGE_UP: number = KeyCode.PageUp;
|
||||
public static SHIFT_PAGE_UP: number = KeyMod.Shift | KeyCode.PageUp;
|
||||
|
||||
public static PAGE_DOWN: number = KeyCode.PageDown;
|
||||
public static SHIFT_PAGE_DOWN: number = KeyMod.Shift | KeyCode.PageDown;
|
||||
|
||||
public static F2: number = KeyCode.F2;
|
||||
|
||||
public static CTRLCMD_S: number = KeyMod.CtrlCmd | KeyCode.KEY_S;
|
||||
public static CTRLCMD_C: number = KeyMod.CtrlCmd | KeyCode.KEY_C;
|
||||
public static CTRLCMD_V: number = KeyMod.CtrlCmd | KeyCode.KEY_V;
|
||||
}
|
||||
|
||||
export class Keybinding {
|
||||
|
||||
/**
|
||||
|
@ -681,7 +635,7 @@ export class Keybinding {
|
|||
result |= KeyMod.WinCtrl;
|
||||
}
|
||||
result |= keyCode;
|
||||
return KeyMod.chord(result, chord);
|
||||
return KeyChord(result, chord);
|
||||
}
|
||||
|
||||
public value:number;
|
||||
|
@ -797,7 +751,7 @@ export class ElectronAcceleratorLabelProvider implements IKeyBindingLabelProvide
|
|||
return 'Right';
|
||||
}
|
||||
|
||||
return KeyCode.toString(keyCode);
|
||||
return KeyCodeUtils.toString(keyCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -831,7 +785,7 @@ export class MacUIKeyLabelProvider implements IKeyBindingLabelProvider {
|
|||
return MacUIKeyLabelProvider.downArrowUnicodeLabel;
|
||||
}
|
||||
|
||||
return KeyCode.toString(keyCode);
|
||||
return KeyCodeUtils.toString(keyCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -849,7 +803,7 @@ export class AriaKeyLabelProvider implements IKeyBindingLabelProvider {
|
|||
public modifierSeparator = '+';
|
||||
|
||||
public getLabelForKey(keyCode:KeyCode): string {
|
||||
return KeyCode.toString(keyCode);
|
||||
return KeyCodeUtils.toString(keyCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -867,7 +821,7 @@ export class ClassicUIKeyLabelProvider implements IKeyBindingLabelProvider {
|
|||
public modifierSeparator = '+';
|
||||
|
||||
public getLabelForKey(keyCode:KeyCode): string {
|
||||
return KeyCode.toString(keyCode);
|
||||
return KeyCodeUtils.toString(keyCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ export class PagedModel<T> implements IPagedModel<T> {
|
|||
|
||||
page.promiseIndexes.unset(index);
|
||||
|
||||
if (page.promiseIndexes.elements.length === 0) {
|
||||
if (page.promiseIndexes.size === 0) {
|
||||
page.promise.cancel();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
'use strict';
|
||||
|
||||
import {isLinux, isWindows} from 'vs/base/common/platform';
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
|
||||
/**
|
||||
* The forward slash path separator.
|
||||
|
@ -113,7 +114,7 @@ export function normalize(path: string, toOSPath?: boolean): string {
|
|||
for (let end = root.length; end <= len; end++) {
|
||||
|
||||
// either at the end or at a path-separator character
|
||||
if (end === len || path.charCodeAt(end) === _slash || path.charCodeAt(end) === _backslash) {
|
||||
if (end === len || path.charCodeAt(end) === CharCode.Slash || path.charCodeAt(end) === CharCode.Backslash) {
|
||||
|
||||
if (streql(path, start, end, '..')) {
|
||||
// skip current and remove parent (if there is already something)
|
||||
|
@ -160,28 +161,28 @@ export function getRoot(path: string, sep: string = '/'): string {
|
|||
|
||||
let len = path.length;
|
||||
let code = path.charCodeAt(0);
|
||||
if (code === _slash || code === _backslash) {
|
||||
if (code === CharCode.Slash || code === CharCode.Backslash) {
|
||||
|
||||
code = path.charCodeAt(1);
|
||||
if (code === _slash || code === _backslash) {
|
||||
if (code === CharCode.Slash || code === CharCode.Backslash) {
|
||||
// UNC candidate \\localhost\shares\ddd
|
||||
// ^^^^^^^^^^^^^^^^^^^
|
||||
code = path.charCodeAt(2);
|
||||
if (code !== _slash && code !== _backslash) {
|
||||
if (code !== CharCode.Slash && code !== CharCode.Backslash) {
|
||||
let pos = 3;
|
||||
let start = pos;
|
||||
for (; pos < len; pos++) {
|
||||
code = path.charCodeAt(pos);
|
||||
if (code === _slash || code === _backslash) {
|
||||
if (code === CharCode.Slash || code === CharCode.Backslash) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
code = path.charCodeAt(pos + 1);
|
||||
if (start !== pos && code !== _slash && code !== _backslash) {
|
||||
if (start !== pos && code !== CharCode.Slash && code !== CharCode.Backslash) {
|
||||
pos += 1;
|
||||
for (; pos < len; pos++) {
|
||||
code = path.charCodeAt(pos);
|
||||
if (code === _slash || code === _backslash) {
|
||||
if (code === CharCode.Slash || code === CharCode.Backslash) {
|
||||
return path.slice(0, pos + 1) // consume this separator
|
||||
.replace(/[\\/]/g, sep);
|
||||
}
|
||||
|
@ -194,12 +195,12 @@ export function getRoot(path: string, sep: string = '/'): string {
|
|||
// ^
|
||||
return sep;
|
||||
|
||||
} else if ((code >= _A && code <= _Z) || (code >= _a && code <= _z)) {
|
||||
} else if ((code >= CharCode.A && code <= CharCode.Z) || (code >= CharCode.a && code <= CharCode.z)) {
|
||||
// check for windows drive letter c:\ or c:
|
||||
|
||||
if (path.charCodeAt(1) === _colon) {
|
||||
if (path.charCodeAt(1) === CharCode.Colon) {
|
||||
code = path.charCodeAt(2);
|
||||
if (code === _slash || code === _backslash) {
|
||||
if (code === CharCode.Slash || code === CharCode.Backslash) {
|
||||
// C:\fff
|
||||
// ^^^
|
||||
return path.slice(0, 2) + sep;
|
||||
|
@ -219,7 +220,7 @@ export function getRoot(path: string, sep: string = '/'): string {
|
|||
pos += 3; // 3 -> "://".length
|
||||
for (; pos < len; pos++) {
|
||||
code = path.charCodeAt(pos);
|
||||
if (code === _slash || code === _backslash) {
|
||||
if (code === CharCode.Slash || code === CharCode.Backslash) {
|
||||
return path.slice(0, pos + 1); // consume this separator
|
||||
}
|
||||
}
|
||||
|
@ -240,9 +241,9 @@ export const join: (...parts: string[]) => string = function () {
|
|||
// add the separater between two parts unless
|
||||
// there already is one
|
||||
let last = value.charCodeAt(value.length - 1);
|
||||
if (last !== _slash && last !== _backslash) {
|
||||
if (last !== CharCode.Slash && last !== CharCode.Backslash) {
|
||||
let next = part.charCodeAt(0);
|
||||
if (next !== _slash && next !== _backslash) {
|
||||
if (next !== CharCode.Slash && next !== CharCode.Backslash) {
|
||||
|
||||
value += sep;
|
||||
}
|
||||
|
@ -274,18 +275,18 @@ export function isUNC(path: string): boolean {
|
|||
}
|
||||
|
||||
let code = path.charCodeAt(0);
|
||||
if (code !== _backslash) {
|
||||
if (code !== CharCode.Backslash) {
|
||||
return false;
|
||||
}
|
||||
code = path.charCodeAt(1);
|
||||
if (code !== _backslash) {
|
||||
if (code !== CharCode.Backslash) {
|
||||
return false;
|
||||
}
|
||||
let pos = 2;
|
||||
let start = pos;
|
||||
for (; pos < path.length; pos++) {
|
||||
code = path.charCodeAt(pos);
|
||||
if (code === _backslash) {
|
||||
if (code === CharCode.Backslash) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -293,7 +294,7 @@ export function isUNC(path: string): boolean {
|
|||
return false;
|
||||
}
|
||||
code = path.charCodeAt(pos + 1);
|
||||
if (isNaN(code) || code === _backslash) {
|
||||
if (isNaN(code) || code === CharCode.Backslash) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -307,15 +308,6 @@ export function makePosixAbsolute(path: string): string {
|
|||
return isPosixAbsolute(normalize(path)) ? path : sep + path;
|
||||
}
|
||||
|
||||
|
||||
const _slash = '/'.charCodeAt(0);
|
||||
const _backslash = '\\'.charCodeAt(0);
|
||||
const _colon = ':'.charCodeAt(0);
|
||||
const _a = 'a'.charCodeAt(0);
|
||||
const _A = 'A'.charCodeAt(0);
|
||||
const _z = 'z'.charCodeAt(0);
|
||||
const _Z = 'Z'.charCodeAt(0);
|
||||
|
||||
export function isEqualOrParent(path: string, candidate: string): boolean {
|
||||
|
||||
if (path === candidate) {
|
||||
|
@ -327,7 +319,7 @@ export function isEqualOrParent(path: string, candidate: string): boolean {
|
|||
|
||||
let candidateLen = candidate.length;
|
||||
let lastCandidateChar = candidate.charCodeAt(candidateLen - 1);
|
||||
if (lastCandidateChar === _slash) {
|
||||
if (lastCandidateChar === CharCode.Slash) {
|
||||
candidate = candidate.substring(0, candidateLen - 1);
|
||||
candidateLen -= 1;
|
||||
}
|
||||
|
@ -351,7 +343,7 @@ export function isEqualOrParent(path: string, candidate: string): boolean {
|
|||
}
|
||||
|
||||
let char = path.charCodeAt(candidateLen);
|
||||
return char === _slash;
|
||||
return char === CharCode.Slash;
|
||||
}
|
||||
|
||||
// Reference: https://en.wikipedia.org/wiki/Filename
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
export class ArraySet<T> {
|
||||
|
||||
private _elements: T[];
|
||||
|
@ -13,6 +11,10 @@ export class ArraySet<T> {
|
|||
this._elements = elements.slice();
|
||||
}
|
||||
|
||||
get size(): number {
|
||||
return this._elements.length;
|
||||
}
|
||||
|
||||
set(element: T): void {
|
||||
this.unset(element);
|
||||
this._elements.push(element);
|
||||
|
@ -31,6 +33,6 @@ export class ArraySet<T> {
|
|||
}
|
||||
|
||||
get elements(): T[] {
|
||||
return this._elements;
|
||||
return this._elements.slice();
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
'use strict';
|
||||
|
||||
import {BoundedLinkedMap} from 'vs/base/common/map';
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
|
||||
/**
|
||||
* The empty string.
|
||||
|
@ -261,7 +262,8 @@ export function normalizeNFC(str: string): string {
|
|||
*/
|
||||
export function firstNonWhitespaceIndex(str: string): number {
|
||||
for (let i = 0, len = str.length; i < len; i++) {
|
||||
if (str.charAt(i) !== ' ' && str.charAt(i) !== '\t') {
|
||||
let chCode = str.charCodeAt(i);
|
||||
if (chCode !== CharCode.Space && chCode !== CharCode.Tab) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -274,7 +276,8 @@ export function firstNonWhitespaceIndex(str: string): number {
|
|||
*/
|
||||
export function getLeadingWhitespace(str: string): string {
|
||||
for (let i = 0, len = str.length; i < len; i++) {
|
||||
if (str.charAt(i) !== ' ' && str.charAt(i) !== '\t') {
|
||||
let chCode = str.charCodeAt(i);
|
||||
if (chCode !== CharCode.Space && chCode !== CharCode.Tab) {
|
||||
return str.substring(0, i);
|
||||
}
|
||||
}
|
||||
|
@ -287,7 +290,8 @@ export function getLeadingWhitespace(str: string): string {
|
|||
*/
|
||||
export function lastNonWhitespaceIndex(str: string, startIndex: number = str.length - 1): number {
|
||||
for (let i = startIndex; i >= 0; i--) {
|
||||
if (str.charAt(i) !== ' ' && str.charAt(i) !== '\t') {
|
||||
let chCode = str.charCodeAt(i);
|
||||
if (chCode !== CharCode.Space && chCode !== CharCode.Tab) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -305,7 +309,7 @@ export function compare(a: string, b: string): number {
|
|||
}
|
||||
|
||||
function isAsciiChar(code: number): boolean {
|
||||
return (code >= 97 && code <= 122) || (code >= 65 && code <= 90);
|
||||
return (code >= CharCode.a && code <= CharCode.z) || (code >= CharCode.A && code <= CharCode.Z);
|
||||
}
|
||||
|
||||
export function equalsIgnoreCase(a: string, b: string): boolean {
|
||||
|
@ -546,12 +550,10 @@ export function removeAnsiEscapeCodes(str: string): string {
|
|||
|
||||
// -- UTF-8 BOM
|
||||
|
||||
const __utf8_bom = 65279;
|
||||
|
||||
export const UTF8_BOM_CHARACTER = String.fromCharCode(__utf8_bom);
|
||||
export const UTF8_BOM_CHARACTER = String.fromCharCode(CharCode.UTF8_BOM);
|
||||
|
||||
export function startsWithUTF8BOM(str: string): boolean {
|
||||
return (str && str.length > 0 && str.charCodeAt(0) === __utf8_bom);
|
||||
return (str && str.length > 0 && str.charCodeAt(0) === CharCode.UTF8_BOM);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
8
src/vs/base/common/winjs.base.d.ts
vendored
8
src/vs/base/common/winjs.base.d.ts
vendored
|
@ -34,7 +34,7 @@ export declare class Promise {
|
|||
// static timeout(delay:number):Promise;
|
||||
|
||||
static wrapError(error:any):Promise;
|
||||
static is(value: any): boolean;
|
||||
static is(value: any): value is Thenable<any>;
|
||||
static addEventListener(type:string, fn:EventCallback):void;
|
||||
|
||||
public then(success?:ValueCallback, error?:ErrorCallback, progress?:ProgressCallback):Promise;
|
||||
|
@ -79,12 +79,16 @@ export declare class TPromise<V> {
|
|||
public cancel():void;
|
||||
|
||||
public static as<ValueType>(value:ValueType):TPromise<ValueType>;
|
||||
public static is(value: any): value is TPromise<any>;
|
||||
public static is(value: any): value is Thenable<any>;
|
||||
public static timeout(delay:number):TPromise<void>;
|
||||
public static join<ValueType>(promises:TPromise<ValueType>[]):TPromise<ValueType[]>;
|
||||
public static join<ValueType>(promises:Thenable<ValueType>[]):Thenable<ValueType[]>;
|
||||
public static join<ValueType>(promises: {[n:string]:TPromise<ValueType>}):TPromise<{[n:string]:ValueType}>;
|
||||
public static any<ValueType>(promises:TPromise<ValueType>[]):TPromise<{ key:string; value:TPromise<ValueType>;}>;
|
||||
|
||||
public static wrap<ValueType>(value: Thenable<ValueType>): TPromise<ValueType>;
|
||||
public static wrap<ValueType>(value: ValueType): TPromise<ValueType>;
|
||||
|
||||
public static wrapError<ValueType>(error:any):TPromise<ValueType>;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
'use strict';
|
||||
|
||||
import sd = require('string_decoder');
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
|
||||
/**
|
||||
* Convenient way to iterate over output line by line. This helper accommodates for the fact that
|
||||
|
@ -35,16 +36,16 @@ export class LineDecoder {
|
|||
}
|
||||
let start = 0;
|
||||
let ch: number;
|
||||
while (start < value.length && ((ch = value.charCodeAt(start)) === 13 || ch === 10)) {
|
||||
while (start < value.length && ((ch = value.charCodeAt(start)) === CharCode.CarriageReturn || ch === CharCode.LineFeed)) {
|
||||
start++;
|
||||
}
|
||||
let idx = start;
|
||||
while (idx < value.length) {
|
||||
ch = value.charCodeAt(idx);
|
||||
if (ch === 13 || ch === 10) {
|
||||
if (ch === CharCode.CarriageReturn || ch === CharCode.LineFeed) {
|
||||
result.push(value.substring(start, idx));
|
||||
idx++;
|
||||
while (idx < value.length && ((ch = value.charCodeAt(idx)) === 13 || ch === 10)) {
|
||||
while (idx < value.length && ((ch = value.charCodeAt(idx)) === CharCode.CarriageReturn || ch === CharCode.LineFeed)) {
|
||||
idx++;
|
||||
}
|
||||
start = idx;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
|
||||
import Event, { mapEvent, filterEvent } from 'vs/base/common/event';
|
||||
import Event, { chain } from 'vs/base/common/event';
|
||||
import { fromEventEmitter } from 'vs/base/node/event';
|
||||
import { Server as IPCServer, Client as IPCClient, IServer, IClient, IChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
|
||||
|
@ -73,9 +73,10 @@ export class Server implements IServer, IDisposable {
|
|||
}
|
||||
|
||||
private createScopedEvent(eventName: string, senderId: string) {
|
||||
const onRawMessageEvent = fromEventEmitter<IIPCEvent>(this.ipc, eventName, (event, message) => ({ event, message }));
|
||||
const onScopedRawMessageEvent = filterEvent<IIPCEvent>(onRawMessageEvent, ({ event }) => event.sender.getId() === senderId);
|
||||
return mapEvent<IIPCEvent,string>(onScopedRawMessageEvent, ({ message }) => message);
|
||||
return chain(fromEventEmitter<IIPCEvent>(this.ipc, eventName, (event, message) => ({ event, message })))
|
||||
.filter(({ event }) => event.sender.getId() === senderId)
|
||||
.map(({ message }) => message)
|
||||
.event;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
|
|
|
@ -335,59 +335,55 @@ export class QuickOpenWidget implements IModelProvider {
|
|||
private navigateInTree(keyCode: KeyCode, isShift?: boolean): void {
|
||||
const model: IModel<any> = this.tree.getInput();
|
||||
const entries = model ? model.entries : [];
|
||||
let focus = this.tree.getFocus();
|
||||
let cycled = false;
|
||||
let revealToTop = false;
|
||||
const oldFocus = this.tree.getFocus();
|
||||
|
||||
// Support cycle-through navigation
|
||||
if (entries.length > 1) {
|
||||
// Normal Navigation
|
||||
switch (keyCode) {
|
||||
case KeyCode.DownArrow:
|
||||
this.tree.focusNext();
|
||||
break;
|
||||
|
||||
case KeyCode.UpArrow:
|
||||
this.tree.focusPrevious();
|
||||
break;
|
||||
|
||||
case KeyCode.PageDown:
|
||||
this.tree.focusNextPage();
|
||||
break;
|
||||
|
||||
case KeyCode.PageUp:
|
||||
this.tree.focusPreviousPage();
|
||||
break;
|
||||
|
||||
case KeyCode.Tab:
|
||||
if (isShift) {
|
||||
this.tree.focusPrevious();
|
||||
} else {
|
||||
this.tree.focusNext();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
let newFocus = this.tree.getFocus();
|
||||
|
||||
// Support cycle-through navigation if focus did not change
|
||||
if (entries.length > 1 && oldFocus === newFocus) {
|
||||
|
||||
// Up from no entry or first entry goes down to last
|
||||
if ((keyCode === KeyCode.UpArrow || (keyCode === KeyCode.Tab && isShift)) && (focus === entries[0] || !focus)) { // TODO@Ben should not make ordering assumptions
|
||||
if (keyCode === KeyCode.UpArrow || (keyCode === KeyCode.Tab && isShift)) {
|
||||
this.tree.focusLast();
|
||||
cycled = true;
|
||||
}
|
||||
|
||||
// Down from last entry goes to up to first
|
||||
else if ((keyCode === KeyCode.DownArrow || keyCode === KeyCode.Tab && !isShift) && focus === entries[entries.length - 1]) { // TODO@Ben should not make ordering assumptions
|
||||
else if (keyCode === KeyCode.DownArrow || keyCode === KeyCode.Tab && !isShift) {
|
||||
this.tree.focusFirst();
|
||||
cycled = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Normal Navigation
|
||||
if (!cycled) {
|
||||
switch (keyCode) {
|
||||
case KeyCode.DownArrow:
|
||||
this.tree.focusNext();
|
||||
break;
|
||||
|
||||
case KeyCode.UpArrow:
|
||||
this.tree.focusPrevious();
|
||||
break;
|
||||
|
||||
case KeyCode.PageDown:
|
||||
this.tree.focusNextPage();
|
||||
break;
|
||||
|
||||
case KeyCode.PageUp:
|
||||
this.tree.focusPreviousPage();
|
||||
break;
|
||||
|
||||
case KeyCode.Tab:
|
||||
if (isShift) {
|
||||
this.tree.focusPrevious();
|
||||
} else {
|
||||
this.tree.focusNext();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Reveal
|
||||
focus = this.tree.getFocus();
|
||||
if (focus) {
|
||||
revealToTop ? this.tree.reveal(focus, 0).done(null, errors.onUnexpectedError) : this.tree.reveal(focus).done(null, errors.onUnexpectedError);
|
||||
newFocus = this.tree.getFocus();
|
||||
if (newFocus) {
|
||||
this.tree.reveal(newFocus).done(null, errors.onUnexpectedError);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,12 +43,6 @@
|
|||
height: 16px;
|
||||
}
|
||||
|
||||
/* Bare Style */
|
||||
.monaco-tree.bare .monaco-tree-row > .content.actions > .primary-action-bar {
|
||||
color: inherit !important;
|
||||
background-color: inherit !important;
|
||||
}
|
||||
|
||||
/* Default theme */
|
||||
.monaco-tree.focused .monaco-tree-row.focused:not(.highlighted) > .content.actions > .primary-action-bar { background-color: #DCEBFC; }
|
||||
.monaco-tree.focused .monaco-tree-row.selected:not(.highlighted) > .content.actions > .primary-action-bar { background-color: #4FA7FF; color: white; }
|
||||
|
|
|
@ -1,29 +1,31 @@
|
|||
<?xml version='1.0' standalone='no' ?>
|
||||
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
|
||||
<style>
|
||||
circle {
|
||||
animation: ball 0.6s linear infinite;
|
||||
}
|
||||
|
||||
circle:nth-child(2) { animation-delay: 0.075s; }
|
||||
circle:nth-child(3) { animation-delay: 0.15s; }
|
||||
circle:nth-child(4) { animation-delay: 0.225s; }
|
||||
circle:nth-child(5) { animation-delay: 0.3s; }
|
||||
circle:nth-child(6) { animation-delay: 0.375s; }
|
||||
circle:nth-child(7) { animation-delay: 0.45s; }
|
||||
circle:nth-child(8) { animation-delay: 0.525s; }
|
||||
|
||||
@keyframes ball {
|
||||
from { opacity: 1; }
|
||||
to { opacity: 0.3; }
|
||||
}
|
||||
</style>
|
||||
<g style="fill:grey;">
|
||||
<circle cx='5' cy='1' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0s' />
|
||||
</circle>
|
||||
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.075s' />
|
||||
</circle>
|
||||
<circle cx='9' cy='5' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.15s' />
|
||||
</circle>
|
||||
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.225s' />
|
||||
</circle>
|
||||
<circle cx='5' cy='9' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.3s' />
|
||||
</circle>
|
||||
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.375s' />
|
||||
</circle>
|
||||
<circle cx='1' cy='5' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.45s' />
|
||||
</circle>
|
||||
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.525s' />
|
||||
</circle>
|
||||
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
|
||||
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
|
||||
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
|
||||
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
|
||||
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
|
||||
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
|
||||
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
|
||||
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.1 KiB |
|
@ -1,29 +1,31 @@
|
|||
<?xml version='1.0' standalone='no' ?>
|
||||
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
|
||||
<g style="fill:#fff;">
|
||||
<circle cx='5' cy='1' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0s' />
|
||||
</circle>
|
||||
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.075s' />
|
||||
</circle>
|
||||
<circle cx='9' cy='5' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.15s' />
|
||||
</circle>
|
||||
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.225s' />
|
||||
</circle>
|
||||
<circle cx='5' cy='9' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.3s' />
|
||||
</circle>
|
||||
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.375s' />
|
||||
</circle>
|
||||
<circle cx='1' cy='5' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.45s' />
|
||||
</circle>
|
||||
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.525s' />
|
||||
</circle>
|
||||
<style>
|
||||
circle {
|
||||
animation: ball 0.6s linear infinite;
|
||||
}
|
||||
|
||||
circle:nth-child(2) { animation-delay: 0.075s; }
|
||||
circle:nth-child(3) { animation-delay: 0.15s; }
|
||||
circle:nth-child(4) { animation-delay: 0.225s; }
|
||||
circle:nth-child(5) { animation-delay: 0.3s; }
|
||||
circle:nth-child(6) { animation-delay: 0.375s; }
|
||||
circle:nth-child(7) { animation-delay: 0.45s; }
|
||||
circle:nth-child(8) { animation-delay: 0.525s; }
|
||||
|
||||
@keyframes ball {
|
||||
from { opacity: 1; }
|
||||
to { opacity: 0.3; }
|
||||
}
|
||||
</style>
|
||||
<g style="fill:white;">
|
||||
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
|
||||
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
|
||||
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
|
||||
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
|
||||
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
|
||||
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
|
||||
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
|
||||
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.1 KiB |
|
@ -1,29 +1,31 @@
|
|||
<?xml version='1.0' standalone='no' ?>
|
||||
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
|
||||
<style>
|
||||
circle {
|
||||
animation: ball 0.6s linear infinite;
|
||||
}
|
||||
|
||||
circle:nth-child(2) { animation-delay: 0.075s; }
|
||||
circle:nth-child(3) { animation-delay: 0.15s; }
|
||||
circle:nth-child(4) { animation-delay: 0.225s; }
|
||||
circle:nth-child(5) { animation-delay: 0.3s; }
|
||||
circle:nth-child(6) { animation-delay: 0.375s; }
|
||||
circle:nth-child(7) { animation-delay: 0.45s; }
|
||||
circle:nth-child(8) { animation-delay: 0.525s; }
|
||||
|
||||
@keyframes ball {
|
||||
from { opacity: 1; }
|
||||
to { opacity: 0.3; }
|
||||
}
|
||||
</style>
|
||||
<g>
|
||||
<circle cx='5' cy='1' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0s' />
|
||||
</circle>
|
||||
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.075s' />
|
||||
</circle>
|
||||
<circle cx='9' cy='5' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.15s' />
|
||||
</circle>
|
||||
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.225s' />
|
||||
</circle>
|
||||
<circle cx='5' cy='9' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.3s' />
|
||||
</circle>
|
||||
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.375s' />
|
||||
</circle>
|
||||
<circle cx='1' cy='5' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.45s' />
|
||||
</circle>
|
||||
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0.3' dur='0.6s' repeatCount='indefinite' begin='0.525s' />
|
||||
</circle>
|
||||
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
|
||||
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
|
||||
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
|
||||
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
|
||||
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
|
||||
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
|
||||
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
|
||||
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.1 KiB |
|
@ -91,14 +91,6 @@
|
|||
opacity: 0.3;
|
||||
}
|
||||
|
||||
/* Bare row */
|
||||
|
||||
.monaco-tree.bare .monaco-tree-wrapper.drop-target,
|
||||
.monaco-tree.bare .monaco-tree-row {
|
||||
color: inherit !important;
|
||||
background-color: inherit !important;
|
||||
}
|
||||
|
||||
/* Default style */
|
||||
|
||||
.monaco-tree.focused .monaco-tree-rows > .monaco-tree-row.focused:not(.highlighted) { background-color: #DCEBFC; }
|
||||
|
|
|
@ -632,7 +632,6 @@ export interface ITreeOptions {
|
|||
verticalScrollMode?: ScrollbarVisibility;
|
||||
alwaysFocused?: boolean;
|
||||
autoExpandSingleChildren?: boolean;
|
||||
bare?:boolean;
|
||||
useShadows?:boolean;
|
||||
paddingOnRow?:boolean;
|
||||
ariaLabel?:string;
|
||||
|
|
|
@ -14,7 +14,7 @@ import dom = require('vs/base/browser/dom');
|
|||
import mouse = require('vs/base/browser/mouseEvent');
|
||||
import {IKeyboardEvent} from 'vs/base/browser/keyboardEvent';
|
||||
import _ = require('vs/base/parts/tree/browser/tree');
|
||||
import {CommonKeybindings} from 'vs/base/common/keyCodes';
|
||||
import {KeyCode, KeyMod} from 'vs/base/common/keyCodes';
|
||||
|
||||
export interface ILegacyTemplateData {
|
||||
root: HTMLElement;
|
||||
|
@ -138,18 +138,18 @@ export class DefaultController implements _.IController {
|
|||
this.options = options;
|
||||
|
||||
this.downKeyBindingDispatcher = new KeybindingDispatcher();
|
||||
this.downKeyBindingDispatcher.set(CommonKeybindings.SPACE, (t, e) => this.onSpace(t, e));
|
||||
this.downKeyBindingDispatcher.set(CommonKeybindings.UP_ARROW, (t, e) => this.onUp(t, e));
|
||||
this.downKeyBindingDispatcher.set(CommonKeybindings.PAGE_UP, (t, e) => this.onPageUp(t, e));
|
||||
this.downKeyBindingDispatcher.set(CommonKeybindings.DOWN_ARROW, (t, e) => this.onDown(t, e));
|
||||
this.downKeyBindingDispatcher.set(CommonKeybindings.PAGE_DOWN, (t, e) => this.onPageDown(t, e));
|
||||
this.downKeyBindingDispatcher.set(CommonKeybindings.LEFT_ARROW, (t, e) => this.onLeft(t, e));
|
||||
this.downKeyBindingDispatcher.set(CommonKeybindings.RIGHT_ARROW, (t, e) => this.onRight(t, e));
|
||||
this.downKeyBindingDispatcher.set(CommonKeybindings.ESCAPE, (t, e) => this.onEscape(t, e));
|
||||
this.downKeyBindingDispatcher.set(KeyCode.Space, (t, e) => this.onSpace(t, e));
|
||||
this.downKeyBindingDispatcher.set(KeyCode.UpArrow, (t, e) => this.onUp(t, e));
|
||||
this.downKeyBindingDispatcher.set(KeyCode.PageUp, (t, e) => this.onPageUp(t, e));
|
||||
this.downKeyBindingDispatcher.set(KeyCode.DownArrow, (t, e) => this.onDown(t, e));
|
||||
this.downKeyBindingDispatcher.set(KeyCode.PageDown, (t, e) => this.onPageDown(t, e));
|
||||
this.downKeyBindingDispatcher.set(KeyCode.LeftArrow, (t, e) => this.onLeft(t, e));
|
||||
this.downKeyBindingDispatcher.set(KeyCode.RightArrow, (t, e) => this.onRight(t, e));
|
||||
this.downKeyBindingDispatcher.set(KeyCode.Escape, (t, e) => this.onEscape(t, e));
|
||||
|
||||
this.upKeyBindingDispatcher = new KeybindingDispatcher();
|
||||
this.upKeyBindingDispatcher.set(CommonKeybindings.ENTER, this.onEnter.bind(this));
|
||||
this.upKeyBindingDispatcher.set(CommonKeybindings.CTRLCMD_ENTER, this.onEnter.bind(this));
|
||||
this.upKeyBindingDispatcher.set(KeyCode.Enter, this.onEnter.bind(this));
|
||||
this.upKeyBindingDispatcher.set(KeyMod.CtrlCmd | KeyCode.Enter, this.onEnter.bind(this));
|
||||
}
|
||||
|
||||
public onMouseDown(tree:_.ITree, element: any, event:mouse.IMouseEvent, origin: string = 'mouse'):boolean {
|
||||
|
|
|
@ -66,7 +66,6 @@ export class Tree extends Events.EventEmitter implements _.ITree {
|
|||
this.options.twistiePixels = typeof this.options.twistiePixels === 'number' ? this.options.twistiePixels : 32;
|
||||
this.options.indentPixels = typeof this.options.indentPixels === 'number' ? this.options.indentPixels : 12;
|
||||
this.options.alwaysFocused = this.options.alwaysFocused === true ? true : false;
|
||||
this.options.bare = this.options.bare === true ? true : false;
|
||||
this.options.useShadows = this.options.useShadows === false ? false : true;
|
||||
this.options.paddingOnRow = this.options.paddingOnRow === false ? false : true;
|
||||
|
||||
|
|
|
@ -477,10 +477,6 @@ export class TreeView extends HeightMap {
|
|||
DOM.addClass(this.domNode, 'focused');
|
||||
}
|
||||
|
||||
if (this.context.options.bare) {
|
||||
DOM.addClass(this.domNode, 'bare');
|
||||
}
|
||||
|
||||
if (!this.context.options.paddingOnRow) {
|
||||
DOM.addClass(this.domNode, 'no-row-padding');
|
||||
}
|
||||
|
|
|
@ -810,7 +810,7 @@ suite('Builder', () => {
|
|||
b.showDelayed(20);
|
||||
assert(b.hasClass('hidden'));
|
||||
|
||||
TPromise.timeout(30).then(function () {
|
||||
TPromise.timeout(30).then(() => {
|
||||
assert(!b.hasClass('hidden'));
|
||||
done();
|
||||
});
|
||||
|
@ -825,7 +825,7 @@ suite('Builder', () => {
|
|||
|
||||
b.hide(); // Should cancel the visibility promise
|
||||
|
||||
TPromise.timeout(30).then(function () {
|
||||
TPromise.timeout(30).then(() => {
|
||||
assert(b.hasClass('hidden'));
|
||||
done();
|
||||
});
|
||||
|
|
122
src/vs/base/test/common/charCode.test.ts
Normal file
122
src/vs/base/test/common/charCode.test.ts
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
|
||||
suite('CharCode', () => {
|
||||
test('has good values', () => {
|
||||
|
||||
function assertValue(actual:CharCode, expected:string): void {
|
||||
assert.equal(actual, expected.charCodeAt(0), 'char code ok for <<' + expected + '>>');
|
||||
}
|
||||
|
||||
assertValue(CharCode.Tab, '\t');
|
||||
assertValue(CharCode.LineFeed, '\n');
|
||||
assertValue(CharCode.CarriageReturn, '\r');
|
||||
assertValue(CharCode.Space, ' ');
|
||||
assertValue(CharCode.ExclamationMark, '!');
|
||||
assertValue(CharCode.DoubleQuote, '"');
|
||||
assertValue(CharCode.Hash, '#');
|
||||
assertValue(CharCode.DollarSign, '$');
|
||||
assertValue(CharCode.PercentSign, '%');
|
||||
assertValue(CharCode.Ampersand, '&');
|
||||
assertValue(CharCode.SingleQuote, '\'');
|
||||
assertValue(CharCode.OpenParen, '(');
|
||||
assertValue(CharCode.CloseParen, ')');
|
||||
assertValue(CharCode.Asterisk, '*');
|
||||
assertValue(CharCode.Plus, '+');
|
||||
assertValue(CharCode.Comma, ',');
|
||||
assertValue(CharCode.Dash, '-');
|
||||
assertValue(CharCode.Period, '.');
|
||||
assertValue(CharCode.Slash, '/');
|
||||
|
||||
assertValue(CharCode.Digit0, '0');
|
||||
assertValue(CharCode.Digit1, '1');
|
||||
assertValue(CharCode.Digit2, '2');
|
||||
assertValue(CharCode.Digit3, '3');
|
||||
assertValue(CharCode.Digit4, '4');
|
||||
assertValue(CharCode.Digit5, '5');
|
||||
assertValue(CharCode.Digit6, '6');
|
||||
assertValue(CharCode.Digit7, '7');
|
||||
assertValue(CharCode.Digit8, '8');
|
||||
assertValue(CharCode.Digit9, '9');
|
||||
|
||||
assertValue(CharCode.Colon, ':');
|
||||
assertValue(CharCode.Semicolon, ';');
|
||||
assertValue(CharCode.LessThan, '<');
|
||||
assertValue(CharCode.Equals, '=');
|
||||
assertValue(CharCode.GreaterThan, '>');
|
||||
assertValue(CharCode.QuestionMark, '?');
|
||||
assertValue(CharCode.AtSign, '@');
|
||||
|
||||
assertValue(CharCode.A, 'A');
|
||||
assertValue(CharCode.B, 'B');
|
||||
assertValue(CharCode.C, 'C');
|
||||
assertValue(CharCode.D, 'D');
|
||||
assertValue(CharCode.E, 'E');
|
||||
assertValue(CharCode.F, 'F');
|
||||
assertValue(CharCode.G, 'G');
|
||||
assertValue(CharCode.H, 'H');
|
||||
assertValue(CharCode.I, 'I');
|
||||
assertValue(CharCode.J, 'J');
|
||||
assertValue(CharCode.K, 'K');
|
||||
assertValue(CharCode.L, 'L');
|
||||
assertValue(CharCode.M, 'M');
|
||||
assertValue(CharCode.N, 'N');
|
||||
assertValue(CharCode.O, 'O');
|
||||
assertValue(CharCode.P, 'P');
|
||||
assertValue(CharCode.Q, 'Q');
|
||||
assertValue(CharCode.R, 'R');
|
||||
assertValue(CharCode.S, 'S');
|
||||
assertValue(CharCode.T, 'T');
|
||||
assertValue(CharCode.U, 'U');
|
||||
assertValue(CharCode.V, 'V');
|
||||
assertValue(CharCode.W, 'W');
|
||||
assertValue(CharCode.X, 'X');
|
||||
assertValue(CharCode.Y, 'Y');
|
||||
assertValue(CharCode.Z, 'Z');
|
||||
|
||||
assertValue(CharCode.OpenSquareBracket, '[');
|
||||
assertValue(CharCode.Backslash, '\\');
|
||||
assertValue(CharCode.CloseSquareBracket, ']');
|
||||
assertValue(CharCode.Caret, '^');
|
||||
assertValue(CharCode.Underline, '_');
|
||||
assertValue(CharCode.BackTick, '`');
|
||||
|
||||
assertValue(CharCode.a, 'a');
|
||||
assertValue(CharCode.b, 'b');
|
||||
assertValue(CharCode.c, 'c');
|
||||
assertValue(CharCode.d, 'd');
|
||||
assertValue(CharCode.e, 'e');
|
||||
assertValue(CharCode.f, 'f');
|
||||
assertValue(CharCode.g, 'g');
|
||||
assertValue(CharCode.h, 'h');
|
||||
assertValue(CharCode.i, 'i');
|
||||
assertValue(CharCode.j, 'j');
|
||||
assertValue(CharCode.k, 'k');
|
||||
assertValue(CharCode.l, 'l');
|
||||
assertValue(CharCode.m, 'm');
|
||||
assertValue(CharCode.n, 'n');
|
||||
assertValue(CharCode.o, 'o');
|
||||
assertValue(CharCode.p, 'p');
|
||||
assertValue(CharCode.q, 'q');
|
||||
assertValue(CharCode.r, 'r');
|
||||
assertValue(CharCode.s, 's');
|
||||
assertValue(CharCode.t, 't');
|
||||
assertValue(CharCode.u, 'u');
|
||||
assertValue(CharCode.v, 'v');
|
||||
assertValue(CharCode.w, 'w');
|
||||
assertValue(CharCode.x, 'x');
|
||||
assertValue(CharCode.y, 'y');
|
||||
assertValue(CharCode.z, 'z');
|
||||
|
||||
assertValue(CharCode.OpenCurlyBrace, '{');
|
||||
assertValue(CharCode.Pipe, '|');
|
||||
assertValue(CharCode.CloseCurlyBrace, '}');
|
||||
assertValue(CharCode.Tilde, '~');
|
||||
});
|
||||
});
|
|
@ -5,10 +5,11 @@
|
|||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import Event, {Emitter, fromEventEmitter, debounceEvent, EventBufferer, once} from 'vs/base/common/event';
|
||||
import Event, {Emitter, fromEventEmitter, debounceEvent, EventBufferer, once, fromPromise, stopwatch} from 'vs/base/common/event';
|
||||
import {IDisposable} from 'vs/base/common/lifecycle';
|
||||
import {EventEmitter} from 'vs/base/common/eventEmitter';
|
||||
import Errors = require('vs/base/common/errors');
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
|
||||
namespace Samples {
|
||||
|
||||
|
@ -282,4 +283,72 @@ suite('EventBufferer', () => {
|
|||
listener1.dispose();
|
||||
listener2.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
suite('fromPromise', () => {
|
||||
|
||||
test('should emit when done', () => {
|
||||
let count = 0;
|
||||
|
||||
const event = fromPromise(TPromise.as(null));
|
||||
event(() => count++);
|
||||
|
||||
assert.equal(count, 0);
|
||||
|
||||
return TPromise.timeout(10).then(() => {
|
||||
assert.equal(count, 1);
|
||||
});
|
||||
});
|
||||
|
||||
test('should emit when done - setTimeout', () => {
|
||||
let count = 0;
|
||||
|
||||
const event = fromPromise(TPromise.timeout(5));
|
||||
event(() => count++);
|
||||
|
||||
assert.equal(count, 0);
|
||||
|
||||
return TPromise.timeout(10).then(() => {
|
||||
assert.equal(count, 1);
|
||||
});
|
||||
});
|
||||
|
||||
test('should emit when done - setTimeout', () => {
|
||||
let count = 0;
|
||||
|
||||
const event = fromPromise(TPromise.timeout(10));
|
||||
event(() => count++);
|
||||
|
||||
assert.equal(count, 0);
|
||||
|
||||
return TPromise.timeout(0).then(() => {
|
||||
assert.equal(count, 0);
|
||||
|
||||
return TPromise.timeout(10).then(() => {
|
||||
assert.equal(count, 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('stopwatch', () => {
|
||||
|
||||
test('should emit', () => {
|
||||
const emitter = new Emitter<void>();
|
||||
const event = stopwatch(emitter.event);
|
||||
|
||||
return new TPromise((c, e) => {
|
||||
event(duration => {
|
||||
try {
|
||||
assert(duration > 0);
|
||||
} catch (err) {
|
||||
e(err);
|
||||
}
|
||||
|
||||
c(null);
|
||||
});
|
||||
|
||||
setTimeout(() => emitter.fire(), 10);
|
||||
});
|
||||
});
|
||||
});
|
114
src/vs/base/test/common/history.test.ts
Normal file
114
src/vs/base/test/common/history.test.ts
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import {HistoryNavigator} from 'vs/base/common/history';
|
||||
|
||||
suite('History Navigator', () => {
|
||||
|
||||
test('create reduces the input to limit', function () {
|
||||
let testObject = new HistoryNavigator(['1', '2', '3', '4'], 2);
|
||||
|
||||
assert.deepEqual(['3', '4'], toArray(testObject));
|
||||
});
|
||||
|
||||
test('create sets the position to last', function () {
|
||||
let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3);
|
||||
|
||||
assert.equal('4', testObject.current());
|
||||
assert.equal(null, testObject.next());
|
||||
assert.equal('3', testObject.previous());
|
||||
});
|
||||
|
||||
test('last returns last element', function () {
|
||||
let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3);
|
||||
|
||||
testObject.first();
|
||||
|
||||
assert.equal('4', testObject.last());
|
||||
});
|
||||
|
||||
test('first returns first element', function () {
|
||||
let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3);
|
||||
|
||||
assert.equal('2', testObject.first());
|
||||
});
|
||||
|
||||
test('next returns next element', function () {
|
||||
let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3);
|
||||
|
||||
testObject.first();
|
||||
|
||||
assert.equal('3', testObject.next());
|
||||
assert.equal('4', testObject.next());
|
||||
assert.equal(null, testObject.next());
|
||||
});
|
||||
|
||||
test('previous returns previous element', function () {
|
||||
let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3);
|
||||
|
||||
assert.equal('3', testObject.previous());
|
||||
assert.equal('2', testObject.previous());
|
||||
assert.equal(null, testObject.previous());
|
||||
});
|
||||
|
||||
test('next on last element returs null and remains on last', function () {
|
||||
let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3);
|
||||
|
||||
testObject.first();
|
||||
testObject.last();
|
||||
|
||||
assert.equal('4', testObject.current());
|
||||
assert.equal(null, testObject.next());
|
||||
});
|
||||
|
||||
test('previous on first element returs null and remains on first', function () {
|
||||
let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3);
|
||||
|
||||
testObject.first();
|
||||
|
||||
assert.equal('2', testObject.current());
|
||||
assert.equal(null, testObject.previous());
|
||||
});
|
||||
|
||||
test('add reduces the input to limit', function () {
|
||||
let testObject = new HistoryNavigator(['1', '2', '3', '4'], 2);
|
||||
|
||||
testObject.add('5');
|
||||
|
||||
assert.deepEqual(['4', '5'], toArray(testObject));
|
||||
});
|
||||
|
||||
test('adding existing element changes the position', function () {
|
||||
let testObject = new HistoryNavigator(['1', '2', '3', '4'], 2);
|
||||
|
||||
testObject.add('2');
|
||||
|
||||
assert.deepEqual(['4', '2'], toArray(testObject));
|
||||
});
|
||||
|
||||
test('add resets the navigator to last', function () {
|
||||
let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3);
|
||||
|
||||
testObject.first();
|
||||
testObject.add('5');
|
||||
|
||||
assert.equal('5', testObject.current());
|
||||
assert.equal(null, testObject.next());
|
||||
});
|
||||
|
||||
function toArray(historyNavigator: HistoryNavigator<string>): string[] {
|
||||
let result = [];
|
||||
historyNavigator.first();
|
||||
if (historyNavigator.current()) {
|
||||
do {
|
||||
result.push(historyNavigator.current());
|
||||
} while (historyNavigator.next());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import {KeyCode, KeyMod, BinaryKeybindings, Keybinding} from 'vs/base/common/keyCodes';
|
||||
import {KeyCode, KeyMod, KeyChord, BinaryKeybindings} from 'vs/base/common/keyCodes';
|
||||
|
||||
interface ITestKeybinding {
|
||||
ctrlCmd?: boolean;
|
||||
|
@ -39,7 +39,7 @@ suite('keyCodes', () => {
|
|||
|
||||
test(null, 0);
|
||||
test({ key: KeyCode.Enter }, KeyCode.Enter);
|
||||
test({ key: KeyCode.Enter, chord: { key: KeyCode.Tab } }, KeyMod.chord(KeyCode.Enter, KeyCode.Tab));
|
||||
test({ key: KeyCode.Enter, chord: { key: KeyCode.Tab } }, KeyChord(KeyCode.Enter, KeyCode.Tab));
|
||||
test({ ctrlCmd: false, shift: false, alt: false, winCtrl: false, key: KeyCode.Enter }, KeyCode.Enter);
|
||||
test({ ctrlCmd: false, shift: false, alt: false, winCtrl: true, key: KeyCode.Enter }, KeyMod.WinCtrl | KeyCode.Enter);
|
||||
test({ ctrlCmd: false, shift: false, alt: true, winCtrl: false, key: KeyCode.Enter }, KeyMod.Alt | KeyCode.Enter);
|
||||
|
@ -57,7 +57,7 @@ suite('keyCodes', () => {
|
|||
test({ ctrlCmd: true, shift: true, alt: true, winCtrl: false, key: KeyCode.Enter }, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.Enter);
|
||||
test({ ctrlCmd: true, shift: true, alt: true, winCtrl: true, key: KeyCode.Enter }, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter);
|
||||
|
||||
let encoded = KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_Y, KeyCode.KEY_Z);
|
||||
let encoded = KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_Y, KeyCode.KEY_Z);
|
||||
let encodedFirstPart = BinaryKeybindings.extractFirstPart(encoded);
|
||||
let encodedSecondPart = BinaryKeybindings.extractChordPart(encoded);
|
||||
|
||||
|
@ -65,44 +65,4 @@ suite('keyCodes', () => {
|
|||
assert.equal(encodedFirstPart, KeyMod.CtrlCmd | KeyCode.KEY_Y, 'first part');
|
||||
assert.equal(encodedSecondPart, encodedSecondPart, 'chord part');
|
||||
});
|
||||
|
||||
test('getUserSettingsKeybindingRegex', () => {
|
||||
let regex = new RegExp(Keybinding.getUserSettingsKeybindingRegex());
|
||||
|
||||
function testIsGood(userSettingsLabel:string, message:string = userSettingsLabel): void {
|
||||
let userSettings = '"' + userSettingsLabel.replace(/\\/g, '\\\\') + '"';
|
||||
let isGood = regex.test(userSettings);
|
||||
assert.ok(isGood, message);
|
||||
}
|
||||
|
||||
// check that all key codes are covered by the regex
|
||||
let ignore: boolean[] = [];
|
||||
ignore[KeyCode.Shift] = true;
|
||||
ignore[KeyCode.Ctrl] = true;
|
||||
ignore[KeyCode.Alt] = true;
|
||||
ignore[KeyCode.Meta] = true;
|
||||
for (let keyCode = KeyCode.Unknown + 1; keyCode < KeyCode.MAX_VALUE; keyCode++) {
|
||||
if (ignore[keyCode]) {
|
||||
continue;
|
||||
}
|
||||
let userSettings = Keybinding.toUserSettingsLabel(keyCode);
|
||||
testIsGood(userSettings, keyCode + ' - ' + KeyCode[keyCode] + ' - ' + userSettings);
|
||||
}
|
||||
|
||||
// one modifier
|
||||
testIsGood('ctrl+a');
|
||||
testIsGood('shift+a');
|
||||
testIsGood('alt+a');
|
||||
testIsGood('cmd+a');
|
||||
testIsGood('meta+a');
|
||||
testIsGood('win+a');
|
||||
|
||||
// more modifiers
|
||||
testIsGood('ctrl+shift+a');
|
||||
testIsGood('shift+alt+a');
|
||||
testIsGood('ctrl+shift+alt+a');
|
||||
|
||||
// chords
|
||||
testIsGood('ctrl+a ctrl+a');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -486,7 +486,6 @@ export class VSCodeMenu {
|
|||
const toggleStatusbar = this.createMenuItem(nls.localize({ key: 'miToggleStatusbar', comment: ['&& denotes a mnemonic'] }, "&&Toggle Status Bar"), 'workbench.action.toggleStatusbarVisibility');
|
||||
|
||||
const toggleWordWrap = this.createMenuItem(nls.localize({ key: 'miToggleWordWrap', comment: ['&& denotes a mnemonic'] }, "Toggle &&Word Wrap"), 'editor.action.toggleWordWrap');
|
||||
const toggleRenderWhitespace = this.createMenuItem(nls.localize({ key: 'miToggleRenderWhitespace', comment: ['&& denotes a mnemonic'] }, "Toggle &&Render Whitespace"), 'editor.action.toggleRenderWhitespace');
|
||||
const toggleRenderControlCharacters = this.createMenuItem(nls.localize({ key: 'miToggleRenderControlCharacters', comment: ['&& denotes a mnemonic'] }, "Toggle &&Control Characters"), 'editor.action.toggleRenderControlCharacter');
|
||||
|
||||
|
||||
|
@ -518,7 +517,6 @@ export class VSCodeMenu {
|
|||
toggleStatusbar,
|
||||
__separator__(),
|
||||
toggleWordWrap,
|
||||
toggleRenderWhitespace,
|
||||
toggleRenderControlCharacters,
|
||||
__separator__(),
|
||||
zoomIn,
|
||||
|
|
|
@ -166,7 +166,7 @@ export class VSCodeWindow {
|
|||
height: this.windowState.height,
|
||||
x: this.windowState.x,
|
||||
y: this.windowState.y,
|
||||
backgroundColor: usesLightTheme ? '#FFFFFF' : platform.isMacintosh ? '#131313' : '#1E1E1E', // https://github.com/electron/electron/issues/5150
|
||||
backgroundColor: usesLightTheme ? '#FFFFFF' : platform.isMacintosh ? '#171717' : '#1E1E1E', // https://github.com/electron/electron/issues/5150
|
||||
minWidth: VSCodeWindow.MIN_WIDTH,
|
||||
minHeight: VSCodeWindow.MIN_HEIGHT,
|
||||
show: !isFullscreenOrMaximized,
|
||||
|
@ -430,7 +430,12 @@ export class VSCodeWindow {
|
|||
public serializeWindowState(): IWindowState {
|
||||
if (this.win.isFullScreen()) {
|
||||
return {
|
||||
mode: WindowMode.Fullscreen
|
||||
mode: WindowMode.Fullscreen,
|
||||
// still carry over window dimensions from previous sessions!
|
||||
width: this.windowState.width,
|
||||
height: this.windowState.height,
|
||||
x: this.windowState.x,
|
||||
y: this.windowState.y
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -494,7 +499,7 @@ export class VSCodeWindow {
|
|||
return state;
|
||||
}
|
||||
|
||||
return null;
|
||||
state.mode = WindowMode.Normal; // if we do not allow fullscreen, treat this state as normal window state
|
||||
}
|
||||
|
||||
if ([state.x, state.y, state.width, state.height].some(n => typeof n !== 'number')) {
|
||||
|
|
|
@ -100,9 +100,11 @@ class Main {
|
|||
const response = JSON.parse(err.responseText);
|
||||
return TPromise.wrapError(response.message);
|
||||
} catch (e) {
|
||||
return TPromise.wrapError(err);
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
return TPromise.wrapError(err);
|
||||
})
|
||||
.then(result => {
|
||||
const [extension] = result.firstPage;
|
||||
|
|
|
@ -383,12 +383,12 @@ class DecorationRenderHelper {
|
|||
}
|
||||
}
|
||||
|
||||
enum ThemeType {
|
||||
const enum ThemeType {
|
||||
Light = 0,
|
||||
Dark = 1,
|
||||
HighContrastBlack = 2
|
||||
}
|
||||
enum ModelDecorationCSSRuleType {
|
||||
const enum ModelDecorationCSSRuleType {
|
||||
ClassName = 0,
|
||||
InlineClassName = 1,
|
||||
GlyphMarginClassName = 2,
|
||||
|
|
|
@ -126,7 +126,7 @@ export class Colorizer {
|
|||
tabSize,
|
||||
0,
|
||||
-1,
|
||||
false,
|
||||
'none',
|
||||
false,
|
||||
tokens
|
||||
));
|
||||
|
@ -171,7 +171,7 @@ function actualColorize(lines:string[], mode:IMode, tabSize:number): IActualColo
|
|||
tabSize,
|
||||
0,
|
||||
-1,
|
||||
false,
|
||||
'none',
|
||||
false,
|
||||
tokenizeResult.tokens.map(t => new ViewLineToken(t.startIndex, t.type))
|
||||
));
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import {EventEmitter} from 'vs/base/common/eventEmitter';
|
||||
import {Schemas} from 'vs/base/common/network';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
|
@ -56,13 +55,18 @@ export class SimpleEditor implements IEditor {
|
|||
}
|
||||
}
|
||||
|
||||
export class SimpleModel extends EventEmitter implements ITextEditorModel {
|
||||
export class SimpleModel implements ITextEditorModel {
|
||||
|
||||
private model:editorCommon.IModel;
|
||||
private _onDispose: Emitter<void>;
|
||||
|
||||
constructor(model:editorCommon.IModel) {
|
||||
super();
|
||||
this.model = model;
|
||||
this._onDispose = new Emitter<void>();
|
||||
}
|
||||
|
||||
public get onDispose(): Event<void> {
|
||||
return this._onDispose.event;
|
||||
}
|
||||
|
||||
public load(): TPromise<SimpleModel> {
|
||||
|
@ -72,6 +76,10 @@ export class SimpleModel extends EventEmitter implements ITextEditorModel {
|
|||
public get textEditorModel():editorCommon.IModel {
|
||||
return this.model;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this._onDispose.fire();
|
||||
}
|
||||
}
|
||||
|
||||
export interface IOpenEditorDelegate {
|
||||
|
|
|
@ -243,7 +243,7 @@ export function colorizeModelLine(model:IModel, lineNumber:number, tabSize:numbe
|
|||
export function createMonacoEditorAPI(): typeof monaco.editor {
|
||||
return {
|
||||
// methods
|
||||
create: create,
|
||||
create: <any>create,
|
||||
createDiffEditor: createDiffEditor,
|
||||
createDiffNavigator: createDiffNavigator,
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import {InlineDecoration} from 'vs/editor/common/viewModel/viewModel';
|
|||
export class ViewLine implements IVisibleLineData {
|
||||
|
||||
protected _context:ViewContext;
|
||||
private _renderWhitespace: boolean;
|
||||
private _renderWhitespace: 'none' | 'boundary' | 'all';
|
||||
private _renderControlCharacters: boolean;
|
||||
private _spaceWidth: number;
|
||||
private _lineHeight: number;
|
||||
|
|
|
@ -13,7 +13,7 @@ import {HorizontalRange, LineVisibleRanges} from 'vs/editor/common/view/renderin
|
|||
import {IRenderingContext} from 'vs/editor/common/view/renderingContext';
|
||||
import {Range} from 'vs/editor/common/core/range';
|
||||
|
||||
enum CornerStyle {
|
||||
const enum CornerStyle {
|
||||
EXTERN,
|
||||
INTERN,
|
||||
FLAT
|
||||
|
|
|
@ -10,6 +10,7 @@ import {Range} from 'vs/editor/common/core/range';
|
|||
import {Selection} from 'vs/editor/common/core/selection';
|
||||
import {ICommand, ICursorStateComputerData, IEditOperationBuilder, ITokenizedModel} from 'vs/editor/common/editorCommon';
|
||||
import {LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
|
||||
export interface IShiftCommandOpts {
|
||||
isUnshift: boolean;
|
||||
|
@ -53,7 +54,6 @@ export class ShiftCommand implements ICommand {
|
|||
public getEditOperations(model: ITokenizedModel, builder: IEditOperationBuilder): void {
|
||||
let startLine = this._selection.startLineNumber;
|
||||
let endLine = this._selection.endLineNumber;
|
||||
let _SPACE = ' '.charCodeAt(0);
|
||||
|
||||
if (this._selection.endColumn === 1 && startLine !== endLine) {
|
||||
endLine = endLine - 1;
|
||||
|
@ -106,7 +106,7 @@ export class ShiftCommand implements ICommand {
|
|||
extraSpaces = previousLineExtraSpaces;
|
||||
if (enterAction.appendText) {
|
||||
for (let j = 0, lenJ = enterAction.appendText.length; j < lenJ && extraSpaces < tabSize; j++) {
|
||||
if (enterAction.appendText.charCodeAt(j) === _SPACE) {
|
||||
if (enterAction.appendText.charCodeAt(j) === CharCode.Space) {
|
||||
extraSpaces++;
|
||||
} else {
|
||||
break;
|
||||
|
@ -119,7 +119,7 @@ export class ShiftCommand implements ICommand {
|
|||
|
||||
// Act as if `prefixSpaces` is not part of the indentation
|
||||
for (let j = 0; j < extraSpaces; j++) {
|
||||
if (indentationEndIndex === 0 || lineText.charCodeAt(indentationEndIndex - 1) !== _SPACE) {
|
||||
if (indentationEndIndex === 0 || lineText.charCodeAt(indentationEndIndex - 1) !== CharCode.Space) {
|
||||
break;
|
||||
}
|
||||
indentationEndIndex--;
|
||||
|
|
|
@ -251,7 +251,7 @@ class InternalEditorOptionsHelper {
|
|||
scrollBeyondLastLine: toBoolean(opts.scrollBeyondLastLine),
|
||||
editorClassName: editorClassName,
|
||||
stopRenderingLineAfter: stopRenderingLineAfter,
|
||||
renderWhitespace: toBoolean(opts.renderWhitespace),
|
||||
renderWhitespace: opts.renderWhitespace,
|
||||
renderControlCharacters: toBoolean(opts.renderControlCharacters),
|
||||
renderIndentGuides: toBoolean(opts.renderIndentGuides),
|
||||
renderLineHighlight: toBoolean(opts.renderLineHighlight),
|
||||
|
@ -478,6 +478,9 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed
|
|||
let fontSize = toFloat(opts.fontSize, DefaultConfig.editor.fontSize);
|
||||
fontSize = Math.max(0, fontSize);
|
||||
fontSize = Math.min(100, fontSize);
|
||||
if (fontSize === 0) {
|
||||
fontSize = DefaultConfig.editor.fontSize;
|
||||
}
|
||||
|
||||
let lineHeight = toInteger(opts.lineHeight, 0, 150);
|
||||
if (lineHeight === 0) {
|
||||
|
@ -769,9 +772,10 @@ let editorConfiguration:IConfigurationNode = {
|
|||
'description': nls.localize('hideCursorInOverviewRuler', "Controls if the cursor should be hidden in the overview ruler.")
|
||||
},
|
||||
'editor.renderWhitespace': {
|
||||
'type': 'boolean',
|
||||
'type': 'string',
|
||||
'enum': ['none', 'boundary', 'all'],
|
||||
default: DefaultConfig.editor.renderWhitespace,
|
||||
description: nls.localize('renderWhitespace', "Controls whether the editor should render whitespace characters")
|
||||
description: nls.localize('renderWhitespace', "Controls how the editor should render whitespace characters, posibilties are 'none', 'boundary', and 'all'. The 'boundary' option does not render single spaces between words.")
|
||||
},
|
||||
'editor.renderControlCharacters': {
|
||||
'type': 'boolean',
|
||||
|
|
|
@ -91,7 +91,7 @@ class ConfigClass implements IConfiguration {
|
|||
codeLens: true,
|
||||
referenceInfos: true,
|
||||
folding: true,
|
||||
renderWhitespace: false,
|
||||
renderWhitespace: 'none',
|
||||
renderControlCharacters: false,
|
||||
renderIndentGuides: false,
|
||||
renderLineHighlight: true,
|
||||
|
|
|
@ -22,7 +22,7 @@ export interface ITypingListener {
|
|||
(): void;
|
||||
}
|
||||
|
||||
enum RevealTarget {
|
||||
const enum RevealTarget {
|
||||
Primary = 0,
|
||||
TopMost = 1,
|
||||
BottomMost = 2
|
||||
|
|
|
@ -50,13 +50,13 @@ export interface IConfiguration {
|
|||
getIndentationOptions(): IInternalIndentationOptions;
|
||||
}
|
||||
|
||||
function isHighSurrogate(model, lineNumber, column) {
|
||||
var code = model.getLineContent(lineNumber).charCodeAt(column - 1);
|
||||
function isHighSurrogate(model:ICursorMoveHelperModel, lineNumber:number, column:number) {
|
||||
let code = model.getLineContent(lineNumber).charCodeAt(column - 1);
|
||||
return 0xD800 <= code && code <= 0xDBFF;
|
||||
}
|
||||
|
||||
function isLowSurrogate(model, lineNumber, column) {
|
||||
var code = model.getLineContent(lineNumber).charCodeAt(column - 1);
|
||||
function isLowSurrogate(model:ICursorMoveHelperModel, lineNumber:number, column:number) {
|
||||
let code = model.getLineContent(lineNumber).charCodeAt(column - 1);
|
||||
return 0xDC00 <= code && code <= 0xDFFF;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ import {Selection, SelectionDirection} from 'vs/editor/common/core/selection';
|
|||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import {IElectricAction, IndentAction} from 'vs/editor/common/modes';
|
||||
import {LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
import {CharacterClassifier} from 'vs/editor/common/core/characterClassifier';
|
||||
|
||||
export interface IPostOperationRunnable {
|
||||
(ctx: IOneCursorOperationContext): void;
|
||||
|
@ -99,31 +101,23 @@ export interface IFindWordResult {
|
|||
wordType: WordType;
|
||||
}
|
||||
|
||||
export enum WordType {
|
||||
export const enum WordType {
|
||||
None = 0,
|
||||
Regular = 1,
|
||||
Separator = 2
|
||||
};
|
||||
|
||||
enum CharacterClass {
|
||||
const enum CharacterClass {
|
||||
Regular = 0,
|
||||
Whitespace = 1,
|
||||
WordSeparator = 2
|
||||
};
|
||||
|
||||
export enum WordNavigationType {
|
||||
export const enum WordNavigationType {
|
||||
WordStart = 0,
|
||||
WordEnd = 1
|
||||
}
|
||||
|
||||
const CH_REGULAR = CharacterClass.Regular;
|
||||
const CH_WHITESPACE = CharacterClass.Whitespace;
|
||||
const CH_WORD_SEPARATOR = CharacterClass.WordSeparator;
|
||||
|
||||
const W_NONE = WordType.None;
|
||||
const W_REGULAR = WordType.Regular;
|
||||
const W_SEPARATOR = WordType.Separator;
|
||||
|
||||
export class OneCursor {
|
||||
|
||||
// --- contextual state
|
||||
|
@ -1528,8 +1522,6 @@ export class OneCursorOp {
|
|||
}
|
||||
|
||||
let selectionContainsOnlyWhitespace = true;
|
||||
let _tab = '\t'.charCodeAt(0);
|
||||
let _space = ' '.charCodeAt(0);
|
||||
|
||||
for (let lineNumber = selection.startLineNumber; lineNumber <= selection.endLineNumber; lineNumber++) {
|
||||
let lineText = cursor.model.getLineContent(lineNumber);
|
||||
|
@ -1537,7 +1529,7 @@ export class OneCursorOp {
|
|||
let endIndex = (lineNumber === selection.endLineNumber ? selection.endColumn - 1 : lineText.length);
|
||||
for (let charIndex = startIndex; charIndex < endIndex; charIndex++) {
|
||||
let charCode = lineText.charCodeAt(charIndex);
|
||||
if (charCode !== _tab && charCode !== _space) {
|
||||
if (charCode !== CharCode.Tab && charCode !== CharCode.Space) {
|
||||
selectionContainsOnlyWhitespace = false;
|
||||
|
||||
// Break outer loop
|
||||
|
@ -2261,7 +2253,7 @@ class CursorHelper {
|
|||
return this.moveHelper.columnFromVisibleColumn(model, lineNumber, column);
|
||||
}
|
||||
|
||||
private _createWord(lineContent: string, wordType:WordType, start: number, end: number): IFindWordResult {
|
||||
private static _createWord(lineContent: string, wordType:WordType, start: number, end: number): IFindWordResult {
|
||||
// console.log('WORD ==> ' + start + ' => ' + end + ':::: <<<' + lineContent.substring(start, end) + '>>>');
|
||||
return { start: start, end: end, wordType: wordType };
|
||||
}
|
||||
|
@ -2270,48 +2262,52 @@ class CursorHelper {
|
|||
let position = this.model.validatePosition(_position);
|
||||
let wordSeparators = getMapForWordSeparators(this.configuration.editor.wordSeparators);
|
||||
let lineContent = this.model.getLineContent(position.lineNumber);
|
||||
let wordType = W_NONE;
|
||||
return CursorHelper._findPreviousWordOnLine(lineContent, wordSeparators, position);
|
||||
}
|
||||
|
||||
private static _findPreviousWordOnLine(lineContent:string, wordSeparators:WordCharacterClassifier, position:Position): IFindWordResult {
|
||||
let wordType = WordType.None;
|
||||
for (let chIndex = position.column - 2; chIndex >= 0; chIndex--) {
|
||||
let chCode = lineContent.charCodeAt(chIndex);
|
||||
let chClass:CharacterClass = (wordSeparators[chCode] || CharacterClass.Regular);
|
||||
let chClass = wordSeparators.get(chCode);
|
||||
|
||||
if (chClass === CH_REGULAR) {
|
||||
if (wordType === W_SEPARATOR) {
|
||||
return this._createWord(lineContent, wordType, chIndex + 1, this._findEndOfWord(lineContent, wordSeparators, wordType, chIndex + 1));
|
||||
if (chClass === CharacterClass.Regular) {
|
||||
if (wordType === WordType.Separator) {
|
||||
return CursorHelper._createWord(lineContent, wordType, chIndex + 1, CursorHelper._findEndOfWord(lineContent, wordSeparators, wordType, chIndex + 1));
|
||||
}
|
||||
wordType = W_REGULAR;
|
||||
} else if (chClass === CH_WORD_SEPARATOR) {
|
||||
if (wordType === W_REGULAR) {
|
||||
return this._createWord(lineContent, wordType, chIndex + 1, this._findEndOfWord(lineContent, wordSeparators, wordType, chIndex + 1));
|
||||
wordType = WordType.Regular;
|
||||
} else if (chClass === CharacterClass.WordSeparator) {
|
||||
if (wordType === WordType.Regular) {
|
||||
return CursorHelper._createWord(lineContent, wordType, chIndex + 1, CursorHelper._findEndOfWord(lineContent, wordSeparators, wordType, chIndex + 1));
|
||||
}
|
||||
wordType = W_SEPARATOR;
|
||||
} else if (chClass === CH_WHITESPACE) {
|
||||
if (wordType !== W_NONE) {
|
||||
return this._createWord(lineContent, wordType, chIndex + 1, this._findEndOfWord(lineContent, wordSeparators, wordType, chIndex + 1));
|
||||
wordType = WordType.Separator;
|
||||
} else if (chClass === CharacterClass.Whitespace) {
|
||||
if (wordType !== WordType.None) {
|
||||
return CursorHelper._createWord(lineContent, wordType, chIndex + 1, CursorHelper._findEndOfWord(lineContent, wordSeparators, wordType, chIndex + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wordType !== W_NONE) {
|
||||
return this._createWord(lineContent, wordType, 0, this._findEndOfWord(lineContent, wordSeparators, wordType, 0));
|
||||
if (wordType !== WordType.None) {
|
||||
return CursorHelper._createWord(lineContent, wordType, 0, CursorHelper._findEndOfWord(lineContent, wordSeparators, wordType, 0));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private _findEndOfWord(lineContent:string, wordSeparators:CharacterClass[], wordType:WordType, startIndex:number): number {
|
||||
private static _findEndOfWord(lineContent:string, wordSeparators:WordCharacterClassifier, wordType:WordType, startIndex:number): number {
|
||||
let len = lineContent.length;
|
||||
for (let chIndex = startIndex; chIndex < len; chIndex++) {
|
||||
let chCode = lineContent.charCodeAt(chIndex);
|
||||
let chClass:CharacterClass = (wordSeparators[chCode] || CharacterClass.Regular);
|
||||
let chClass = wordSeparators.get(chCode);
|
||||
|
||||
if (chClass === CH_WHITESPACE) {
|
||||
if (chClass === CharacterClass.Whitespace) {
|
||||
return chIndex;
|
||||
}
|
||||
if (wordType === W_REGULAR && chClass === CH_WORD_SEPARATOR) {
|
||||
if (wordType === WordType.Regular && chClass === CharacterClass.WordSeparator) {
|
||||
return chIndex;
|
||||
}
|
||||
if (wordType === W_SEPARATOR && chClass === CH_REGULAR) {
|
||||
if (wordType === WordType.Separator && chClass === CharacterClass.Regular) {
|
||||
return chIndex;
|
||||
}
|
||||
}
|
||||
|
@ -2322,49 +2318,53 @@ class CursorHelper {
|
|||
let position = this.model.validatePosition(_position);
|
||||
let wordSeparators = getMapForWordSeparators(this.configuration.editor.wordSeparators);
|
||||
let lineContent = this.model.getLineContent(position.lineNumber);
|
||||
let wordType = W_NONE;
|
||||
return CursorHelper._findNextWordOnLine(lineContent, wordSeparators, position);
|
||||
}
|
||||
|
||||
private static _findNextWordOnLine(lineContent:string, wordSeparators:WordCharacterClassifier, position:Position): IFindWordResult {
|
||||
let wordType = WordType.None;
|
||||
let len = lineContent.length;
|
||||
|
||||
for (let chIndex = position.column - 1; chIndex < len; chIndex++) {
|
||||
let chCode = lineContent.charCodeAt(chIndex);
|
||||
let chClass:CharacterClass = (wordSeparators[chCode] || CharacterClass.Regular);
|
||||
let chClass = wordSeparators.get(chCode);
|
||||
|
||||
if (chClass === CH_REGULAR) {
|
||||
if (wordType === W_SEPARATOR) {
|
||||
return this._createWord(lineContent, wordType, this._findStartOfWord(lineContent, wordSeparators, wordType, chIndex - 1), chIndex);
|
||||
if (chClass === CharacterClass.Regular) {
|
||||
if (wordType === WordType.Separator) {
|
||||
return CursorHelper._createWord(lineContent, wordType, CursorHelper._findStartOfWord(lineContent, wordSeparators, wordType, chIndex - 1), chIndex);
|
||||
}
|
||||
wordType = W_REGULAR;
|
||||
} else if (chClass === CH_WORD_SEPARATOR) {
|
||||
if (wordType === W_REGULAR) {
|
||||
return this._createWord(lineContent, wordType, this._findStartOfWord(lineContent, wordSeparators, wordType, chIndex - 1), chIndex);
|
||||
wordType = WordType.Regular;
|
||||
} else if (chClass === CharacterClass.WordSeparator) {
|
||||
if (wordType === WordType.Regular) {
|
||||
return CursorHelper._createWord(lineContent, wordType, CursorHelper._findStartOfWord(lineContent, wordSeparators, wordType, chIndex - 1), chIndex);
|
||||
}
|
||||
wordType = W_SEPARATOR;
|
||||
} else if (chClass === CH_WHITESPACE) {
|
||||
if (wordType !== W_NONE) {
|
||||
return this._createWord(lineContent, wordType, this._findStartOfWord(lineContent, wordSeparators, wordType, chIndex - 1), chIndex);
|
||||
wordType = WordType.Separator;
|
||||
} else if (chClass === CharacterClass.Whitespace) {
|
||||
if (wordType !== WordType.None) {
|
||||
return CursorHelper._createWord(lineContent, wordType, CursorHelper._findStartOfWord(lineContent, wordSeparators, wordType, chIndex - 1), chIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wordType !== W_NONE) {
|
||||
return this._createWord(lineContent, wordType, this._findStartOfWord(lineContent, wordSeparators, wordType, len - 1), len);
|
||||
if (wordType !== WordType.None) {
|
||||
return CursorHelper._createWord(lineContent, wordType, CursorHelper._findStartOfWord(lineContent, wordSeparators, wordType, len - 1), len);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private _findStartOfWord(lineContent:string, wordSeparators:CharacterClass[], wordType:WordType, startIndex:number): number {
|
||||
private static _findStartOfWord(lineContent:string, wordSeparators:WordCharacterClassifier, wordType:WordType, startIndex:number): number {
|
||||
for (let chIndex = startIndex; chIndex >= 0; chIndex--) {
|
||||
let chCode = lineContent.charCodeAt(chIndex);
|
||||
let chClass:CharacterClass = (wordSeparators[chCode] || CharacterClass.Regular);
|
||||
let chClass = wordSeparators.get(chCode);
|
||||
|
||||
if (chClass === CH_WHITESPACE) {
|
||||
if (chClass === CharacterClass.Whitespace) {
|
||||
return chIndex + 1;
|
||||
}
|
||||
if (wordType === W_REGULAR && chClass === CH_WORD_SEPARATOR) {
|
||||
if (wordType === WordType.Regular && chClass === CharacterClass.WordSeparator) {
|
||||
return chIndex + 1;
|
||||
}
|
||||
if (wordType === W_SEPARATOR && chClass === CH_REGULAR) {
|
||||
if (wordType === WordType.Separator && chClass === CharacterClass.Regular) {
|
||||
return chIndex + 1;
|
||||
}
|
||||
}
|
||||
|
@ -2372,37 +2372,33 @@ class CursorHelper {
|
|||
}
|
||||
}
|
||||
|
||||
function once<T, R>(keyFn:(input:T)=>string, computeFn:(input:T)=>R):(input:T)=>R {
|
||||
let cache: {[key:string]:R;} = {};
|
||||
return (input:T):R => {
|
||||
let key = keyFn(input);
|
||||
if (!cache.hasOwnProperty(key)) {
|
||||
cache[key] = computeFn(input);
|
||||
class WordCharacterClassifier extends CharacterClassifier<CharacterClass> {
|
||||
|
||||
constructor(wordSeparators:string) {
|
||||
super(CharacterClass.Regular);
|
||||
|
||||
for (let i = 0, len = wordSeparators.length; i < len; i++) {
|
||||
this.set(wordSeparators.charCodeAt(i), CharacterClass.WordSeparator);
|
||||
}
|
||||
return cache[key];
|
||||
|
||||
this.set(CharCode.Space, CharacterClass.Whitespace);
|
||||
this.set(CharCode.Tab, CharacterClass.Whitespace);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function once<R>(computeFn:(input:string)=>R):(input:string)=>R {
|
||||
let cache: {[key:string]:R;} = {}; // TODO@Alex unbounded cache
|
||||
return (input:string):R => {
|
||||
if (!cache.hasOwnProperty(input)) {
|
||||
cache[input] = computeFn(input);
|
||||
}
|
||||
return cache[input];
|
||||
};
|
||||
}
|
||||
|
||||
let getMapForWordSeparators = once<string,CharacterClass[]>(
|
||||
(input) => input,
|
||||
(input) => {
|
||||
|
||||
let r:CharacterClass[] = [];
|
||||
|
||||
// Make array fast for ASCII text
|
||||
for (let chCode = 0; chCode < 256; chCode++) {
|
||||
r[chCode] = CharacterClass.Regular;
|
||||
}
|
||||
|
||||
for (let i = 0, len = input.length; i < len; i++) {
|
||||
r[input.charCodeAt(i)] = CharacterClass.WordSeparator;
|
||||
}
|
||||
|
||||
r[' '.charCodeAt(0)] = CharacterClass.Whitespace;
|
||||
r['\t'.charCodeAt(0)] = CharacterClass.Whitespace;
|
||||
|
||||
return r;
|
||||
}
|
||||
let getMapForWordSeparators = once<WordCharacterClassifier>(
|
||||
(input) => new WordCharacterClassifier(input)
|
||||
);
|
||||
|
||||
class Utils {
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
import {RunOnceScheduler} from 'vs/base/common/async';
|
||||
import Event, {Emitter} from 'vs/base/common/event';
|
||||
import {CommonKeybindings} from 'vs/base/common/keyCodes';
|
||||
import {KeyCode} from 'vs/base/common/keyCodes';
|
||||
import {Disposable} from 'vs/base/common/lifecycle';
|
||||
import {IClipboardEvent, ICompositionEvent, IKeyboardEventWrapper, ISimpleModel, ITextAreaWrapper, ITypeData, TextAreaState, TextAreaStrategy, createTextAreaState} from 'vs/editor/common/controller/textAreaState';
|
||||
import {Range} from 'vs/editor/common/core/range';
|
||||
import {EndOfLinePreference} from 'vs/editor/common/editorCommon';
|
||||
|
||||
enum ReadFromTextArea {
|
||||
const enum ReadFromTextArea {
|
||||
Type,
|
||||
Paste
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ export class TextAreaHandler extends Disposable {
|
|||
}
|
||||
|
||||
private _onKeyDownHandler(e:IKeyboardEventWrapper): void {
|
||||
if (e.equals(CommonKeybindings.ESCAPE)) {
|
||||
if (e.equals(KeyCode.Escape)) {
|
||||
// Prevent default always for `Esc`, otherwise it will generate a keypress
|
||||
// See https://msdn.microsoft.com/en-us/library/ie/ms536939(v=vs.85).aspx
|
||||
e.preventDefault();
|
||||
|
|
52
src/vs/editor/common/core/characterClassifier.ts
Normal file
52
src/vs/editor/common/core/characterClassifier.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* A fast character classifier that uses a compact array for ASCII values.
|
||||
*/
|
||||
export class CharacterClassifier<T> {
|
||||
/**
|
||||
* Maintain a compact (fully initialized ASCII map for quickly classifying ASCII characters - used more often in code).
|
||||
*/
|
||||
private _asciiMap: T[];
|
||||
|
||||
/**
|
||||
* The entire map (sparse array).
|
||||
*/
|
||||
private _map: T[];
|
||||
|
||||
private _defaultValue: T;
|
||||
|
||||
constructor(defaultValue:T) {
|
||||
this._defaultValue = defaultValue;
|
||||
this._asciiMap = CharacterClassifier._createAsciiMap(defaultValue);
|
||||
this._map = [];
|
||||
}
|
||||
|
||||
private static _createAsciiMap<T>(defaultValue:T): T[] {
|
||||
let asciiMap:T[] = [];
|
||||
for (let i = 0; i < 256; i++) {
|
||||
asciiMap[i] = defaultValue;
|
||||
}
|
||||
return asciiMap;
|
||||
}
|
||||
|
||||
public set(charCode:number, value:T): void {
|
||||
if (charCode >= 0 && charCode < 256) {
|
||||
this._asciiMap[charCode] = value;
|
||||
} else {
|
||||
this._map[charCode] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public get(charCode:number): T {
|
||||
if (charCode >= 0 && charCode < 256) {
|
||||
return this._asciiMap[charCode];
|
||||
} else {
|
||||
return this._map[charCode] || this._defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -430,10 +430,10 @@ export interface IEditorOptions {
|
|||
*/
|
||||
folding?: boolean;
|
||||
/**
|
||||
* Enable rendering of leading whitespace.
|
||||
* Defaults to false.
|
||||
* Enable rendering of whitespace.
|
||||
* Defaults to none.
|
||||
*/
|
||||
renderWhitespace?: boolean;
|
||||
renderWhitespace?: 'none' | 'boundary' | 'all';
|
||||
/**
|
||||
* Enable rendering of control characters.
|
||||
* Defaults to false.
|
||||
|
@ -644,7 +644,7 @@ export class InternalEditorViewOptions {
|
|||
scrollBeyondLastLine:boolean;
|
||||
editorClassName: string;
|
||||
stopRenderingLineAfter: number;
|
||||
renderWhitespace: boolean;
|
||||
renderWhitespace: 'none' | 'boundary' | 'all';
|
||||
renderControlCharacters: boolean;
|
||||
renderIndentGuides: boolean;
|
||||
renderLineHighlight: boolean;
|
||||
|
@ -672,7 +672,7 @@ export class InternalEditorViewOptions {
|
|||
scrollBeyondLastLine:boolean;
|
||||
editorClassName: string;
|
||||
stopRenderingLineAfter: number;
|
||||
renderWhitespace: boolean;
|
||||
renderWhitespace: 'none' | 'boundary' | 'all';
|
||||
renderControlCharacters: boolean;
|
||||
renderIndentGuides: boolean;
|
||||
renderLineHighlight: boolean;
|
||||
|
@ -696,7 +696,7 @@ export class InternalEditorViewOptions {
|
|||
this.scrollBeyondLastLine = Boolean(source.scrollBeyondLastLine);
|
||||
this.editorClassName = String(source.editorClassName);
|
||||
this.stopRenderingLineAfter = source.stopRenderingLineAfter|0;
|
||||
this.renderWhitespace = Boolean(source.renderWhitespace);
|
||||
this.renderWhitespace = source.renderWhitespace;
|
||||
this.renderControlCharacters = Boolean(source.renderControlCharacters);
|
||||
this.renderIndentGuides = Boolean(source.renderIndentGuides);
|
||||
this.renderLineHighlight = Boolean(source.renderLineHighlight);
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
const __space = ' '.charCodeAt(0);
|
||||
const __tab = '\t'.charCodeAt(0);
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
|
||||
/**
|
||||
* Compute the diff in spaces between two line's indentation.
|
||||
|
@ -31,7 +30,7 @@ function spacesDiff(a:string, aLength:number, b:string, bLength:number): number
|
|||
let aSpacesCnt = 0, aTabsCount = 0;
|
||||
for (let j = i; j < aLength; j++) {
|
||||
let aCharCode = a.charCodeAt(j);
|
||||
if (aCharCode === __space) {
|
||||
if (aCharCode === CharCode.Space) {
|
||||
aSpacesCnt++;
|
||||
} else {
|
||||
aTabsCount++;
|
||||
|
@ -41,7 +40,7 @@ function spacesDiff(a:string, aLength:number, b:string, bLength:number): number
|
|||
let bSpacesCnt = 0, bTabsCount = 0;
|
||||
for (let j = i; j < bLength; j++) {
|
||||
let bCharCode = b.charCodeAt(j);
|
||||
if (bCharCode === __space) {
|
||||
if (bCharCode === CharCode.Space) {
|
||||
bSpacesCnt++;
|
||||
} else {
|
||||
bTabsCount++;
|
||||
|
@ -103,9 +102,9 @@ export function guessIndentation(lines:string[], defaultTabSize:number, defaultI
|
|||
for (let j = 0, lenJ = currentLineText.length; j < lenJ; j++) {
|
||||
let charCode = currentLineText.charCodeAt(j);
|
||||
|
||||
if (charCode === __tab) {
|
||||
if (charCode === CharCode.Tab) {
|
||||
currentLineTabsCount++;
|
||||
} else if (charCode === __space) {
|
||||
} else if (charCode === CharCode.Space) {
|
||||
currentLineSpacesCount++;
|
||||
} else {
|
||||
// Hit non whitespace character on this line
|
||||
|
|
|
@ -7,15 +7,11 @@
|
|||
import * as strings from 'vs/base/common/strings';
|
||||
import {ILineTokens, IReadOnlyLineMarker} from 'vs/editor/common/editorCommon';
|
||||
import {IState} from 'vs/editor/common/modes';
|
||||
import {TokensBinaryEncoding, TokensInflatorMap} from 'vs/editor/common/model/tokensBinaryEncoding';
|
||||
import {TokensBinaryEncoding, TokensBinaryEncodingValues, TokensInflatorMap} from 'vs/editor/common/model/tokensBinaryEncoding';
|
||||
import {ModeTransition} from 'vs/editor/common/core/modeTransition';
|
||||
import {Token} from 'vs/editor/common/core/token';
|
||||
import {ViewLineToken} from 'vs/editor/common/core/viewLineToken';
|
||||
|
||||
const START_INDEX_MASK = TokensBinaryEncoding.START_INDEX_MASK;
|
||||
const TYPE_MASK = TokensBinaryEncoding.TYPE_MASK;
|
||||
const START_INDEX_OFFSET = TokensBinaryEncoding.START_INDEX_OFFSET;
|
||||
const TYPE_OFFSET = TokensBinaryEncoding.TYPE_OFFSET;
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
|
||||
export interface ILineEdit {
|
||||
startColumn: number;
|
||||
|
@ -65,7 +61,7 @@ var NO_OP_MARKERS_ADJUSTER: IMarkersAdjuster = {
|
|||
finish: () => {}
|
||||
};
|
||||
|
||||
enum MarkerMoveSemantics {
|
||||
const enum MarkerMoveSemantics {
|
||||
MarkerDefined = 0,
|
||||
ForceMove = 1,
|
||||
ForceStay = 2
|
||||
|
@ -83,9 +79,9 @@ function computePlusOneIndentLevel(line: string, tabSize: number): number {
|
|||
|
||||
while (i < len) {
|
||||
let chCode = line.charCodeAt(i);
|
||||
if (chCode === 32 /*space*/) {
|
||||
if (chCode === CharCode.Space) {
|
||||
indent++;
|
||||
} else if (chCode === 9 /*\t*/) {
|
||||
} else if (chCode === CharCode.Tab) {
|
||||
indent = indent - indent % tabSize + tabSize;
|
||||
} else {
|
||||
break;
|
||||
|
@ -232,14 +228,14 @@ export class ModelLine {
|
|||
|
||||
if (currentTokenStartIndex > 0 && delta !== 0) {
|
||||
// adjust token's `startIndex` by `delta`
|
||||
let deflatedType = (tokens[tokensIndex] / TYPE_OFFSET) & TYPE_MASK;
|
||||
let deflatedType = (tokens[tokensIndex] / TokensBinaryEncodingValues.TYPE_OFFSET) & TokensBinaryEncodingValues.TYPE_MASK;
|
||||
let newStartIndex = Math.max(minimumAllowedIndex, currentTokenStartIndex + delta);
|
||||
let newToken = deflatedType * TYPE_OFFSET + newStartIndex * START_INDEX_OFFSET;
|
||||
let newToken = deflatedType * TokensBinaryEncodingValues.TYPE_OFFSET + newStartIndex * TokensBinaryEncodingValues.START_INDEX_OFFSET;
|
||||
|
||||
if (delta < 0) {
|
||||
// pop all previous tokens that have become `collapsed`
|
||||
while (tokensIndex > 0) {
|
||||
let prevTokenStartIndex = (tokens[tokensIndex - 1] / START_INDEX_OFFSET) & START_INDEX_MASK;
|
||||
let prevTokenStartIndex = (tokens[tokensIndex - 1] / TokensBinaryEncodingValues.START_INDEX_OFFSET) & TokensBinaryEncodingValues.START_INDEX_MASK;
|
||||
if (prevTokenStartIndex >= newStartIndex) {
|
||||
// Token at `tokensIndex` - 1 is now `collapsed` => pop it
|
||||
tokens.splice(tokensIndex - 1, 1);
|
||||
|
@ -256,7 +252,7 @@ export class ModelLine {
|
|||
tokensIndex++;
|
||||
|
||||
if (tokensIndex < tokensLength) {
|
||||
currentTokenStartIndex = (tokens[tokensIndex] / START_INDEX_OFFSET) & START_INDEX_MASK;
|
||||
currentTokenStartIndex = (tokens[tokensIndex] / TokensBinaryEncodingValues.START_INDEX_OFFSET) & TokensBinaryEncodingValues.START_INDEX_MASK;
|
||||
}
|
||||
}
|
||||
// console.log('after call: tokensIndex: ' + tokensIndex + ': ' + String(this.getTokens()));
|
||||
|
@ -287,7 +283,7 @@ export class ModelLine {
|
|||
|
||||
// Remove overflowing tokens
|
||||
while (tokens.length > 0) {
|
||||
let lastTokenStartIndex = (tokens[tokens.length - 1] / START_INDEX_OFFSET) & START_INDEX_MASK;
|
||||
let lastTokenStartIndex = (tokens[tokens.length - 1] / TokensBinaryEncodingValues.START_INDEX_OFFSET) & TokensBinaryEncodingValues.START_INDEX_MASK;
|
||||
if (lastTokenStartIndex < lineTextLength) {
|
||||
// Valid token
|
||||
break;
|
||||
|
@ -533,10 +529,10 @@ export class ModelLine {
|
|||
for (let i = 0, len = otherTokens.length; i < len; i++) {
|
||||
let token = otherTokens[i];
|
||||
|
||||
let deflatedStartIndex = (token / START_INDEX_OFFSET) & START_INDEX_MASK;
|
||||
let deflatedType = (token / TYPE_OFFSET) & TYPE_MASK;
|
||||
let deflatedStartIndex = (token / TokensBinaryEncodingValues.START_INDEX_OFFSET) & TokensBinaryEncodingValues.START_INDEX_MASK;
|
||||
let deflatedType = (token / TokensBinaryEncodingValues.TYPE_OFFSET) & TokensBinaryEncodingValues.TYPE_MASK;
|
||||
let newStartIndex = deflatedStartIndex + thisTextLength;
|
||||
let newToken = deflatedType * TYPE_OFFSET + newStartIndex * START_INDEX_OFFSET;
|
||||
let newToken = deflatedType * TokensBinaryEncodingValues.TYPE_OFFSET + newStartIndex * TokensBinaryEncodingValues.START_INDEX_OFFSET;
|
||||
|
||||
otherTokens[i] = newToken;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import {guessIndentation} from 'vs/editor/common/model/indentationGuesser';
|
|||
import {DEFAULT_INDENTATION, DEFAULT_TRIM_AUTO_WHITESPACE} from 'vs/editor/common/config/defaultConfig';
|
||||
import {PrefixSumComputer} from 'vs/editor/common/viewModel/prefixSumComputer';
|
||||
import {IndentRange, computeRanges} from 'vs/editor/common/model/indentRanges';
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
|
||||
const LIMIT_FIND_COUNT = 999;
|
||||
export const LONG_LINE_BOUNDARY = 1000;
|
||||
|
@ -728,10 +729,6 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo
|
|||
}
|
||||
|
||||
private static _isMultiline(searchString:string): boolean {
|
||||
const BACKSLASH_CHAR_CODE = '\\'.charCodeAt(0);
|
||||
const n_CHAR_CODE = 'n'.charCodeAt(0);
|
||||
const r_CHAR_CODE = 'r'.charCodeAt(0);
|
||||
|
||||
if (!searchString || searchString.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -739,7 +736,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo
|
|||
for (let i = 0, len = searchString.length; i < len; i++) {
|
||||
let chCode = searchString.charCodeAt(i);
|
||||
|
||||
if (chCode === BACKSLASH_CHAR_CODE) {
|
||||
if (chCode === CharCode.Backslash) {
|
||||
|
||||
// move to next char
|
||||
i++;
|
||||
|
@ -750,7 +747,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo
|
|||
}
|
||||
|
||||
let nextChCode = searchString.charCodeAt(i);
|
||||
if (nextChCode === n_CHAR_CODE || nextChCode === r_CHAR_CODE) {
|
||||
if (nextChCode === CharCode.n || nextChCode === CharCode.r) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,10 +9,12 @@ import * as strings from 'vs/base/common/strings';
|
|||
import {ViewLineToken} from 'vs/editor/common/core/viewLineToken';
|
||||
import {Token} from 'vs/editor/common/core/token';
|
||||
|
||||
const START_INDEX_MASK = 0xffffffff;
|
||||
const TYPE_MASK = 0xffff;
|
||||
const START_INDEX_OFFSET = 1;
|
||||
const TYPE_OFFSET = Math.pow(2, 32);
|
||||
export const enum TokensBinaryEncodingValues {
|
||||
START_INDEX_MASK = 0xffffffff,
|
||||
TYPE_MASK = 0xffff,
|
||||
START_INDEX_OFFSET = 1,
|
||||
TYPE_OFFSET = 4294967296 // Math.pow(2, 32)
|
||||
}
|
||||
|
||||
const DEFAULT_VIEW_TOKEN = new ViewLineToken(0, '');
|
||||
const INFLATED_TOKENS_EMPTY_TEXT:ViewLineToken[] = [];
|
||||
|
@ -35,10 +37,6 @@ export class TokensInflatorMap {
|
|||
}
|
||||
|
||||
export class TokensBinaryEncoding {
|
||||
public static START_INDEX_MASK = START_INDEX_MASK;
|
||||
public static TYPE_MASK = TYPE_MASK;
|
||||
public static START_INDEX_OFFSET = START_INDEX_OFFSET;
|
||||
public static TYPE_OFFSET = TYPE_OFFSET;
|
||||
|
||||
public static deflateArr(map:TokensInflatorMap, tokens:Token[]): number[] {
|
||||
if (tokens.length === 0) {
|
||||
|
@ -90,7 +88,7 @@ export class TokensBinaryEncoding {
|
|||
// 16 bits for token => up to 2^16 = 65,536
|
||||
|
||||
// [token][startIndex]
|
||||
deflated = deflatedToken * TYPE_OFFSET + token.startIndex * START_INDEX_OFFSET;
|
||||
deflated = deflatedToken * TokensBinaryEncodingValues.TYPE_OFFSET + token.startIndex * TokensBinaryEncodingValues.START_INDEX_OFFSET;
|
||||
|
||||
result[i] = deflated;
|
||||
|
||||
|
@ -101,11 +99,11 @@ export class TokensBinaryEncoding {
|
|||
}
|
||||
|
||||
public static getStartIndex(binaryEncodedToken:number): number {
|
||||
return (binaryEncodedToken / START_INDEX_OFFSET) & START_INDEX_MASK;
|
||||
return (binaryEncodedToken / TokensBinaryEncodingValues.START_INDEX_OFFSET) & TokensBinaryEncodingValues.START_INDEX_MASK;
|
||||
}
|
||||
|
||||
public static getType(map:TokensInflatorMap, binaryEncodedToken:number): string {
|
||||
var deflatedType = (binaryEncodedToken / TYPE_OFFSET) & TYPE_MASK;
|
||||
var deflatedType = (binaryEncodedToken / TokensBinaryEncodingValues.TYPE_OFFSET) & TokensBinaryEncodingValues.TYPE_MASK;
|
||||
if (deflatedType === 0) {
|
||||
return strings.empty;
|
||||
}
|
||||
|
@ -126,8 +124,8 @@ export class TokensBinaryEncoding {
|
|||
for (let i = 0, len = binaryEncodedTokens.length; i < len; i++) {
|
||||
let deflated = binaryEncodedTokens[i];
|
||||
|
||||
let startIndex = (deflated / START_INDEX_OFFSET) & START_INDEX_MASK;
|
||||
let deflatedType = (deflated / TYPE_OFFSET) & TYPE_MASK;
|
||||
let startIndex = (deflated / TokensBinaryEncodingValues.START_INDEX_OFFSET) & TokensBinaryEncodingValues.START_INDEX_MASK;
|
||||
let deflatedType = (deflated / TokensBinaryEncodingValues.TYPE_OFFSET) & TokensBinaryEncodingValues.TYPE_MASK;
|
||||
|
||||
result.push(new ViewLineToken(startIndex, inflateMap[deflatedType]));
|
||||
}
|
||||
|
@ -152,19 +150,19 @@ export class TokensBinaryEncoding {
|
|||
const inflateMap = map._inflate;
|
||||
|
||||
let originalToken = binaryEncodedTokens[startIndex];
|
||||
let deflatedType = (originalToken / TYPE_OFFSET) & TYPE_MASK;
|
||||
let deflatedType = (originalToken / TokensBinaryEncodingValues.TYPE_OFFSET) & TokensBinaryEncodingValues.TYPE_MASK;
|
||||
let newStartIndex = 0;
|
||||
result.push(new ViewLineToken(newStartIndex, inflateMap[deflatedType]));
|
||||
|
||||
for (let i = startIndex + 1, len = binaryEncodedTokens.length; i < len; i++) {
|
||||
originalToken = binaryEncodedTokens[i];
|
||||
let originalStartIndex = (originalToken / START_INDEX_OFFSET) & START_INDEX_MASK;
|
||||
let originalStartIndex = (originalToken / TokensBinaryEncodingValues.START_INDEX_OFFSET) & TokensBinaryEncodingValues.START_INDEX_MASK;
|
||||
|
||||
if (originalStartIndex >= endOffset) {
|
||||
break;
|
||||
}
|
||||
|
||||
deflatedType = (originalToken / TYPE_OFFSET) & TYPE_MASK;
|
||||
deflatedType = (originalToken / TokensBinaryEncodingValues.TYPE_OFFSET) & TokensBinaryEncodingValues.TYPE_MASK;
|
||||
newStartIndex = originalStartIndex - startOffset + deltaStartIndex;
|
||||
result.push(new ViewLineToken(newStartIndex, inflateMap[deflatedType]));
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import {TextualSuggestSupport} from 'vs/editor/common/modes/supports/suggestSupp
|
|||
import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService';
|
||||
import * as wordHelper from 'vs/editor/common/model/wordHelper';
|
||||
import {ICompatWorkerService, ICompatMode} from 'vs/editor/common/services/compatWorkerService';
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
|
||||
export function createWordRegExp(allowInWords:string = ''): RegExp {
|
||||
return wordHelper.createWordRegExp(allowInWords);
|
||||
|
@ -105,7 +106,7 @@ export abstract class AbstractMode implements modes.IMode {
|
|||
}
|
||||
|
||||
public setTokenizationSupport<T>(callback:(mode:modes.IMode) => T) : IDisposable {
|
||||
var supportImpl = callback(this);
|
||||
let supportImpl = callback(this);
|
||||
this['tokenizationSupport'] = supportImpl;
|
||||
this._eventEmitter.emit('modeSupportChanged', _createModeSupportChangedEvent());
|
||||
|
||||
|
@ -170,69 +171,43 @@ class SimplifiedMode implements modes.IMode {
|
|||
}
|
||||
}
|
||||
|
||||
export var isDigit:(character:string, base:number)=>boolean = (function () {
|
||||
|
||||
var _0 = '0'.charCodeAt(0),
|
||||
_1 = '1'.charCodeAt(0),
|
||||
_2 = '2'.charCodeAt(0),
|
||||
_3 = '3'.charCodeAt(0),
|
||||
_4 = '4'.charCodeAt(0),
|
||||
_5 = '5'.charCodeAt(0),
|
||||
_6 = '6'.charCodeAt(0),
|
||||
_7 = '7'.charCodeAt(0),
|
||||
_8 = '8'.charCodeAt(0),
|
||||
_9 = '9'.charCodeAt(0),
|
||||
_a = 'a'.charCodeAt(0),
|
||||
_b = 'b'.charCodeAt(0),
|
||||
_c = 'c'.charCodeAt(0),
|
||||
_d = 'd'.charCodeAt(0),
|
||||
_e = 'e'.charCodeAt(0),
|
||||
_f = 'f'.charCodeAt(0),
|
||||
_A = 'A'.charCodeAt(0),
|
||||
_B = 'B'.charCodeAt(0),
|
||||
_C = 'C'.charCodeAt(0),
|
||||
_D = 'D'.charCodeAt(0),
|
||||
_E = 'E'.charCodeAt(0),
|
||||
_F = 'F'.charCodeAt(0);
|
||||
|
||||
return function isDigit(character:string, base:number):boolean {
|
||||
var c = character.charCodeAt(0);
|
||||
switch (base) {
|
||||
case 1:
|
||||
return c === _0;
|
||||
case 2:
|
||||
return c >= _0 && c <= _1;
|
||||
case 3:
|
||||
return c >= _0 && c <= _2;
|
||||
case 4:
|
||||
return c >= _0 && c <= _3;
|
||||
case 5:
|
||||
return c >= _0 && c <= _4;
|
||||
case 6:
|
||||
return c >= _0 && c <= _5;
|
||||
case 7:
|
||||
return c >= _0 && c <= _6;
|
||||
case 8:
|
||||
return c >= _0 && c <= _7;
|
||||
case 9:
|
||||
return c >= _0 && c <= _8;
|
||||
case 10:
|
||||
return c >= _0 && c <= _9;
|
||||
case 11:
|
||||
return (c >= _0 && c <= _9) || (c === _a) || (c === _A);
|
||||
case 12:
|
||||
return (c >= _0 && c <= _9) || (c >= _a && c <= _b) || (c >= _A && c <= _B);
|
||||
case 13:
|
||||
return (c >= _0 && c <= _9) || (c >= _a && c <= _c) || (c >= _A && c <= _C);
|
||||
case 14:
|
||||
return (c >= _0 && c <= _9) || (c >= _a && c <= _d) || (c >= _A && c <= _D);
|
||||
case 15:
|
||||
return (c >= _0 && c <= _9) || (c >= _a && c <= _e) || (c >= _A && c <= _E);
|
||||
default:
|
||||
return (c >= _0 && c <= _9) || (c >= _a && c <= _f) || (c >= _A && c <= _F);
|
||||
}
|
||||
};
|
||||
})();
|
||||
export function isDigit(character:string, base:number): boolean {
|
||||
let c = character.charCodeAt(0);
|
||||
switch (base) {
|
||||
case 1:
|
||||
return c === CharCode.Digit0;
|
||||
case 2:
|
||||
return c >= CharCode.Digit0 && c <= CharCode.Digit1;
|
||||
case 3:
|
||||
return c >= CharCode.Digit0 && c <= CharCode.Digit2;
|
||||
case 4:
|
||||
return c >= CharCode.Digit0 && c <= CharCode.Digit3;
|
||||
case 5:
|
||||
return c >= CharCode.Digit0 && c <= CharCode.Digit4;
|
||||
case 6:
|
||||
return c >= CharCode.Digit0 && c <= CharCode.Digit5;
|
||||
case 7:
|
||||
return c >= CharCode.Digit0 && c <= CharCode.Digit6;
|
||||
case 8:
|
||||
return c >= CharCode.Digit0 && c <= CharCode.Digit7;
|
||||
case 9:
|
||||
return c >= CharCode.Digit0 && c <= CharCode.Digit8;
|
||||
case 10:
|
||||
return c >= CharCode.Digit0 && c <= CharCode.Digit9;
|
||||
case 11:
|
||||
return (c >= CharCode.Digit0 && c <= CharCode.Digit9) || (c === CharCode.a) || (c === CharCode.A);
|
||||
case 12:
|
||||
return (c >= CharCode.Digit0 && c <= CharCode.Digit9) || (c >= CharCode.a && c <= CharCode.b) || (c >= CharCode.A && c <= CharCode.B);
|
||||
case 13:
|
||||
return (c >= CharCode.Digit0 && c <= CharCode.Digit9) || (c >= CharCode.a && c <= CharCode.c) || (c >= CharCode.A && c <= CharCode.C);
|
||||
case 14:
|
||||
return (c >= CharCode.Digit0 && c <= CharCode.Digit9) || (c >= CharCode.a && c <= CharCode.d) || (c >= CharCode.A && c <= CharCode.D);
|
||||
case 15:
|
||||
return (c >= CharCode.Digit0 && c <= CharCode.Digit9) || (c >= CharCode.a && c <= CharCode.e) || (c >= CharCode.A && c <= CharCode.E);
|
||||
default:
|
||||
return (c >= CharCode.Digit0 && c <= CharCode.Digit9) || (c >= CharCode.a && c <= CharCode.f) || (c >= CharCode.A && c <= CharCode.F);
|
||||
}
|
||||
}
|
||||
|
||||
export class FrankensteinMode extends AbstractMode {
|
||||
|
||||
|
|
|
@ -5,53 +5,55 @@
|
|||
'use strict';
|
||||
|
||||
import {IStream} from 'vs/editor/common/modes';
|
||||
import {CharacterClassifier} from 'vs/editor/common/core/characterClassifier';
|
||||
|
||||
class CharacterSet {
|
||||
|
||||
private static _CACHE:{ [key:string]:CharacterSet; } = {}; // TODO@Alex unbounded cache
|
||||
|
||||
public static getOrCreate(source:string): CharacterSet {
|
||||
if (!CharacterSet._CACHE.hasOwnProperty(source)) {
|
||||
CharacterSet._CACHE[source] = new CharacterSet(source);
|
||||
}
|
||||
return CharacterSet._CACHE[source];
|
||||
}
|
||||
|
||||
private _classifier: CharacterClassifier<boolean>;
|
||||
|
||||
constructor(source:string) {
|
||||
this._classifier = new CharacterClassifier<boolean>(false);
|
||||
for (let i = 0, len = source.length; i < len; i++) {
|
||||
this._classifier.set(source.charCodeAt(i), true);
|
||||
}
|
||||
}
|
||||
|
||||
public contains(charCode:number): boolean {
|
||||
return this._classifier.get(charCode);
|
||||
}
|
||||
}
|
||||
|
||||
export class LineStream implements IStream {
|
||||
|
||||
static STRING_TO_ARRAY_CACHE:{ [key:string]:boolean[]; } = {};
|
||||
|
||||
/*protected*/ _source:string;
|
||||
private sourceLength:number;
|
||||
/*protected*/ _pos:number;
|
||||
private whitespace:string;
|
||||
private whitespaceArr:boolean[];
|
||||
private separators:string;
|
||||
private separatorsArr:boolean[];
|
||||
private tokenStart:number;
|
||||
private tokenEnd:number;
|
||||
private _source:string;
|
||||
private _sourceLength:number;
|
||||
private _pos:number;
|
||||
private _whitespace:string;
|
||||
private _whitespaceArr:CharacterSet;
|
||||
private _separators:string;
|
||||
private _separatorsArr:CharacterSet;
|
||||
private _tokenStart:number;
|
||||
private _tokenEnd:number;
|
||||
|
||||
constructor(source:string) {
|
||||
this._source = source;
|
||||
this.sourceLength = source.length;
|
||||
this._sourceLength = source.length;
|
||||
this._pos = 0;
|
||||
this.whitespace = '\t \u00a0';
|
||||
this.whitespaceArr = this.stringToArray(this.whitespace);
|
||||
this.separators = '';
|
||||
this.separatorsArr = this.stringToArray(this.separators);
|
||||
this.tokenStart = -1;
|
||||
this.tokenEnd = -1;
|
||||
}
|
||||
|
||||
private stringToArray(str:string):boolean[] {
|
||||
if (!LineStream.STRING_TO_ARRAY_CACHE.hasOwnProperty(str)) {
|
||||
LineStream.STRING_TO_ARRAY_CACHE[str] = this.actualStringToArray(str);
|
||||
}
|
||||
return LineStream.STRING_TO_ARRAY_CACHE[str];
|
||||
}
|
||||
|
||||
private actualStringToArray(str:string):boolean[] {
|
||||
let maxCharCode = 0;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
maxCharCode = Math.max(maxCharCode, str.charCodeAt(i));
|
||||
}
|
||||
let r:boolean[] = [];
|
||||
for (let i = 0; i <= maxCharCode; i++) {
|
||||
r[i] = false;
|
||||
}
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
r[str.charCodeAt(i)] = true;
|
||||
}
|
||||
return r;
|
||||
this._whitespace = '\t \u00a0';
|
||||
this._whitespaceArr = CharacterSet.getOrCreate(this._whitespace);
|
||||
this._separators = '';
|
||||
this._separatorsArr = CharacterSet.getOrCreate(this._separators);
|
||||
this._tokenStart = -1;
|
||||
this._tokenEnd = -1;
|
||||
}
|
||||
|
||||
public pos():number {
|
||||
|
@ -59,12 +61,12 @@ export class LineStream implements IStream {
|
|||
}
|
||||
|
||||
public eos() {
|
||||
return this._pos >= this.sourceLength;
|
||||
return this._pos >= this._sourceLength;
|
||||
}
|
||||
|
||||
public peek():string {
|
||||
// Check EOS
|
||||
if (this._pos >= this.sourceLength) {
|
||||
if (this._pos >= this._sourceLength) {
|
||||
throw new Error('Stream is at the end');
|
||||
}
|
||||
return this._source[this._pos];
|
||||
|
@ -72,26 +74,26 @@ export class LineStream implements IStream {
|
|||
|
||||
public next():string {
|
||||
// Check EOS
|
||||
if (this._pos >= this.sourceLength) {
|
||||
if (this._pos >= this._sourceLength) {
|
||||
throw new Error('Stream is at the end');
|
||||
}
|
||||
|
||||
// Reset peeked token
|
||||
this.tokenStart = -1;
|
||||
this.tokenEnd = -1;
|
||||
this._tokenStart = -1;
|
||||
this._tokenEnd = -1;
|
||||
|
||||
return this._source[this._pos++];
|
||||
}
|
||||
|
||||
public next2(): void {
|
||||
// Check EOS
|
||||
if (this._pos >= this.sourceLength) {
|
||||
if (this._pos >= this._sourceLength) {
|
||||
throw new Error('Stream is at the end');
|
||||
}
|
||||
|
||||
// Reset peeked token
|
||||
this.tokenStart = -1;
|
||||
this.tokenEnd = -1;
|
||||
this._tokenStart = -1;
|
||||
this._tokenEnd = -1;
|
||||
|
||||
this._pos++;
|
||||
}
|
||||
|
@ -100,11 +102,11 @@ export class LineStream implements IStream {
|
|||
if (n === 0) {
|
||||
return '';
|
||||
}
|
||||
var oldPos = this._pos;
|
||||
const oldPos = this._pos;
|
||||
this._pos += n;
|
||||
// Reset peeked token
|
||||
this.tokenStart = -1;
|
||||
this.tokenEnd = -1;
|
||||
this._tokenStart = -1;
|
||||
this._tokenEnd = -1;
|
||||
return this._source.substring(oldPos, this._pos);
|
||||
}
|
||||
|
||||
|
@ -114,14 +116,14 @@ export class LineStream implements IStream {
|
|||
}
|
||||
this._pos += n;
|
||||
// Reset peeked token
|
||||
this.tokenStart = -1;
|
||||
this.tokenEnd = -1;
|
||||
this._tokenStart = -1;
|
||||
this._tokenEnd = -1;
|
||||
return n;
|
||||
}
|
||||
|
||||
public advanceToEOS():string {
|
||||
var oldPos = this._pos;
|
||||
this._pos = this.sourceLength;
|
||||
const oldPos = this._pos;
|
||||
this._pos = this._sourceLength;
|
||||
this.resetPeekedToken();
|
||||
return this._source.substring(oldPos, this._pos);
|
||||
}
|
||||
|
@ -131,10 +133,10 @@ export class LineStream implements IStream {
|
|||
this.resetPeekedToken();
|
||||
}
|
||||
|
||||
private createPeeker(condition:any):()=>number {
|
||||
private createPeeker(condition:RegExp|string):()=>number {
|
||||
if (condition instanceof RegExp) {
|
||||
return () => {
|
||||
var result = condition.exec(this._source.substr(this._pos));
|
||||
let result = condition.exec(this._source.substr(this._pos));
|
||||
if (result === null) {
|
||||
return 0;
|
||||
} else if (result.index !== 0) {
|
||||
|
@ -142,13 +144,14 @@ export class LineStream implements IStream {
|
|||
}
|
||||
return result[0].length;
|
||||
};
|
||||
} else if ((condition instanceof String || (typeof condition) === 'string') && condition) {
|
||||
} else if ((typeof condition === 'string') && condition) {
|
||||
return () => {
|
||||
var len = (<String> condition).length, match = this._pos + len <= this.sourceLength;
|
||||
for (var i = 0; match && i < len; i++) {
|
||||
match = this._source.charCodeAt(this._pos + i) === (<String> condition).charCodeAt(i);
|
||||
const len = condition.length;
|
||||
let match = (this._pos + len <= this._sourceLength);
|
||||
for (let i = 0; match && i < len; i++) {
|
||||
match = this._source.charCodeAt(this._pos + i) === condition.charCodeAt(i);
|
||||
}
|
||||
return match ? len : 0;
|
||||
return (match ? len : 0);
|
||||
};
|
||||
}
|
||||
throw new Error('Condition must be either a regular expression, function or a non-empty string');
|
||||
|
@ -156,16 +159,15 @@ export class LineStream implements IStream {
|
|||
|
||||
// --- BEGIN `_advanceIfStringCaseInsensitive`
|
||||
private _advanceIfStringCaseInsensitive(condition:string): number {
|
||||
var oldPos = this._pos,
|
||||
source = this._source,
|
||||
len = condition.length,
|
||||
i:number;
|
||||
const oldPos = this._pos;
|
||||
const source = this._source;
|
||||
const len = condition.length;
|
||||
|
||||
if (len < 1 || oldPos + len > this.sourceLength) {
|
||||
if (len < 1 || oldPos + len > this._sourceLength) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
for (let i = 0; i < len; i++) {
|
||||
if (source.charAt(oldPos + i).toLowerCase() !== condition.charAt(i).toLowerCase()) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -183,16 +185,15 @@ export class LineStream implements IStream {
|
|||
|
||||
// --- BEGIN `advanceIfString`
|
||||
private _advanceIfString(condition: string): number {
|
||||
var oldPos = this._pos,
|
||||
source = this._source,
|
||||
len = condition.length,
|
||||
i:number;
|
||||
const oldPos = this._pos;
|
||||
const source = this._source;
|
||||
const len = condition.length;
|
||||
|
||||
if (len < 1 || oldPos + len > this.sourceLength) {
|
||||
if (len < 1 || oldPos + len > this._sourceLength) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
for (let i = 0; i < len; i++) {
|
||||
if (source.charCodeAt(oldPos + i) !== condition.charCodeAt(i)) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -210,7 +211,7 @@ export class LineStream implements IStream {
|
|||
|
||||
// --- BEGIN `advanceIfString`
|
||||
private _advanceIfCharCode(charCode:number): number {
|
||||
if (this._pos < this.sourceLength && this._source.charCodeAt(this._pos) === charCode) {
|
||||
if (this._pos < this._sourceLength && this._source.charCodeAt(this._pos) === charCode) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -226,7 +227,7 @@ export class LineStream implements IStream {
|
|||
|
||||
// --- BEGIN `advanceIfRegExp`
|
||||
private _advanceIfRegExp(condition:RegExp): number {
|
||||
if (this._pos >= this.sourceLength) {
|
||||
if (this._pos >= this._sourceLength) {
|
||||
return 0;
|
||||
}
|
||||
if (!condition.test(this._source.substr(this._pos))) {
|
||||
|
@ -242,14 +243,14 @@ export class LineStream implements IStream {
|
|||
}
|
||||
// --- END
|
||||
|
||||
private advanceLoop(condition:any, isWhile:boolean, including:boolean):string {
|
||||
private advanceLoop(condition:RegExp|string, isWhile:boolean, including:boolean):string {
|
||||
if (this.eos()) {
|
||||
return '';
|
||||
}
|
||||
var peeker = this.createPeeker(condition);
|
||||
var oldPos = this._pos;
|
||||
var n = 0;
|
||||
var f = null;
|
||||
const peeker = this.createPeeker(condition);
|
||||
const oldPos = this._pos;
|
||||
let n = 0;
|
||||
let f = null;
|
||||
if (isWhile) {
|
||||
f = (n) => {
|
||||
return n > 0;
|
||||
|
@ -272,11 +273,11 @@ export class LineStream implements IStream {
|
|||
return this._source.substring(oldPos, this._pos);
|
||||
}
|
||||
|
||||
public advanceWhile(condition:any):string {
|
||||
public advanceWhile(condition:RegExp|string):string {
|
||||
return this.advanceLoop(condition, true, false);
|
||||
}
|
||||
|
||||
public advanceUntil(condition:any, including:boolean):string {
|
||||
public advanceUntil(condition:RegExp|string, including:boolean):string {
|
||||
return this.advanceLoop(condition, false, including);
|
||||
}
|
||||
|
||||
|
@ -286,12 +287,12 @@ export class LineStream implements IStream {
|
|||
return 0;
|
||||
}
|
||||
|
||||
var oldPos = this._pos;
|
||||
var index = this._source.indexOf(condition, oldPos);
|
||||
const oldPos = this._pos;
|
||||
const index = this._source.indexOf(condition, oldPos);
|
||||
|
||||
if (index === -1) {
|
||||
// String was not found => advanced to `eos`
|
||||
return (this.sourceLength - oldPos);
|
||||
return (this._sourceLength - oldPos);
|
||||
}
|
||||
|
||||
if (including) {
|
||||
|
@ -311,16 +312,16 @@ export class LineStream implements IStream {
|
|||
// --- END
|
||||
|
||||
private resetPeekedToken() {
|
||||
this.tokenStart = -1;
|
||||
this.tokenEnd = -1;
|
||||
this._tokenStart = -1;
|
||||
this._tokenEnd = -1;
|
||||
}
|
||||
|
||||
public setTokenRules(separators:string, whitespace:string):void {
|
||||
if (this.separators !== separators || this.whitespace !== whitespace) {
|
||||
this.separators = separators;
|
||||
this.separatorsArr = this.stringToArray(this.separators);
|
||||
this.whitespace = whitespace;
|
||||
this.whitespaceArr = this.stringToArray(this.whitespace);
|
||||
if (this._separators !== separators || this._whitespace !== whitespace) {
|
||||
this._separators = separators;
|
||||
this._separatorsArr = CharacterSet.getOrCreate(this._separators);
|
||||
this._whitespace = whitespace;
|
||||
this._whitespaceArr = CharacterSet.getOrCreate(this._whitespace);
|
||||
this.resetPeekedToken();
|
||||
}
|
||||
}
|
||||
|
@ -328,15 +329,16 @@ export class LineStream implements IStream {
|
|||
// --- tokens
|
||||
|
||||
public peekToken():string {
|
||||
if (this.tokenStart !== -1) {
|
||||
return this._source.substring(this.tokenStart, this.tokenEnd);
|
||||
if (this._tokenStart !== -1) {
|
||||
return this._source.substring(this._tokenStart, this._tokenEnd);
|
||||
}
|
||||
|
||||
var source = this._source,
|
||||
sourceLength = this.sourceLength,
|
||||
whitespaceArr = this.whitespaceArr,
|
||||
separatorsArr = this.separatorsArr,
|
||||
tokenStart = this._pos;
|
||||
const source = this._source;
|
||||
const sourceLength = this._sourceLength;
|
||||
const whitespaceArr = this._whitespaceArr;
|
||||
const separatorsArr = this._separatorsArr;
|
||||
|
||||
let tokenStart = this._pos;
|
||||
|
||||
// Check EOS
|
||||
if (tokenStart >= sourceLength) {
|
||||
|
@ -344,48 +346,48 @@ export class LineStream implements IStream {
|
|||
}
|
||||
|
||||
// Skip whitespace
|
||||
while (whitespaceArr[source.charCodeAt(tokenStart)] && tokenStart < sourceLength) {
|
||||
while (whitespaceArr.contains(source.charCodeAt(tokenStart)) && tokenStart < sourceLength) {
|
||||
tokenStart++;
|
||||
}
|
||||
|
||||
var tokenEnd = tokenStart;
|
||||
let tokenEnd = tokenStart;
|
||||
// If a separator is hit, it is a token
|
||||
if (separatorsArr[source.charCodeAt(tokenEnd)] && tokenEnd < sourceLength) {
|
||||
if (separatorsArr.contains(source.charCodeAt(tokenEnd)) && tokenEnd < sourceLength) {
|
||||
tokenEnd++;
|
||||
} else {
|
||||
// Advance until a separator or a whitespace is hit
|
||||
while (!separatorsArr[source.charCodeAt(tokenEnd)] && !whitespaceArr[source.charCodeAt(tokenEnd)] && tokenEnd < sourceLength) {
|
||||
while (!separatorsArr.contains(source.charCodeAt(tokenEnd)) && !whitespaceArr.contains(source.charCodeAt(tokenEnd)) && tokenEnd < sourceLength) {
|
||||
tokenEnd++;
|
||||
}
|
||||
}
|
||||
|
||||
// Cache peeked token
|
||||
this.tokenStart = tokenStart;
|
||||
this.tokenEnd = tokenEnd;
|
||||
this._tokenStart = tokenStart;
|
||||
this._tokenEnd = tokenEnd;
|
||||
|
||||
return source.substring(tokenStart, tokenEnd);
|
||||
}
|
||||
|
||||
public nextToken():string {
|
||||
// Check EOS
|
||||
if (this._pos >= this.sourceLength) {
|
||||
if (this._pos >= this._sourceLength) {
|
||||
throw new Error('Stream is at the end');
|
||||
}
|
||||
|
||||
// Peek token if necessary
|
||||
var result:string;
|
||||
if (this.tokenStart === -1) {
|
||||
let result:string;
|
||||
if (this._tokenStart === -1) {
|
||||
result = this.peekToken();
|
||||
} else {
|
||||
result = this._source.substring(this.tokenStart, this.tokenEnd);
|
||||
result = this._source.substring(this._tokenStart, this._tokenEnd);
|
||||
}
|
||||
|
||||
// Advance to tokenEnd
|
||||
this._pos = this.tokenEnd;
|
||||
this._pos = this._tokenEnd;
|
||||
|
||||
// Reset peeked token
|
||||
this.tokenStart = -1;
|
||||
this.tokenEnd = -1;
|
||||
this._tokenStart = -1;
|
||||
this._tokenEnd = -1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -393,26 +395,26 @@ export class LineStream implements IStream {
|
|||
// -- whitespace
|
||||
|
||||
public peekWhitespace():string {
|
||||
var source = this._source,
|
||||
sourceLength = this.sourceLength,
|
||||
whitespaceArr = this.whitespaceArr,
|
||||
peek = this._pos;
|
||||
const source = this._source;
|
||||
const sourceLength = this._sourceLength;
|
||||
const whitespaceArr = this._whitespaceArr;
|
||||
|
||||
while (whitespaceArr[source.charCodeAt(peek)] && peek < sourceLength) {
|
||||
let peek = this._pos;
|
||||
while (whitespaceArr.contains(source.charCodeAt(peek)) && peek < sourceLength) {
|
||||
peek++;
|
||||
}
|
||||
return source.substring(this._pos, peek);
|
||||
}
|
||||
|
||||
// --- BEGIN `advanceIfRegExp`
|
||||
// --- BEGIN `skipWhitespace`
|
||||
private _skipWhitespace(): number {
|
||||
var source = this._source,
|
||||
sourceLength = this.sourceLength,
|
||||
whitespaceArr = this.whitespaceArr,
|
||||
oldPos = this._pos,
|
||||
peek = this._pos;
|
||||
const source = this._source;
|
||||
const sourceLength = this._sourceLength;
|
||||
const whitespaceArr = this._whitespaceArr;
|
||||
const oldPos = this._pos;
|
||||
|
||||
while (whitespaceArr[source.charCodeAt(peek)] && peek < sourceLength) {
|
||||
let peek = this._pos;
|
||||
while (whitespaceArr.contains(source.charCodeAt(peek)) && peek < sourceLength) {
|
||||
peek++;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,97 +5,137 @@
|
|||
'use strict';
|
||||
|
||||
import {ILink} from 'vs/editor/common/modes';
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
import {CharacterClassifier} from 'vs/editor/common/core/characterClassifier';
|
||||
|
||||
export interface ILinkComputerTarget {
|
||||
getLineCount(): number;
|
||||
getLineContent(lineNumber:number): string;
|
||||
}
|
||||
|
||||
const enum State {
|
||||
Invalid = 0,
|
||||
Start = 1,
|
||||
H = 2,
|
||||
HT = 3,
|
||||
HTT = 4,
|
||||
HTTP = 5,
|
||||
F = 6,
|
||||
FI = 7,
|
||||
FIL = 8,
|
||||
BeforeColon = 9,
|
||||
AfterColon = 10,
|
||||
AlmostThere = 11,
|
||||
End = 12,
|
||||
Accept = 13
|
||||
}
|
||||
|
||||
type Edge = [State,number,State];
|
||||
|
||||
class StateMachine {
|
||||
|
||||
private _states: State[][];
|
||||
private _maxCharCode: number;
|
||||
|
||||
constructor(edges:Edge[]) {
|
||||
let maxCharCode = 0;
|
||||
let maxState = State.Invalid;
|
||||
for (let i = 0, len = edges.length; i < len; i++) {
|
||||
let [from, chCode, to] = edges[i];
|
||||
if (chCode > maxCharCode) {
|
||||
maxCharCode = chCode;
|
||||
}
|
||||
if (from > maxState) {
|
||||
maxState = from;
|
||||
}
|
||||
if (to > maxState) {
|
||||
maxState = to;
|
||||
}
|
||||
}
|
||||
|
||||
let states:number[][] = [];
|
||||
for (let i = 0; i <= maxState; i++) {
|
||||
let tmp:number[] = [];
|
||||
for (let j = 0; j <= maxCharCode; j++) {
|
||||
tmp[j] = State.Invalid;
|
||||
}
|
||||
states[i] = tmp;
|
||||
}
|
||||
|
||||
for (let i = 0, len = edges.length; i < len; i++) {
|
||||
let [from, chCode, to] = edges[i];
|
||||
states[from][chCode] = to;
|
||||
}
|
||||
|
||||
this._states = states;
|
||||
this._maxCharCode = maxCharCode;
|
||||
}
|
||||
|
||||
public nextState(currentState:State, chCode:number): State {
|
||||
if (chCode < 0 || chCode > this._maxCharCode) {
|
||||
return State.Invalid;
|
||||
}
|
||||
return this._states[currentState][chCode];
|
||||
}
|
||||
}
|
||||
|
||||
// State machine for http:// or https:// or file://
|
||||
const STATE_MAP:{[ch:string]:number}[] = [];
|
||||
const START_STATE = 1;
|
||||
const END_STATE = 12;
|
||||
const ACCEPT_STATE = 13;
|
||||
let stateMachine = new StateMachine([
|
||||
[State.Start, CharCode.h, State.H],
|
||||
[State.Start, CharCode.H, State.H],
|
||||
[State.Start, CharCode.f, State.F],
|
||||
[State.Start, CharCode.F, State.F],
|
||||
|
||||
STATE_MAP[1] = { 'h': 2, 'H': 2, 'f': 6, 'F': 6 };
|
||||
STATE_MAP[2] = { 't': 3, 'T': 3 };
|
||||
STATE_MAP[3] = { 't': 4, 'T': 4 };
|
||||
STATE_MAP[4] = { 'p': 5, 'P': 5 };
|
||||
STATE_MAP[5] = { 's': 9, 'S': 9, ':': 10 };
|
||||
STATE_MAP[6] = { 'i': 7, 'I': 7 };
|
||||
STATE_MAP[7] = { 'l': 8, 'L': 8 };
|
||||
STATE_MAP[8] = { 'e': 9, 'E': 9 };
|
||||
STATE_MAP[9] = { ':': 10 };
|
||||
STATE_MAP[10] = { '/': 11 };
|
||||
STATE_MAP[11] = { '/': END_STATE };
|
||||
[State.H, CharCode.t, State.HT],
|
||||
[State.H, CharCode.T, State.HT],
|
||||
|
||||
enum CharacterClass {
|
||||
[State.HT, CharCode.t, State.HTT],
|
||||
[State.HT, CharCode.T, State.HTT],
|
||||
|
||||
[State.HTT, CharCode.p, State.HTTP],
|
||||
[State.HTT, CharCode.P, State.HTTP],
|
||||
|
||||
[State.HTTP, CharCode.s, State.BeforeColon],
|
||||
[State.HTTP, CharCode.S, State.BeforeColon],
|
||||
[State.HTTP, CharCode.Colon, State.AfterColon],
|
||||
|
||||
[State.F, CharCode.i, State.FI],
|
||||
[State.F, CharCode.I, State.FI],
|
||||
|
||||
[State.FI, CharCode.l, State.FIL],
|
||||
[State.FI, CharCode.L, State.FIL],
|
||||
|
||||
[State.FIL, CharCode.e, State.BeforeColon],
|
||||
[State.FIL, CharCode.E, State.BeforeColon],
|
||||
|
||||
[State.BeforeColon, CharCode.Colon, State.AfterColon],
|
||||
|
||||
[State.AfterColon, CharCode.Slash, State.AlmostThere],
|
||||
|
||||
[State.AlmostThere, CharCode.Slash, State.End],
|
||||
]);
|
||||
|
||||
const enum CharacterClass {
|
||||
None = 0,
|
||||
ForceTermination = 1,
|
||||
CannotEndIn = 2
|
||||
}
|
||||
|
||||
const _openParens = '('.charCodeAt(0);
|
||||
const _closeParens = ')'.charCodeAt(0);
|
||||
const _openSquareBracket = '['.charCodeAt(0);
|
||||
const _closeSquareBracket = ']'.charCodeAt(0);
|
||||
const _openCurlyBracket = '{'.charCodeAt(0);
|
||||
const _closeCurlyBracket = '}'.charCodeAt(0);
|
||||
const classifier = (function() {
|
||||
let result = new CharacterClassifier(CharacterClass.None);
|
||||
|
||||
class CharacterClassifier {
|
||||
|
||||
/**
|
||||
* Maintain a compact (fully initialized ASCII map for quickly classifying ASCII characters - used more often in code).
|
||||
*/
|
||||
private _asciiMap: CharacterClass[];
|
||||
|
||||
/**
|
||||
* The entire map (sparse array).
|
||||
*/
|
||||
private _map: CharacterClass[];
|
||||
|
||||
constructor() {
|
||||
const FORCE_TERMINATION_CHARACTERS = ' \t<>\'\"、。。、,.:;?!@#$%&*‘“〈《「『【〔([{「」}])〕】』」》〉”’`~…';
|
||||
const CANNOT_END_WITH_CHARACTERS = '.,;';
|
||||
|
||||
this._asciiMap = [];
|
||||
for (let i = 0; i < 256; i++) {
|
||||
this._asciiMap[i] = CharacterClass.None;
|
||||
}
|
||||
|
||||
this._map = [];
|
||||
|
||||
for (let i = 0; i < FORCE_TERMINATION_CHARACTERS.length; i++) {
|
||||
this._set(FORCE_TERMINATION_CHARACTERS.charCodeAt(i), CharacterClass.ForceTermination);
|
||||
}
|
||||
|
||||
for (let i = 0; i < CANNOT_END_WITH_CHARACTERS.length; i++) {
|
||||
this._set(CANNOT_END_WITH_CHARACTERS.charCodeAt(i), CharacterClass.CannotEndIn);
|
||||
}
|
||||
const FORCE_TERMINATION_CHARACTERS = ' \t<>\'\"、。。、,.:;?!@#$%&*‘“〈《「『【〔([{「」}])〕】』」》〉”’`~…';
|
||||
for (let i = 0; i < FORCE_TERMINATION_CHARACTERS.length; i++) {
|
||||
result.set(FORCE_TERMINATION_CHARACTERS.charCodeAt(i), CharacterClass.ForceTermination);
|
||||
}
|
||||
|
||||
private _set(charCode:number, charClass:CharacterClass): void {
|
||||
if (charCode < 256) {
|
||||
this._asciiMap[charCode] = charClass;
|
||||
}
|
||||
this._map[charCode] = charClass;
|
||||
const CANNOT_END_WITH_CHARACTERS = '.,;';
|
||||
for (let i = 0; i < CANNOT_END_WITH_CHARACTERS.length; i++) {
|
||||
result.set(CANNOT_END_WITH_CHARACTERS.charCodeAt(i), CharacterClass.CannotEndIn);
|
||||
}
|
||||
|
||||
public classify(charCode:number): CharacterClass {
|
||||
if (charCode < 256) {
|
||||
return this._asciiMap[charCode];
|
||||
}
|
||||
|
||||
let charClass = this._map[charCode];
|
||||
if (charClass) {
|
||||
return charClass;
|
||||
}
|
||||
|
||||
return CharacterClass.None;
|
||||
}
|
||||
}
|
||||
|
||||
const characterClassifier = new CharacterClassifier();
|
||||
return result;
|
||||
})();
|
||||
|
||||
class LinkComputer {
|
||||
|
||||
|
@ -104,7 +144,7 @@ class LinkComputer {
|
|||
let lastIncludedCharIndex = linkEndIndex - 1;
|
||||
do {
|
||||
const chCode = line.charCodeAt(lastIncludedCharIndex);
|
||||
const chClass = characterClassifier.classify(chCode);
|
||||
const chClass = classifier.get(chCode);
|
||||
if (chClass !== CharacterClass.CannotEndIn) {
|
||||
break;
|
||||
}
|
||||
|
@ -130,7 +170,7 @@ class LinkComputer {
|
|||
|
||||
let j = 0;
|
||||
let linkBeginIndex = 0;
|
||||
let state = START_STATE;
|
||||
let state = State.Start;
|
||||
let hasOpenParens = false;
|
||||
let hasOpenSquareBracket = false;
|
||||
let hasOpenCurlyBracket = false;
|
||||
|
@ -138,34 +178,34 @@ class LinkComputer {
|
|||
while (j < len) {
|
||||
|
||||
let resetStateMachine = false;
|
||||
const chCode = line.charCodeAt(j);
|
||||
|
||||
if (state === ACCEPT_STATE) {
|
||||
const chCode = line.charCodeAt(j);
|
||||
if (state === State.Accept) {
|
||||
let chClass:CharacterClass;
|
||||
switch (chCode) {
|
||||
case _openParens:
|
||||
case CharCode.OpenParen:
|
||||
hasOpenParens = true;
|
||||
chClass = CharacterClass.None;
|
||||
break;
|
||||
case _closeParens:
|
||||
case CharCode.CloseParen:
|
||||
chClass = (hasOpenParens ? CharacterClass.None : CharacterClass.ForceTermination);
|
||||
break;
|
||||
case _openSquareBracket:
|
||||
case CharCode.OpenSquareBracket:
|
||||
hasOpenSquareBracket = true;
|
||||
chClass = CharacterClass.None;
|
||||
break;
|
||||
case _closeSquareBracket:
|
||||
case CharCode.CloseSquareBracket:
|
||||
chClass = (hasOpenSquareBracket ? CharacterClass.None : CharacterClass.ForceTermination);
|
||||
break;
|
||||
case _openCurlyBracket:
|
||||
case CharCode.OpenCurlyBrace:
|
||||
hasOpenCurlyBracket = true;
|
||||
chClass = CharacterClass.None;
|
||||
break;
|
||||
case _closeCurlyBracket:
|
||||
case CharCode.CloseCurlyBrace:
|
||||
chClass = (hasOpenCurlyBracket ? CharacterClass.None : CharacterClass.ForceTermination);
|
||||
break;
|
||||
default:
|
||||
chClass = characterClassifier.classify(chCode);
|
||||
chClass = classifier.get(chCode);
|
||||
}
|
||||
|
||||
// Check if character terminates link
|
||||
|
@ -173,27 +213,24 @@ class LinkComputer {
|
|||
result.push(LinkComputer._createLink(line, i, linkBeginIndex, j));
|
||||
resetStateMachine = true;
|
||||
}
|
||||
} else if (state === END_STATE) {
|
||||
const chCode = line.charCodeAt(j);
|
||||
const chClass = characterClassifier.classify(chCode);
|
||||
} else if (state === State.End) {
|
||||
const chClass = classifier.get(chCode);
|
||||
|
||||
// Check if character terminates link
|
||||
if (chClass === CharacterClass.ForceTermination) {
|
||||
resetStateMachine = true;
|
||||
} else {
|
||||
state = ACCEPT_STATE;
|
||||
state = State.Accept;
|
||||
}
|
||||
} else {
|
||||
const ch = line.charAt(j);
|
||||
if (STATE_MAP[state].hasOwnProperty(ch)) {
|
||||
state = STATE_MAP[state][ch];
|
||||
} else {
|
||||
state = stateMachine.nextState(state, chCode);
|
||||
if (state === State.Invalid) {
|
||||
resetStateMachine = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (resetStateMachine) {
|
||||
state = START_STATE;
|
||||
state = State.Start;
|
||||
hasOpenParens = false;
|
||||
hasOpenSquareBracket = false;
|
||||
hasOpenCurlyBracket = false;
|
||||
|
@ -205,7 +242,7 @@ class LinkComputer {
|
|||
j++;
|
||||
}
|
||||
|
||||
if (state === ACCEPT_STATE) {
|
||||
if (state === State.Accept) {
|
||||
result.push(LinkComputer._createLink(line, i, linkBeginIndex, len));
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* Inside monarch we use fully typed definitions and compiled versions of the more abstract JSON descriptions.
|
||||
*/
|
||||
|
||||
export enum MonarchBracket {
|
||||
export const enum MonarchBracket {
|
||||
None = 0,
|
||||
Open = 1,
|
||||
Close = -1
|
||||
|
|
|
@ -68,7 +68,7 @@ function _tokenizeToString(text: string, tokenizationSupport: ITokenizationSuppo
|
|||
result += '<br/>';
|
||||
};
|
||||
|
||||
result = '<div style="white-space: pre-wrap;">';
|
||||
result = `<div class="monaco-tokenized-source">`;
|
||||
_tokenizeLines(text, tokenizationSupport, emitToken, emitNewLine);
|
||||
result += '</div>';
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import * as nls from 'vs/nls';
|
|||
import network = require('vs/base/common/network');
|
||||
import Event, {Emitter} from 'vs/base/common/event';
|
||||
import {EmitterEvent} from 'vs/base/common/eventEmitter';
|
||||
import {MarkedString, textToMarkedString} from 'vs/base/common/htmlContent';
|
||||
import {MarkedString} from 'vs/base/common/htmlContent';
|
||||
import {IDisposable} from 'vs/base/common/lifecycle';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import URI from 'vs/base/common/uri';
|
||||
|
@ -145,9 +145,10 @@ class ModelMarkerHandler {
|
|||
|
||||
if (typeof message === 'string') {
|
||||
if (source) {
|
||||
message = nls.localize('sourceAndDiagMessage', "[{0}] {1}", source, message);
|
||||
const indent = new Array(source.length + 1 + 3 /*'[] '.length*/).join(' ');
|
||||
message = nls.localize('diagAndSource', "[{0}] {1}", source, message.replace(/\n/g, '\n' + indent));
|
||||
}
|
||||
hoverMessage = [textToMarkedString(message)];
|
||||
hoverMessage = [{ language: '_', value: message }];
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
'use strict';
|
||||
|
||||
import {Emitter} from 'vs/base/common/event';
|
||||
import {KeyCode, KeyMod} from 'vs/base/common/keyCodes';
|
||||
import {KeyMod as ConstKeyMod, KeyChord} from 'vs/base/common/keyCodes';
|
||||
import {Position} from 'vs/editor/common/core/position';
|
||||
import {Range} from 'vs/editor/common/core/range';
|
||||
import {Selection, SelectionDirection} from 'vs/editor/common/core/selection';
|
||||
|
@ -14,6 +14,198 @@ import {CancellationTokenSource} from 'vs/base/common/cancellation';
|
|||
import Severity from 'vs/base/common/severity';
|
||||
import URI from 'vs/base/common/uri';
|
||||
|
||||
// --------------------------------------------
|
||||
// This is repeated here so it can be exported
|
||||
// --------------------------------------------
|
||||
export class KeyMod {
|
||||
public static CtrlCmd:number = ConstKeyMod.CtrlCmd;
|
||||
public static Shift:number = ConstKeyMod.Shift;
|
||||
public static Alt:number = ConstKeyMod.Alt;
|
||||
public static WinCtrl:number = ConstKeyMod.WinCtrl;
|
||||
|
||||
public static chord(firstPart:number, secondPart:number): number {
|
||||
return KeyChord(firstPart, secondPart);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------
|
||||
// This is repeated here so it can be exported
|
||||
// --------------------------------------------
|
||||
/**
|
||||
* Virtual Key Codes, the value does not hold any inherent meaning.
|
||||
* Inspired somewhat from https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
|
||||
* But these are "more general", as they should work across browsers & OS`s.
|
||||
*/
|
||||
export enum KeyCode {
|
||||
/**
|
||||
* Placed first to cover the 0 value of the enum.
|
||||
*/
|
||||
Unknown = 0,
|
||||
Backspace = 1,
|
||||
Tab = 2,
|
||||
Enter = 3,
|
||||
Shift = 4,
|
||||
Ctrl = 5,
|
||||
Alt = 6,
|
||||
PauseBreak = 7,
|
||||
CapsLock = 8,
|
||||
Escape = 9,
|
||||
Space = 10,
|
||||
PageUp = 11,
|
||||
PageDown = 12,
|
||||
End = 13,
|
||||
Home = 14,
|
||||
LeftArrow = 15,
|
||||
UpArrow = 16,
|
||||
RightArrow = 17,
|
||||
DownArrow = 18,
|
||||
Insert = 19,
|
||||
Delete = 20,
|
||||
KEY_0 = 21,
|
||||
KEY_1 = 22,
|
||||
KEY_2 = 23,
|
||||
KEY_3 = 24,
|
||||
KEY_4 = 25,
|
||||
KEY_5 = 26,
|
||||
KEY_6 = 27,
|
||||
KEY_7 = 28,
|
||||
KEY_8 = 29,
|
||||
KEY_9 = 30,
|
||||
KEY_A = 31,
|
||||
KEY_B = 32,
|
||||
KEY_C = 33,
|
||||
KEY_D = 34,
|
||||
KEY_E = 35,
|
||||
KEY_F = 36,
|
||||
KEY_G = 37,
|
||||
KEY_H = 38,
|
||||
KEY_I = 39,
|
||||
KEY_J = 40,
|
||||
KEY_K = 41,
|
||||
KEY_L = 42,
|
||||
KEY_M = 43,
|
||||
KEY_N = 44,
|
||||
KEY_O = 45,
|
||||
KEY_P = 46,
|
||||
KEY_Q = 47,
|
||||
KEY_R = 48,
|
||||
KEY_S = 49,
|
||||
KEY_T = 50,
|
||||
KEY_U = 51,
|
||||
KEY_V = 52,
|
||||
KEY_W = 53,
|
||||
KEY_X = 54,
|
||||
KEY_Y = 55,
|
||||
KEY_Z = 56,
|
||||
Meta = 57,
|
||||
ContextMenu = 58,
|
||||
F1 = 59,
|
||||
F2 = 60,
|
||||
F3 = 61,
|
||||
F4 = 62,
|
||||
F5 = 63,
|
||||
F6 = 64,
|
||||
F7 = 65,
|
||||
F8 = 66,
|
||||
F9 = 67,
|
||||
F10 = 68,
|
||||
F11 = 69,
|
||||
F12 = 70,
|
||||
F13 = 71,
|
||||
F14 = 72,
|
||||
F15 = 73,
|
||||
F16 = 74,
|
||||
F17 = 75,
|
||||
F18 = 76,
|
||||
F19 = 77,
|
||||
NumLock = 78,
|
||||
ScrollLock = 79,
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
* For the US standard keyboard, the ';:' key
|
||||
*/
|
||||
US_SEMICOLON = 80,
|
||||
/**
|
||||
* For any country/region, the '+' key
|
||||
* For the US standard keyboard, the '=+' key
|
||||
*/
|
||||
US_EQUAL = 81,
|
||||
/**
|
||||
* For any country/region, the ',' key
|
||||
* For the US standard keyboard, the ',<' key
|
||||
*/
|
||||
US_COMMA = 82,
|
||||
/**
|
||||
* For any country/region, the '-' key
|
||||
* For the US standard keyboard, the '-_' key
|
||||
*/
|
||||
US_MINUS = 83,
|
||||
/**
|
||||
* For any country/region, the '.' key
|
||||
* For the US standard keyboard, the '.>' key
|
||||
*/
|
||||
US_DOT = 84,
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
* For the US standard keyboard, the '/?' key
|
||||
*/
|
||||
US_SLASH = 85,
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
* For the US standard keyboard, the '`~' key
|
||||
*/
|
||||
US_BACKTICK = 86,
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
* For the US standard keyboard, the '[{' key
|
||||
*/
|
||||
US_OPEN_SQUARE_BRACKET = 87,
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
* For the US standard keyboard, the '\|' key
|
||||
*/
|
||||
US_BACKSLASH = 88,
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
* For the US standard keyboard, the ']}' key
|
||||
*/
|
||||
US_CLOSE_SQUARE_BRACKET = 89,
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
* For the US standard keyboard, the ''"' key
|
||||
*/
|
||||
US_QUOTE = 90,
|
||||
/**
|
||||
* Used for miscellaneous characters; it can vary by keyboard.
|
||||
*/
|
||||
OEM_8 = 91,
|
||||
/**
|
||||
* Either the angle bracket key or the backslash key on the RT 102-key keyboard.
|
||||
*/
|
||||
OEM_102 = 92,
|
||||
NUMPAD_0 = 93,
|
||||
NUMPAD_1 = 94,
|
||||
NUMPAD_2 = 95,
|
||||
NUMPAD_3 = 96,
|
||||
NUMPAD_4 = 97,
|
||||
NUMPAD_5 = 98,
|
||||
NUMPAD_6 = 99,
|
||||
NUMPAD_7 = 100,
|
||||
NUMPAD_8 = 101,
|
||||
NUMPAD_9 = 102,
|
||||
NUMPAD_MULTIPLY = 103,
|
||||
NUMPAD_ADD = 104,
|
||||
NUMPAD_SEPARATOR = 105,
|
||||
NUMPAD_SUBTRACT = 106,
|
||||
NUMPAD_DECIMAL = 107,
|
||||
NUMPAD_DIVIDE = 108,
|
||||
/**
|
||||
* Placed last to cover the length of the enum.
|
||||
* Please do not depend on this value!
|
||||
*/
|
||||
MAX_VALUE
|
||||
}
|
||||
|
||||
export function createMonacoBaseAPI(): typeof monaco {
|
||||
return {
|
||||
editor: undefined,
|
||||
|
|
|
@ -9,15 +9,16 @@ import {Arrays} from 'vs/editor/common/core/arrays';
|
|||
import {Range} from 'vs/editor/common/core/range';
|
||||
import {ViewLineToken, ViewLineTokens} from 'vs/editor/common/core/viewLineToken';
|
||||
import {InlineDecoration} from 'vs/editor/common/viewModel/viewModel';
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
|
||||
function cmpLineDecorations(a:InlineDecoration, b:InlineDecoration): number {
|
||||
return Range.compareRangesUsingStarts(a.range, b.range);
|
||||
}
|
||||
|
||||
export function createLineParts(lineNumber:number, minLineColumn:number, lineContent:string, tabSize:number, lineTokens:ViewLineTokens, rawLineDecorations:InlineDecoration[], renderWhitespace:boolean): LineParts {
|
||||
if (renderWhitespace) {
|
||||
export function createLineParts(lineNumber:number, minLineColumn:number, lineContent:string, tabSize:number, lineTokens:ViewLineTokens, rawLineDecorations:InlineDecoration[], renderWhitespace:'none' | 'boundary' | 'all'): LineParts {
|
||||
if (renderWhitespace !== 'none') {
|
||||
let oldLength = rawLineDecorations.length;
|
||||
rawLineDecorations = insertWhitespaceLineDecorations(lineNumber, lineContent, tabSize, lineTokens.getFauxIndentLength(), rawLineDecorations);
|
||||
rawLineDecorations = insertWhitespaceLineDecorations(lineNumber, lineContent, tabSize, lineTokens.getFauxIndentLength(), renderWhitespace, rawLineDecorations);
|
||||
if (rawLineDecorations.length !== oldLength) {
|
||||
rawLineDecorations.sort(cmpLineDecorations);
|
||||
}
|
||||
|
@ -93,27 +94,16 @@ function trimEmptyTrailingPart(parts: ViewLineToken[], lineContent: string): Vie
|
|||
return parts.slice(0, parts.length - 1);
|
||||
}
|
||||
|
||||
const _tab = '\t'.charCodeAt(0);
|
||||
const _space = ' '.charCodeAt(0);
|
||||
|
||||
function insertOneCustomLineDecoration(dest:InlineDecoration[], lineNumber:number, startColumn:number, endColumn:number, className:string): void {
|
||||
dest.push(new InlineDecoration(new Range(lineNumber, startColumn, lineNumber, endColumn), className));
|
||||
}
|
||||
|
||||
function insertWhitespaceLineDecorations(lineNumber:number, lineContent: string, tabSize:number, fauxIndentLength: number, rawLineDecorations: InlineDecoration[]): InlineDecoration[] {
|
||||
function insertWhitespaceLineDecorations(lineNumber:number, lineContent: string, tabSize:number, fauxIndentLength: number, renderWhitespace: 'none' | 'boundary' | 'all', rawLineDecorations: InlineDecoration[]): InlineDecoration[] {
|
||||
let lineLength = lineContent.length;
|
||||
if (lineLength === fauxIndentLength) {
|
||||
return rawLineDecorations;
|
||||
}
|
||||
|
||||
let firstChar = lineContent.charCodeAt(fauxIndentLength);
|
||||
let lastChar = lineContent.charCodeAt(lineLength - 1);
|
||||
|
||||
if (firstChar !== _tab && firstChar !== _space && lastChar !== _tab && lastChar !== _space) {
|
||||
// This line contains no leading nor trailing whitespace => fast path
|
||||
return rawLineDecorations;
|
||||
}
|
||||
|
||||
let firstNonWhitespaceIndex = strings.firstNonWhitespaceIndex(lineContent);
|
||||
let lastNonWhitespaceIndex: number;
|
||||
if (firstNonWhitespaceIndex === -1) {
|
||||
|
@ -138,6 +128,33 @@ function insertWhitespaceLineDecorations(lineNumber:number, lineContent: string,
|
|||
sm_decoration.push('leading whitespace');
|
||||
|
||||
}
|
||||
|
||||
let startOfWhitespace = -1;
|
||||
let hasTab = false;
|
||||
|
||||
for (let i = Math.max(firstNonWhitespaceIndex, fauxIndentLength); i <= lastNonWhitespaceIndex; ++i) {
|
||||
let currentCharIsTab = lineContent.charCodeAt(i) === CharCode.Tab;
|
||||
if (currentCharIsTab || lineContent.charCodeAt(i) === CharCode.Space) {
|
||||
if (currentCharIsTab) {
|
||||
hasTab = true;
|
||||
}
|
||||
if (startOfWhitespace === -1) {
|
||||
startOfWhitespace = i;
|
||||
}
|
||||
} else if (startOfWhitespace !== -1) {
|
||||
if (renderWhitespace === 'all' || renderWhitespace === 'boundary' && (hasTab || i - startOfWhitespace >= 2)) {
|
||||
sm_endIndex.push(startOfWhitespace - 1);
|
||||
sm_decoration.push(null);
|
||||
|
||||
sm_endIndex.push(i - 1);
|
||||
sm_decoration.push('embedded whitespace');
|
||||
}
|
||||
|
||||
startOfWhitespace = -1;
|
||||
hasTab = false;
|
||||
}
|
||||
}
|
||||
|
||||
// add content state
|
||||
sm_endIndex.push(lastNonWhitespaceIndex);
|
||||
sm_decoration.push(null);
|
||||
|
@ -166,7 +183,7 @@ function insertCustomLineDecorationsWithStateMachine(lineNumber:number, lineCont
|
|||
for (let index = 0; index < lineLength; index++) {
|
||||
let chCode = lineContent.charCodeAt(index);
|
||||
|
||||
if (chCode === _tab) {
|
||||
if (chCode === CharCode.Tab) {
|
||||
tmpIndent = tabSize;
|
||||
} else {
|
||||
tmpIndent++;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
'use strict';
|
||||
|
||||
import {ViewLineToken} from 'vs/editor/common/core/viewLineToken';
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
|
||||
export class RenderLineInput {
|
||||
_renderLineInputBrand: void;
|
||||
|
@ -13,7 +14,7 @@ export class RenderLineInput {
|
|||
tabSize: number;
|
||||
spaceWidth: number;
|
||||
stopRenderingLineAfter: number;
|
||||
renderWhitespace: boolean;
|
||||
renderWhitespace: 'none' | 'boundary' | 'all';
|
||||
renderControlCharacters: boolean;
|
||||
parts: ViewLineToken[];
|
||||
|
||||
|
@ -22,7 +23,7 @@ export class RenderLineInput {
|
|||
tabSize: number,
|
||||
spaceWidth: number,
|
||||
stopRenderingLineAfter: number,
|
||||
renderWhitespace: boolean,
|
||||
renderWhitespace: 'none' | 'boundary' | 'all',
|
||||
renderControlCharacters: boolean,
|
||||
parts: ViewLineToken[]
|
||||
) {
|
||||
|
@ -49,16 +50,6 @@ export class RenderLineOutput {
|
|||
}
|
||||
}
|
||||
|
||||
const _space = ' '.charCodeAt(0);
|
||||
const _tab = '\t'.charCodeAt(0);
|
||||
const _lowerThan = '<'.charCodeAt(0);
|
||||
const _greaterThan = '>'.charCodeAt(0);
|
||||
const _ampersand = '&'.charCodeAt(0);
|
||||
const _carriageReturn = '\r'.charCodeAt(0);
|
||||
const _controlCharacterSequenceConversionStart = 9216;
|
||||
const _lineSeparator = '\u2028'.charCodeAt(0); //http://www.fileformat.info/info/unicode/char/2028/index.htm
|
||||
const _bom = 65279;
|
||||
|
||||
export function renderLine(input:RenderLineInput): RenderLineOutput {
|
||||
const lineText = input.lineContent;
|
||||
const lineTextLength = lineText.length;
|
||||
|
@ -92,11 +83,13 @@ function isWhitespace(type:string): boolean {
|
|||
function isControlCharacter(characterCode: number): boolean {
|
||||
return characterCode < 32;
|
||||
}
|
||||
|
||||
const _controlCharacterSequenceConversionStart = 9216;
|
||||
function controlCharacterToPrintable(characterCode: number): string {
|
||||
return String.fromCharCode(_controlCharacterSequenceConversionStart + characterCode);
|
||||
}
|
||||
|
||||
function renderLineActual(lineText: string, lineTextLength: number, tabSize: number, spaceWidth: number, actualLineParts: ViewLineToken[], renderWhitespace: boolean, renderControlCharacters: boolean, charBreakIndex: number): RenderLineOutput {
|
||||
function renderLineActual(lineText: string, lineTextLength: number, tabSize: number, spaceWidth: number, actualLineParts: ViewLineToken[], renderWhitespace: 'none' | 'boundary' | 'all', renderControlCharacters: boolean, charBreakIndex: number): RenderLineOutput {
|
||||
lineTextLength = +lineTextLength;
|
||||
tabSize = +tabSize;
|
||||
charBreakIndex = +charBreakIndex;
|
||||
|
@ -111,7 +104,7 @@ function renderLineActual(lineText: string, lineTextLength: number, tabSize: num
|
|||
for (let partIndex = 0, partIndexLen = actualLineParts.length; partIndex < partIndexLen; partIndex++) {
|
||||
let part = actualLineParts[partIndex];
|
||||
|
||||
let parsRendersWhitespace = (renderWhitespace && isWhitespace(part.type));
|
||||
let parsRendersWhitespace = (renderWhitespace !== 'none' && isWhitespace(part.type));
|
||||
|
||||
let toCharIndex = lineTextLength;
|
||||
if (partIndex + 1 < partIndexLen) {
|
||||
|
@ -128,7 +121,7 @@ function renderLineActual(lineText: string, lineTextLength: number, tabSize: num
|
|||
charOffsetInPartArr[charIndex] = charOffsetInPart;
|
||||
let charCode = lineText.charCodeAt(charIndex);
|
||||
|
||||
if (charCode === _tab) {
|
||||
if (charCode === CharCode.Tab) {
|
||||
let insertSpacesCount = tabSize - (charIndex + tabsCharDelta) % tabSize;
|
||||
tabsCharDelta += insertSpacesCount - 1;
|
||||
charOffsetInPart += insertSpacesCount - 1;
|
||||
|
@ -143,7 +136,7 @@ function renderLineActual(lineText: string, lineTextLength: number, tabSize: num
|
|||
insertSpacesCount--;
|
||||
}
|
||||
} else {
|
||||
// must be _space
|
||||
// must be CharCode.Space
|
||||
partContent += '·';
|
||||
partContentCnt++;
|
||||
}
|
||||
|
@ -175,7 +168,7 @@ function renderLineActual(lineText: string, lineTextLength: number, tabSize: num
|
|||
let charCode = lineText.charCodeAt(charIndex);
|
||||
|
||||
switch (charCode) {
|
||||
case _tab:
|
||||
case CharCode.Tab:
|
||||
let insertSpacesCount = tabSize - (charIndex + tabsCharDelta) % tabSize;
|
||||
tabsCharDelta += insertSpacesCount - 1;
|
||||
charOffsetInPart += insertSpacesCount - 1;
|
||||
|
@ -185,40 +178,39 @@ function renderLineActual(lineText: string, lineTextLength: number, tabSize: num
|
|||
}
|
||||
break;
|
||||
|
||||
case _space:
|
||||
case CharCode.Space:
|
||||
out += ' ';
|
||||
break;
|
||||
|
||||
case _lowerThan:
|
||||
case CharCode.LessThan:
|
||||
out += '<';
|
||||
break;
|
||||
|
||||
case _greaterThan:
|
||||
case CharCode.GreaterThan:
|
||||
out += '>';
|
||||
break;
|
||||
|
||||
case _ampersand:
|
||||
case CharCode.Ampersand:
|
||||
out += '&';
|
||||
break;
|
||||
|
||||
case 0:
|
||||
case CharCode.Null:
|
||||
out += '�';
|
||||
break;
|
||||
|
||||
case _bom:
|
||||
case _lineSeparator:
|
||||
case CharCode.UTF8_BOM:
|
||||
case CharCode.LINE_SEPARATOR_2028:
|
||||
out += '\ufffd';
|
||||
break;
|
||||
|
||||
case _carriageReturn:
|
||||
case CharCode.CarriageReturn:
|
||||
// zero width space, because carriage return would introduce a line break
|
||||
out += '​';
|
||||
break;
|
||||
|
||||
default:
|
||||
let characterCode = lineText.charCodeAt(charIndex);
|
||||
if (renderControlCharacters && isControlCharacter(characterCode)) {
|
||||
out += controlCharacterToPrintable(characterCode);
|
||||
if (renderControlCharacters && isControlCharacter(charCode)) {
|
||||
out += controlCharacterToPrintable(charCode);
|
||||
} else {
|
||||
out += lineText.charAt(charIndex);
|
||||
}
|
||||
|
|
|
@ -8,8 +8,10 @@ import * as strings from 'vs/base/common/strings';
|
|||
import {WrappingIndent} from 'vs/editor/common/editorCommon';
|
||||
import {PrefixSumComputer} from 'vs/editor/common/viewModel/prefixSumComputer';
|
||||
import {ILineMapperFactory, ILineMapping, OutputPosition} from 'vs/editor/common/viewModel/splitLinesCollection';
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
import {CharacterClassifier} from 'vs/editor/common/core/characterClassifier';
|
||||
|
||||
enum CharacterClass {
|
||||
const enum CharacterClass {
|
||||
NONE = 0,
|
||||
BREAK_BEFORE = 1,
|
||||
BREAK_AFTER = 2,
|
||||
|
@ -17,57 +19,25 @@ enum CharacterClass {
|
|||
BREAK_IDEOGRAPHIC = 4 // for Han and Kana.
|
||||
}
|
||||
|
||||
class CharacterClassifier {
|
||||
|
||||
/**
|
||||
* Maintain a compact (fully initialized ASCII map for quickly classifying ASCII characters - used more often in code).
|
||||
*/
|
||||
private _asciiMap: CharacterClass[];
|
||||
|
||||
/**
|
||||
* The entire map (sparse array).
|
||||
*/
|
||||
private _map: CharacterClass[];
|
||||
class WrappingCharacterClassifier extends CharacterClassifier<CharacterClass> {
|
||||
|
||||
constructor(BREAK_BEFORE:string, BREAK_AFTER:string, BREAK_OBTRUSIVE:string) {
|
||||
|
||||
this._asciiMap = [];
|
||||
for (let i = 0; i < 256; i++) {
|
||||
this._asciiMap[i] = CharacterClass.NONE;
|
||||
}
|
||||
|
||||
this._map = [];
|
||||
super(CharacterClass.NONE);
|
||||
|
||||
for (let i = 0; i < BREAK_BEFORE.length; i++) {
|
||||
this._set(BREAK_BEFORE.charCodeAt(i), CharacterClass.BREAK_BEFORE);
|
||||
this.set(BREAK_BEFORE.charCodeAt(i), CharacterClass.BREAK_BEFORE);
|
||||
}
|
||||
|
||||
for (let i = 0; i < BREAK_AFTER.length; i++) {
|
||||
this._set(BREAK_AFTER.charCodeAt(i), CharacterClass.BREAK_AFTER);
|
||||
this.set(BREAK_AFTER.charCodeAt(i), CharacterClass.BREAK_AFTER);
|
||||
}
|
||||
|
||||
for (let i = 0; i < BREAK_OBTRUSIVE.length; i++) {
|
||||
this._set(BREAK_OBTRUSIVE.charCodeAt(i), CharacterClass.BREAK_OBTRUSIVE);
|
||||
this.set(BREAK_OBTRUSIVE.charCodeAt(i), CharacterClass.BREAK_OBTRUSIVE);
|
||||
}
|
||||
}
|
||||
|
||||
private _set(charCode:number, charClass:CharacterClass): void {
|
||||
if (charCode < 256) {
|
||||
this._asciiMap[charCode] = charClass;
|
||||
}
|
||||
this._map[charCode] = charClass;
|
||||
}
|
||||
|
||||
public classify(charCode:number): CharacterClass {
|
||||
if (charCode < 256) {
|
||||
return this._asciiMap[charCode];
|
||||
}
|
||||
|
||||
let charClass = this._map[charCode];
|
||||
if (charClass) {
|
||||
return charClass;
|
||||
}
|
||||
|
||||
public get(charCode:number): CharacterClass {
|
||||
// Initialize CharacterClass.BREAK_IDEOGRAPHIC for these Unicode ranges:
|
||||
// 1. CJK Unified Ideographs (0x4E00 -- 0x9FFF)
|
||||
// 2. CJK Unified Ideographs Extension A (0x3400 -- 0x4DBF)
|
||||
|
@ -80,16 +50,16 @@ class CharacterClassifier {
|
|||
return CharacterClass.BREAK_IDEOGRAPHIC;
|
||||
}
|
||||
|
||||
return CharacterClass.NONE;
|
||||
return super.get(charCode);
|
||||
}
|
||||
}
|
||||
|
||||
export class CharacterHardWrappingLineMapperFactory implements ILineMapperFactory {
|
||||
|
||||
private classifier:CharacterClassifier;
|
||||
private classifier:WrappingCharacterClassifier;
|
||||
|
||||
constructor(breakBeforeChars:string, breakAfterChars:string, breakObtrusiveChars:string) {
|
||||
this.classifier = new CharacterClassifier(breakBeforeChars, breakAfterChars, breakObtrusiveChars);
|
||||
this.classifier = new WrappingCharacterClassifier(breakBeforeChars, breakAfterChars, breakObtrusiveChars);
|
||||
}
|
||||
|
||||
// TODO@Alex -> duplicated in lineCommentCommand
|
||||
|
@ -116,7 +86,6 @@ export class CharacterHardWrappingLineMapperFactory implements ILineMapperFactor
|
|||
|
||||
let wrappedTextIndentVisibleColumn = 0;
|
||||
let wrappedTextIndent = '';
|
||||
const TAB_CHAR_CODE = '\t'.charCodeAt(0);
|
||||
|
||||
let firstNonWhitespaceIndex = -1;
|
||||
if (hardWrappingIndent !== WrappingIndent.None) {
|
||||
|
@ -124,7 +93,7 @@ export class CharacterHardWrappingLineMapperFactory implements ILineMapperFactor
|
|||
if (firstNonWhitespaceIndex !== -1) {
|
||||
wrappedTextIndent = lineText.substring(0, firstNonWhitespaceIndex);
|
||||
for (let i = 0; i < firstNonWhitespaceIndex; i++) {
|
||||
wrappedTextIndentVisibleColumn = CharacterHardWrappingLineMapperFactory.nextVisibleColumn(wrappedTextIndentVisibleColumn, tabSize, lineText.charCodeAt(i) === TAB_CHAR_CODE, 1);
|
||||
wrappedTextIndentVisibleColumn = CharacterHardWrappingLineMapperFactory.nextVisibleColumn(wrappedTextIndentVisibleColumn, tabSize, lineText.charCodeAt(i) === CharCode.Tab, 1);
|
||||
}
|
||||
if (hardWrappingIndent === WrappingIndent.Indent) {
|
||||
wrappedTextIndent += '\t';
|
||||
|
@ -156,8 +125,8 @@ export class CharacterHardWrappingLineMapperFactory implements ILineMapperFactor
|
|||
// but the character at `i` might not fit
|
||||
|
||||
let charCode = lineText.charCodeAt(i);
|
||||
let charCodeIsTab = (charCode === TAB_CHAR_CODE);
|
||||
let charCodeClass = classifier.classify(charCode);
|
||||
let charCodeIsTab = (charCode === CharCode.Tab);
|
||||
let charCodeClass = classifier.get(charCode);
|
||||
|
||||
if (charCodeClass === CharacterClass.BREAK_BEFORE) {
|
||||
// This is a character that indicates that a break should happen before it
|
||||
|
@ -170,7 +139,7 @@ export class CharacterHardWrappingLineMapperFactory implements ILineMapperFactor
|
|||
// CJK breaking : before break
|
||||
if (charCodeClass === CharacterClass.BREAK_IDEOGRAPHIC && i > 0) {
|
||||
let prevCode = lineText.charCodeAt(i - 1);
|
||||
let prevClass = classifier.classify(prevCode);
|
||||
let prevClass = classifier.get(prevCode);
|
||||
if (prevClass !== CharacterClass.BREAK_BEFORE) { // Kinsoku Shori: Don't break after a leading character, like an open bracket
|
||||
niceBreakOffset = i;
|
||||
niceBreakVisibleColumn = 0;
|
||||
|
@ -245,7 +214,7 @@ export class CharacterHardWrappingLineMapperFactory implements ILineMapperFactor
|
|||
// CJK breaking : after break
|
||||
if (charCodeClass === CharacterClass.BREAK_IDEOGRAPHIC && i < len - 1) {
|
||||
let nextCode = lineText.charCodeAt(i + 1);
|
||||
let nextClass = classifier.classify(nextCode);
|
||||
let nextClass = classifier.get(nextCode);
|
||||
if (nextClass !== CharacterClass.BREAK_AFTER) { // Kinsoku Shori: Don't break before a trailing character, like a period
|
||||
niceBreakOffset = i + 1;
|
||||
niceBreakVisibleColumn = wrappedTextIndentVisibleColumn;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
'use strict';
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import {KeyCode, KeyMod} from 'vs/base/common/keyCodes';
|
||||
import {KeyCode, KeyMod, KeyChord} from 'vs/base/common/keyCodes';
|
||||
import {ICommand, ICommonCodeEditor, EditorContextKeys} from 'vs/editor/common/editorCommon';
|
||||
import {editorAction, IActionOptions, EditorAction, ServicesAccessor} from 'vs/editor/common/editorCommonExtensions';
|
||||
import {BlockCommentCommand} from './blockCommentCommand';
|
||||
|
@ -65,7 +65,7 @@ class AddLineCommentAction extends CommentLineAction {
|
|||
precondition: EditorContextKeys.Writable,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.TextFocus,
|
||||
primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_C)
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_C)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ class RemoveLineCommentAction extends CommentLineAction {
|
|||
precondition: EditorContextKeys.Writable,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.TextFocus,
|
||||
primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_U)
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_U)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
|
|||
import {ICommentsConfiguration} from 'vs/editor/common/modes';
|
||||
import {BlockCommentCommand} from './blockCommentCommand';
|
||||
import {LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
import {CharCode} from 'vs/base/common/charCode';
|
||||
|
||||
export interface IInsertionPoint {
|
||||
ignore: boolean;
|
||||
|
@ -36,7 +37,7 @@ export interface ISimpleModel {
|
|||
getLineContent(lineNumber:number): string;
|
||||
}
|
||||
|
||||
export enum Type {
|
||||
export const enum Type {
|
||||
Toggle = 0,
|
||||
ForceAdd = 1,
|
||||
ForceRemove = 2
|
||||
|
@ -114,7 +115,6 @@ export class LineCommentCommand implements editorCommon.ICommand {
|
|||
lineNumber:number,
|
||||
shouldRemoveComments:boolean,
|
||||
lineContent: string,
|
||||
_space = ' '.charCodeAt(0),
|
||||
onlyWhitespaceLines = true;
|
||||
|
||||
if (type === Type.Toggle) {
|
||||
|
@ -162,7 +162,7 @@ export class LineCommentCommand implements editorCommon.ICommand {
|
|||
|
||||
if (shouldRemoveComments) {
|
||||
commentStrEndOffset = lineContentStartOffset + lineData.commentStrLength;
|
||||
if (commentStrEndOffset < lineContent.length && lineContent.charCodeAt(commentStrEndOffset) === _space) {
|
||||
if (commentStrEndOffset < lineContent.length && lineContent.charCodeAt(commentStrEndOffset) === CharCode.Space) {
|
||||
lineData.commentStrLength += 1;
|
||||
}
|
||||
}
|
||||
|
@ -414,8 +414,7 @@ export class LineCommentCommand implements editorCommon.ICommand {
|
|||
lineContent: string,
|
||||
j: number,
|
||||
lenJ: number,
|
||||
currentVisibleColumn: number,
|
||||
_tab = '\t'.charCodeAt(0);
|
||||
currentVisibleColumn: number;
|
||||
|
||||
for (i = 0, len = lines.length; i < len; i++) {
|
||||
if (lines[i].ignore) {
|
||||
|
@ -426,7 +425,7 @@ export class LineCommentCommand implements editorCommon.ICommand {
|
|||
|
||||
currentVisibleColumn = 0;
|
||||
for (j = 0, lenJ = lines[i].commentStrOffset; currentVisibleColumn < minVisibleColumn && j < lenJ; j++) {
|
||||
currentVisibleColumn = LineCommentCommand.nextVisibleColumn(currentVisibleColumn, tabSize, lineContent.charCodeAt(j) === _tab, 1);
|
||||
currentVisibleColumn = LineCommentCommand.nextVisibleColumn(currentVisibleColumn, tabSize, lineContent.charCodeAt(j) === CharCode.Tab, 1);
|
||||
}
|
||||
|
||||
if (currentVisibleColumn < minVisibleColumn) {
|
||||
|
@ -445,7 +444,7 @@ export class LineCommentCommand implements editorCommon.ICommand {
|
|||
|
||||
currentVisibleColumn = 0;
|
||||
for (j = 0, lenJ = lines[i].commentStrOffset; currentVisibleColumn < minVisibleColumn && j < lenJ; j++) {
|
||||
currentVisibleColumn = LineCommentCommand.nextVisibleColumn(currentVisibleColumn, tabSize, lineContent.charCodeAt(j) === _tab, 1);
|
||||
currentVisibleColumn = LineCommentCommand.nextVisibleColumn(currentVisibleColumn, tabSize, lineContent.charCodeAt(j) === CharCode.Tab, 1);
|
||||
}
|
||||
|
||||
if (currentVisibleColumn > minVisibleColumn) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import 'vs/css!./defineKeybinding';
|
|||
import * as nls from 'vs/nls';
|
||||
import {RunOnceScheduler} from 'vs/base/common/async';
|
||||
import {MarkedString} from 'vs/base/common/htmlContent';
|
||||
import {CommonKeybindings, KeyCode, KeyMod, Keybinding} from 'vs/base/common/keyCodes';
|
||||
import {KeyCode, KeyMod, KeyChord, Keybinding} from 'vs/base/common/keyCodes';
|
||||
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import {renderHtml} from 'vs/base/browser/htmlContentRenderer';
|
||||
|
@ -353,14 +353,14 @@ class DefineKeybindingWidget implements IOverlayWidget {
|
|||
|
||||
let kb = new Keybinding(keyEvent.asKeybinding());
|
||||
switch (kb.value) {
|
||||
case CommonKeybindings.ENTER:
|
||||
case KeyCode.Enter:
|
||||
if (this._lastKeybinding) {
|
||||
this._onAccepted(this._lastKeybinding.toUserSettingsLabel());
|
||||
}
|
||||
this._stop();
|
||||
return;
|
||||
|
||||
case CommonKeybindings.ESCAPE:
|
||||
case KeyCode.Escape:
|
||||
this._stop();
|
||||
return;
|
||||
}
|
||||
|
@ -461,7 +461,7 @@ export class DefineKeybindingAction extends EditorAction {
|
|||
precondition: ContextKeyExpr.and(EditorContextKeys.Writable, EditorContextKeys.LanguageId.isEqualTo('json')),
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.TextFocus,
|
||||
primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K)
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import 'vs/css!./findWidget';
|
||||
import * as nls from 'vs/nls';
|
||||
import {onUnexpectedError} from 'vs/base/common/errors';
|
||||
import {CommonKeybindings} from 'vs/base/common/keyCodes';
|
||||
import {KeyCode, KeyMod} from 'vs/base/common/keyCodes';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import {IKeyboardEvent} from 'vs/base/browser/keyboardEvent';
|
||||
|
@ -318,17 +318,17 @@ export class FindWidget extends Widget implements IOverlayWidget {
|
|||
private _onFindInputKeyDown(e:IKeyboardEvent): void {
|
||||
|
||||
switch (e.asKeybinding()) {
|
||||
case CommonKeybindings.ENTER:
|
||||
case KeyCode.Enter:
|
||||
this._codeEditor.getAction(FIND_IDS.NextMatchFindAction).run().done(null, onUnexpectedError);
|
||||
e.preventDefault();
|
||||
return;
|
||||
|
||||
case CommonKeybindings.SHIFT_ENTER:
|
||||
case KeyMod.Shift | KeyCode.Enter:
|
||||
this._codeEditor.getAction(FIND_IDS.PreviousMatchFindAction).run().done(null, onUnexpectedError);
|
||||
e.preventDefault();
|
||||
return;
|
||||
|
||||
case CommonKeybindings.TAB:
|
||||
case KeyCode.Tab:
|
||||
if (this._isReplaceVisible) {
|
||||
this._replaceInputBox.focus();
|
||||
} else {
|
||||
|
@ -337,7 +337,7 @@ export class FindWidget extends Widget implements IOverlayWidget {
|
|||
e.preventDefault();
|
||||
return;
|
||||
|
||||
case CommonKeybindings.CTRLCMD_DOWN_ARROW:
|
||||
case KeyMod.CtrlCmd | KeyCode.DownArrow:
|
||||
this._codeEditor.focus();
|
||||
e.preventDefault();
|
||||
return;
|
||||
|
@ -347,27 +347,27 @@ export class FindWidget extends Widget implements IOverlayWidget {
|
|||
private _onReplaceInputKeyDown(e:IKeyboardEvent): void {
|
||||
|
||||
switch (e.asKeybinding()) {
|
||||
case CommonKeybindings.ENTER:
|
||||
case KeyCode.Enter:
|
||||
this._controller.replace();
|
||||
e.preventDefault();
|
||||
return;
|
||||
|
||||
case CommonKeybindings.CTRLCMD_ENTER:
|
||||
case KeyMod.CtrlCmd | KeyCode.Enter:
|
||||
this._controller.replaceAll();
|
||||
e.preventDefault();
|
||||
return;
|
||||
|
||||
case CommonKeybindings.TAB:
|
||||
case KeyCode.Tab:
|
||||
this._findInput.focusOnCaseSensitive();
|
||||
e.preventDefault();
|
||||
return;
|
||||
|
||||
case CommonKeybindings.SHIFT_TAB:
|
||||
case KeyMod.Shift | KeyCode.Tab:
|
||||
this._findInput.focus();
|
||||
e.preventDefault();
|
||||
return;
|
||||
|
||||
case CommonKeybindings.CTRLCMD_DOWN_ARROW:
|
||||
case KeyMod.CtrlCmd | KeyCode.DownArrow:
|
||||
this._codeEditor.focus();
|
||||
e.preventDefault();
|
||||
return;
|
||||
|
@ -422,7 +422,7 @@ export class FindWidget extends Widget implements IOverlayWidget {
|
|||
}, true);
|
||||
}));
|
||||
this._register(this._findInput.onCaseSensitiveKeyDown((e) => {
|
||||
if (e.equals(CommonKeybindings.SHIFT_TAB)) {
|
||||
if (e.equals(KeyMod.Shift | KeyCode.Tab)) {
|
||||
if (this._isReplaceVisible) {
|
||||
this._replaceInputBox.focus();
|
||||
e.preventDefault();
|
||||
|
@ -485,7 +485,7 @@ export class FindWidget extends Widget implements IOverlayWidget {
|
|||
this._state.change({ isRevealed: false }, false);
|
||||
},
|
||||
onKeyDown: (e) => {
|
||||
if (e.equals(CommonKeybindings.TAB)) {
|
||||
if (e.equals(KeyCode.Tab)) {
|
||||
if (this._isReplaceVisible) {
|
||||
if (this._replaceBtn.isEnabled()) {
|
||||
this._replaceBtn.focus();
|
||||
|
@ -526,7 +526,7 @@ export class FindWidget extends Widget implements IOverlayWidget {
|
|||
this._controller.replace();
|
||||
},
|
||||
onKeyDown: (e) => {
|
||||
if (e.equals(CommonKeybindings.SHIFT_TAB)) {
|
||||
if (e.equals(KeyMod.Shift | KeyCode.Tab)) {
|
||||
this._closeBtn.focus();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
@ -687,7 +687,7 @@ class SimpleButton extends Widget {
|
|||
e.preventDefault();
|
||||
});
|
||||
this.onkeydown(this._domNode, (e) => {
|
||||
if (e.equals(CommonKeybindings.SPACE) || e.equals(CommonKeybindings.ENTER)) {
|
||||
if (e.equals(KeyCode.Space) || e.equals(KeyCode.Enter)) {
|
||||
this._opts.onTrigger();
|
||||
e.preventDefault();
|
||||
return;
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
'use strict';
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import {KeyCode, KeyMod} from 'vs/base/common/keyCodes';
|
||||
import {HistoryNavigator} from 'vs/base/common/history';
|
||||
import {KeyCode, KeyMod, KeyChord} from 'vs/base/common/keyCodes';
|
||||
import {Disposable} from 'vs/base/common/lifecycle';
|
||||
import {ContextKeyExpr, RawContextKey, IContextKey, IContextKeyService} from 'vs/platform/contextkey/common/contextkey';
|
||||
import {Range} from 'vs/editor/common/core/range';
|
||||
|
@ -16,21 +17,21 @@ import {editorAction, commonEditorContribution, ServicesAccessor, EditorAction,
|
|||
import {FIND_IDS, FindModelBoundToEditorModel} from 'vs/editor/contrib/find/common/findModel';
|
||||
import {FindReplaceState, FindReplaceStateChangedEvent, INewFindReplaceState} from 'vs/editor/contrib/find/common/findState';
|
||||
import {DocumentHighlightProviderRegistry} from 'vs/editor/common/modes';
|
||||
import {RunOnceScheduler} from 'vs/base/common/async';
|
||||
import {RunOnceScheduler, Delayer} from 'vs/base/common/async';
|
||||
|
||||
import EditorContextKeys = editorCommon.EditorContextKeys;
|
||||
|
||||
export enum FindStartFocusAction {
|
||||
export const enum FindStartFocusAction {
|
||||
NoFocusChange,
|
||||
FocusFindInput,
|
||||
FocusReplaceInput
|
||||
}
|
||||
|
||||
export interface IFindStartOptions {
|
||||
forceRevealReplace:boolean;
|
||||
seedSearchStringFromSelection:boolean;
|
||||
shouldFocus:FindStartFocusAction;
|
||||
shouldAnimate:boolean;
|
||||
forceRevealReplace: boolean;
|
||||
seedSearchStringFromSelection: boolean;
|
||||
shouldFocus: FindStartFocusAction;
|
||||
shouldAnimate: boolean;
|
||||
}
|
||||
|
||||
export const CONTEXT_FIND_WIDGET_VISIBLE = new RawContextKey<boolean>('findWidgetVisible', false);
|
||||
|
@ -43,17 +44,21 @@ export class CommonFindController extends Disposable implements editorCommon.IEd
|
|||
private _editor: editorCommon.ICommonCodeEditor;
|
||||
private _findWidgetVisible: IContextKey<boolean>;
|
||||
protected _state: FindReplaceState;
|
||||
private _currentHistoryNavigator: HistoryNavigator<string>;
|
||||
private _updateHistoryDelayer: Delayer<void>;
|
||||
private _model: FindModelBoundToEditorModel;
|
||||
|
||||
public static get(editor:editorCommon.ICommonCodeEditor): CommonFindController {
|
||||
public static get(editor: editorCommon.ICommonCodeEditor): CommonFindController {
|
||||
return editor.getContribution<CommonFindController>(CommonFindController.ID);
|
||||
}
|
||||
|
||||
constructor(editor:editorCommon.ICommonCodeEditor, @IContextKeyService contextKeyService: IContextKeyService) {
|
||||
constructor(editor: editorCommon.ICommonCodeEditor, @IContextKeyService contextKeyService: IContextKeyService) {
|
||||
super();
|
||||
this._editor = editor;
|
||||
this._findWidgetVisible = CONTEXT_FIND_WIDGET_VISIBLE.bindTo(contextKeyService);
|
||||
|
||||
this._updateHistoryDelayer = new Delayer<void>(500);
|
||||
this._currentHistoryNavigator = new HistoryNavigator<string>();
|
||||
this._state = this._register(new FindReplaceState());
|
||||
this._register(this._state.addChangeListener((e) => this._onStateChanged(e)));
|
||||
|
||||
|
@ -95,7 +100,10 @@ export class CommonFindController extends Disposable implements editorCommon.IEd
|
|||
return CommonFindController.ID;
|
||||
}
|
||||
|
||||
private _onStateChanged(e:FindReplaceStateChangedEvent): void {
|
||||
private _onStateChanged(e: FindReplaceStateChangedEvent): void {
|
||||
if (e.updateHistory && e.searchString) {
|
||||
this._delayedUpdateHistory();
|
||||
}
|
||||
if (e.isRevealed) {
|
||||
if (this._state.isRevealed) {
|
||||
this._findWidgetVisible.set(true);
|
||||
|
@ -106,10 +114,24 @@ export class CommonFindController extends Disposable implements editorCommon.IEd
|
|||
}
|
||||
}
|
||||
|
||||
protected _delayedUpdateHistory() {
|
||||
this._updateHistoryDelayer.trigger(this._updateHistory.bind(this));
|
||||
}
|
||||
|
||||
protected _updateHistory() {
|
||||
if (this._state.searchString) {
|
||||
this._currentHistoryNavigator.add(this._state.searchString);
|
||||
}
|
||||
}
|
||||
|
||||
public getState(): FindReplaceState {
|
||||
return this._state;
|
||||
}
|
||||
|
||||
public getHistory(): HistoryNavigator<string> {
|
||||
return this._currentHistoryNavigator;
|
||||
}
|
||||
|
||||
public closeFindWidget(): void {
|
||||
this._state.change({
|
||||
isRevealed: false,
|
||||
|
@ -130,7 +152,7 @@ export class CommonFindController extends Disposable implements editorCommon.IEd
|
|||
this._state.change({ isRegex: !this._state.isRegex }, false);
|
||||
}
|
||||
|
||||
public setSearchString(searchString:string): void {
|
||||
public setSearchString(searchString: string): void {
|
||||
this._state.change({ searchString: searchString }, false);
|
||||
}
|
||||
|
||||
|
@ -151,7 +173,7 @@ export class CommonFindController extends Disposable implements editorCommon.IEd
|
|||
return null;
|
||||
}
|
||||
|
||||
protected _start(opts:IFindStartOptions): void {
|
||||
protected _start(opts: IFindStartOptions): void {
|
||||
this.disposeModel();
|
||||
|
||||
if (!this._editor.getModel()) {
|
||||
|
@ -187,7 +209,7 @@ export class CommonFindController extends Disposable implements editorCommon.IEd
|
|||
}
|
||||
}
|
||||
|
||||
public start(opts:IFindStartOptions): void {
|
||||
public start(opts: IFindStartOptions): void {
|
||||
this._start(opts);
|
||||
}
|
||||
|
||||
|
@ -231,6 +253,22 @@ export class CommonFindController extends Disposable implements editorCommon.IEd
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public showPreviousFindTerm(): boolean {
|
||||
let previousTerm = this._currentHistoryNavigator.previous();
|
||||
if (previousTerm) {
|
||||
this._state.change({ searchString: previousTerm }, false, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public showNextFindTerm(): boolean {
|
||||
let nextTerm = this._currentHistoryNavigator.next();
|
||||
if (nextTerm) {
|
||||
this._state.change({ searchString: nextTerm }, false, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@editorAction
|
||||
|
@ -239,7 +277,7 @@ export class StartFindAction extends EditorAction {
|
|||
constructor() {
|
||||
super({
|
||||
id: FIND_IDS.StartFindAction,
|
||||
label: nls.localize('startFindAction',"Find"),
|
||||
label: nls.localize('startFindAction', "Find"),
|
||||
alias: 'Find',
|
||||
precondition: null,
|
||||
kbOpts: {
|
||||
|
@ -253,7 +291,7 @@ export class StartFindAction extends EditorAction {
|
|||
});
|
||||
}
|
||||
|
||||
public run(accessor:ServicesAccessor, editor:editorCommon.ICommonCodeEditor): void {
|
||||
public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void {
|
||||
let controller = CommonFindController.get(editor);
|
||||
if (controller) {
|
||||
controller.start({
|
||||
|
@ -267,7 +305,7 @@ export class StartFindAction extends EditorAction {
|
|||
}
|
||||
|
||||
export abstract class MatchFindAction extends EditorAction {
|
||||
public run(accessor:ServicesAccessor, editor:editorCommon.ICommonCodeEditor): void {
|
||||
public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void {
|
||||
let controller = CommonFindController.get(editor);
|
||||
if (controller && !this._run(controller)) {
|
||||
controller.start({
|
||||
|
@ -280,7 +318,7 @@ export abstract class MatchFindAction extends EditorAction {
|
|||
}
|
||||
}
|
||||
|
||||
protected abstract _run(controller:CommonFindController): boolean;
|
||||
protected abstract _run(controller: CommonFindController): boolean;
|
||||
}
|
||||
|
||||
@editorAction
|
||||
|
@ -300,7 +338,7 @@ export class NextMatchFindAction extends MatchFindAction {
|
|||
});
|
||||
}
|
||||
|
||||
protected _run(controller:CommonFindController): boolean {
|
||||
protected _run(controller: CommonFindController): boolean {
|
||||
return controller.moveToNextMatch();
|
||||
}
|
||||
}
|
||||
|
@ -322,13 +360,13 @@ export class PreviousMatchFindAction extends MatchFindAction {
|
|||
});
|
||||
}
|
||||
|
||||
protected _run(controller:CommonFindController): boolean {
|
||||
protected _run(controller: CommonFindController): boolean {
|
||||
return controller.moveToPrevMatch();
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class SelectionMatchFindAction extends EditorAction {
|
||||
public run(accessor:ServicesAccessor, editor:editorCommon.ICommonCodeEditor): void {
|
||||
public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void {
|
||||
let controller = CommonFindController.get(editor);
|
||||
if (!controller) {
|
||||
return;
|
||||
|
@ -348,7 +386,7 @@ export abstract class SelectionMatchFindAction extends EditorAction {
|
|||
}
|
||||
}
|
||||
|
||||
protected abstract _run(controller:CommonFindController): boolean;
|
||||
protected abstract _run(controller: CommonFindController): boolean;
|
||||
}
|
||||
|
||||
@editorAction
|
||||
|
@ -367,7 +405,7 @@ export class NextSelectionMatchFindAction extends SelectionMatchFindAction {
|
|||
});
|
||||
}
|
||||
|
||||
protected _run(controller:CommonFindController): boolean {
|
||||
protected _run(controller: CommonFindController): boolean {
|
||||
return controller.moveToNextMatch();
|
||||
}
|
||||
}
|
||||
|
@ -388,7 +426,7 @@ export class PreviousSelectionMatchFindAction extends SelectionMatchFindAction {
|
|||
});
|
||||
}
|
||||
|
||||
protected _run(controller:CommonFindController): boolean {
|
||||
protected _run(controller: CommonFindController): boolean {
|
||||
return controller.moveToPrevMatch();
|
||||
}
|
||||
}
|
||||
|
@ -410,7 +448,7 @@ export class StartFindReplaceAction extends EditorAction {
|
|||
});
|
||||
}
|
||||
|
||||
public run(accessor:ServicesAccessor, editor:editorCommon.ICommonCodeEditor): void {
|
||||
public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void {
|
||||
if (editor.getConfiguration().readOnly) {
|
||||
return;
|
||||
}
|
||||
|
@ -428,14 +466,14 @@ export class StartFindReplaceAction extends EditorAction {
|
|||
}
|
||||
|
||||
export interface IMultiCursorFindResult {
|
||||
searchText:string;
|
||||
matchCase:boolean;
|
||||
wholeWord:boolean;
|
||||
searchText: string;
|
||||
matchCase: boolean;
|
||||
wholeWord: boolean;
|
||||
|
||||
currentMatch: Selection;
|
||||
}
|
||||
|
||||
function multiCursorFind(editor:editorCommon.ICommonCodeEditor, changeFindSearchString:boolean): IMultiCursorFindResult {
|
||||
function multiCursorFind(editor: editorCommon.ICommonCodeEditor, changeFindSearchString: boolean): IMultiCursorFindResult {
|
||||
let controller = CommonFindController.get(editor);
|
||||
if (!controller) {
|
||||
return null;
|
||||
|
@ -489,7 +527,7 @@ function multiCursorFind(editor:editorCommon.ICommonCodeEditor, changeFindSearch
|
|||
}
|
||||
|
||||
export abstract class SelectNextFindMatchAction extends EditorAction {
|
||||
protected _getNextMatch(editor:editorCommon.ICommonCodeEditor): Selection {
|
||||
protected _getNextMatch(editor: editorCommon.ICommonCodeEditor): Selection {
|
||||
let r = multiCursorFind(editor, true);
|
||||
if (!r) {
|
||||
return null;
|
||||
|
@ -512,7 +550,7 @@ export abstract class SelectNextFindMatchAction extends EditorAction {
|
|||
}
|
||||
|
||||
export abstract class SelectPreviousFindMatchAction extends EditorAction {
|
||||
protected _getPreviousMatch(editor:editorCommon.ICommonCodeEditor): Selection {
|
||||
protected _getPreviousMatch(editor: editorCommon.ICommonCodeEditor): Selection {
|
||||
let r = multiCursorFind(editor, true);
|
||||
if (!r) {
|
||||
return null;
|
||||
|
@ -550,7 +588,7 @@ export class AddSelectionToNextFindMatchAction extends SelectNextFindMatchAction
|
|||
});
|
||||
}
|
||||
|
||||
public run(accessor:ServicesAccessor, editor:editorCommon.ICommonCodeEditor): void {
|
||||
public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void {
|
||||
let nextMatch = this._getNextMatch(editor);
|
||||
|
||||
if (!nextMatch) {
|
||||
|
@ -575,7 +613,7 @@ export class AddSelectionToPreviousFindMatchAction extends SelectPreviousFindMat
|
|||
});
|
||||
}
|
||||
|
||||
public run(accessor:ServicesAccessor, editor:editorCommon.ICommonCodeEditor): void {
|
||||
public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void {
|
||||
let previousMatch = this._getPreviousMatch(editor);
|
||||
|
||||
if (!previousMatch) {
|
||||
|
@ -599,12 +637,12 @@ export class MoveSelectionToNextFindMatchAction extends SelectNextFindMatchActio
|
|||
precondition: null,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.Focus,
|
||||
primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_D)
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_D)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public run(accessor:ServicesAccessor, editor:editorCommon.ICommonCodeEditor): void {
|
||||
public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void {
|
||||
let nextMatch = this._getNextMatch(editor);
|
||||
|
||||
if (!nextMatch) {
|
||||
|
@ -629,7 +667,7 @@ export class MoveSelectionToPreviousFindMatchAction extends SelectPreviousFindMa
|
|||
});
|
||||
}
|
||||
|
||||
public run(accessor:ServicesAccessor, editor:editorCommon.ICommonCodeEditor): void {
|
||||
public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void {
|
||||
let previousMatch = this._getPreviousMatch(editor);
|
||||
|
||||
if (!previousMatch) {
|
||||
|
@ -643,7 +681,7 @@ export class MoveSelectionToPreviousFindMatchAction extends SelectPreviousFindMa
|
|||
}
|
||||
|
||||
export abstract class AbstractSelectHighlightsAction extends EditorAction {
|
||||
public run(accessor:ServicesAccessor, editor:editorCommon.ICommonCodeEditor): void {
|
||||
public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void {
|
||||
let r = multiCursorFind(editor, true);
|
||||
if (!r) {
|
||||
return;
|
||||
|
@ -713,7 +751,7 @@ export class SelectionHighlighter extends Disposable implements editorCommon.IEd
|
|||
private updateSoon: RunOnceScheduler;
|
||||
private lastWordUnderCursor: Range;
|
||||
|
||||
constructor(editor:editorCommon.ICommonCodeEditor) {
|
||||
constructor(editor: editorCommon.ICommonCodeEditor) {
|
||||
super();
|
||||
this.editor = editor;
|
||||
this.decorations = [];
|
||||
|
@ -812,7 +850,7 @@ export class SelectionHighlighter extends Disposable implements editorCommon.IEd
|
|||
|
||||
// do not overlap with selection (issue #64 and #512)
|
||||
let matches: Range[] = [];
|
||||
for (let i = 0, j = 0, len = allMatches.length, lenJ = selections.length; i < len; ) {
|
||||
for (let i = 0, j = 0, len = allMatches.length, lenJ = selections.length; i < len;) {
|
||||
let match = allMatches[i];
|
||||
|
||||
if (j >= lenJ) {
|
||||
|
@ -943,3 +981,25 @@ CommonEditorRegistry.registerEditorCommand(new FindCommand({
|
|||
primary: KeyMod.Alt | KeyCode.Enter
|
||||
}
|
||||
}));
|
||||
|
||||
CommonEditorRegistry.registerEditorCommand(new FindCommand({
|
||||
id: FIND_IDS.ShowPreviousFindTermAction,
|
||||
precondition: CONTEXT_FIND_WIDGET_VISIBLE,
|
||||
handler: x => x.showPreviousFindTerm(),
|
||||
kbOpts: {
|
||||
weight: CommonEditorRegistry.commandWeight(5),
|
||||
kbExpr: EditorContextKeys.Focus,
|
||||
primary: KeyMod.Alt | KeyCode.UpArrow
|
||||
}
|
||||
}));
|
||||
|
||||
CommonEditorRegistry.registerEditorCommand(new FindCommand({
|
||||
id: FIND_IDS.ShowNextFindTermAction,
|
||||
precondition: CONTEXT_FIND_WIDGET_VISIBLE,
|
||||
handler: x => x.showNextFindTerm(),
|
||||
kbOpts: {
|
||||
weight: CommonEditorRegistry.commandWeight(5),
|
||||
kbExpr: EditorContextKeys.Focus,
|
||||
primary: KeyMod.Alt | KeyCode.DownArrow
|
||||
}
|
||||
}));
|
||||
|
|
|
@ -34,7 +34,9 @@ export const FIND_IDS = {
|
|||
ToggleRegexCommand: 'toggleFindRegex',
|
||||
ReplaceOneAction: 'editor.action.replaceOne',
|
||||
ReplaceAllAction: 'editor.action.replaceAll',
|
||||
SelectAllMatchesAction: 'editor.action.selectAllMatches'
|
||||
SelectAllMatchesAction: 'editor.action.selectAllMatches',
|
||||
ShowPreviousFindTermAction: 'find.history.showPrevious',
|
||||
ShowNextFindTermAction: 'find.history.showNext'
|
||||
};
|
||||
|
||||
export const MATCHES_LIMIT = 999;
|
||||
|
|
|
@ -10,6 +10,7 @@ import {Range} from 'vs/editor/common/core/range';
|
|||
|
||||
export interface FindReplaceStateChangedEvent {
|
||||
moveCursor: boolean;
|
||||
updateHistory: boolean;
|
||||
|
||||
searchString: boolean;
|
||||
replaceString: boolean;
|
||||
|
@ -90,6 +91,7 @@ export class FindReplaceState implements IDisposable {
|
|||
public changeMatchInfo(matchesPosition:number, matchesCount:number, currentMatch:Range): void {
|
||||
let changeEvent:FindReplaceStateChangedEvent = {
|
||||
moveCursor: false,
|
||||
updateHistory: false,
|
||||
searchString: false,
|
||||
replaceString: false,
|
||||
isRevealed: false,
|
||||
|
@ -135,9 +137,10 @@ export class FindReplaceState implements IDisposable {
|
|||
}
|
||||
}
|
||||
|
||||
public change(newState:INewFindReplaceState, moveCursor:boolean): void {
|
||||
public change(newState:INewFindReplaceState, moveCursor:boolean, updateHistory: boolean = true): void {
|
||||
let changeEvent:FindReplaceStateChangedEvent = {
|
||||
moveCursor: moveCursor,
|
||||
updateHistory: updateHistory,
|
||||
searchString: false,
|
||||
replaceString: false,
|
||||
isRevealed: false,
|
||||
|
|
|
@ -15,10 +15,12 @@ import {
|
|||
NextMatchFindAction, StartFindAction, SelectHighlightsAction
|
||||
} from 'vs/editor/contrib/find/common/findController';
|
||||
import {withMockCodeEditor} from 'vs/editor/test/common/mocks/mockCodeEditor';
|
||||
import {HistoryNavigator} from 'vs/base/common/history';
|
||||
|
||||
class TestFindController extends CommonFindController {
|
||||
|
||||
public hasFocus: boolean;
|
||||
public delayUpdateHistory: boolean = false;
|
||||
|
||||
protected _start(opts:IFindStartOptions): void {
|
||||
super._start(opts);
|
||||
|
@ -27,6 +29,14 @@ class TestFindController extends CommonFindController {
|
|||
this.hasFocus = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected _delayedUpdateHistory() {
|
||||
if (this.delayUpdateHistory) {
|
||||
super._delayedUpdateHistory();
|
||||
} else {
|
||||
this._updateHistory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suite('FindController', () => {
|
||||
|
@ -196,4 +206,125 @@ suite('FindController', () => {
|
|||
assert.equal(findController.getState().searchScope, null);
|
||||
});
|
||||
});
|
||||
|
||||
test('find term is added to history on state change', () => {
|
||||
withMockCodeEditor([
|
||||
'var x = (3 * 5)',
|
||||
'var y = (3 * 5)',
|
||||
'var z = (3 * 5)',
|
||||
], {}, (editor, cursor) => {
|
||||
|
||||
let findController = editor.registerAndInstantiateContribution<TestFindController>(TestFindController);
|
||||
findController.getState().change({ searchString: '1' }, false);
|
||||
findController.getState().change({ searchString: '2' }, false);
|
||||
findController.getState().change({ searchString: '3' }, false);
|
||||
|
||||
assert.deepEqual(['1', '2', '3'], toArray(findController.getHistory()));
|
||||
});
|
||||
});
|
||||
|
||||
test('find term is added with delay', (done) => {
|
||||
withMockCodeEditor([
|
||||
'var x = (3 * 5)',
|
||||
'var y = (3 * 5)',
|
||||
'var z = (3 * 5)',
|
||||
], {}, (editor, cursor) => {
|
||||
|
||||
let findController = editor.registerAndInstantiateContribution<TestFindController>(TestFindController);
|
||||
findController.delayUpdateHistory = true;
|
||||
findController.getState().change({ searchString: '1' }, false);
|
||||
findController.getState().change({ searchString: '2' }, false);
|
||||
findController.getState().change({ searchString: '3' }, false);
|
||||
|
||||
setTimeout(function() {
|
||||
assert.deepEqual(['3'], toArray(findController.getHistory()));
|
||||
done();
|
||||
}, 500);
|
||||
});
|
||||
});
|
||||
|
||||
test('show previous find term', () => {
|
||||
withMockCodeEditor([
|
||||
'var x = (3 * 5)',
|
||||
'var y = (3 * 5)',
|
||||
'var z = (3 * 5)',
|
||||
], {}, (editor, cursor) => {
|
||||
|
||||
let findController = editor.registerAndInstantiateContribution<TestFindController>(TestFindController);
|
||||
findController.getState().change({ searchString: '1' }, false);
|
||||
findController.getState().change({ searchString: '2' }, false);
|
||||
findController.getState().change({ searchString: '3' }, false);
|
||||
|
||||
findController.showPreviousFindTerm();
|
||||
assert.deepEqual('2', findController.getState().searchString);
|
||||
});
|
||||
});
|
||||
|
||||
test('show previous find term do not update history', () => {
|
||||
withMockCodeEditor([
|
||||
'var x = (3 * 5)',
|
||||
'var y = (3 * 5)',
|
||||
'var z = (3 * 5)',
|
||||
], {}, (editor, cursor) => {
|
||||
|
||||
let findController = editor.registerAndInstantiateContribution<TestFindController>(TestFindController);
|
||||
findController.getState().change({ searchString: '1' }, false);
|
||||
findController.getState().change({ searchString: '2' }, false);
|
||||
findController.getState().change({ searchString: '3' }, false);
|
||||
|
||||
findController.showPreviousFindTerm();
|
||||
assert.deepEqual(['1', '2', '3'], toArray(findController.getHistory()));
|
||||
});
|
||||
});
|
||||
|
||||
test('show next find term', () => {
|
||||
withMockCodeEditor([
|
||||
'var x = (3 * 5)',
|
||||
'var y = (3 * 5)',
|
||||
'var z = (3 * 5)',
|
||||
], {}, (editor, cursor) => {
|
||||
|
||||
let findController = editor.registerAndInstantiateContribution<TestFindController>(TestFindController);
|
||||
findController.getState().change({ searchString: '1' }, false);
|
||||
findController.getState().change({ searchString: '2' }, false);
|
||||
findController.getState().change({ searchString: '3' }, false);
|
||||
findController.getState().change({ searchString: '4' }, false);
|
||||
|
||||
findController.showPreviousFindTerm();
|
||||
findController.showPreviousFindTerm();
|
||||
findController.showNextFindTerm();
|
||||
assert.deepEqual('3', findController.getState().searchString);
|
||||
});
|
||||
});
|
||||
|
||||
test('show next find term do not update history', () => {
|
||||
withMockCodeEditor([
|
||||
'var x = (3 * 5)',
|
||||
'var y = (3 * 5)',
|
||||
'var z = (3 * 5)',
|
||||
], {}, (editor, cursor) => {
|
||||
|
||||
let findController = editor.registerAndInstantiateContribution<TestFindController>(TestFindController);
|
||||
findController.getState().change({ searchString: '1' }, false);
|
||||
findController.getState().change({ searchString: '2' }, false);
|
||||
findController.getState().change({ searchString: '3' }, false);
|
||||
findController.getState().change({ searchString: '4' }, false);
|
||||
|
||||
findController.showPreviousFindTerm();
|
||||
findController.showPreviousFindTerm();
|
||||
findController.showNextFindTerm();
|
||||
assert.deepEqual(['1', '2', '3', '4'], toArray(findController.getHistory()));
|
||||
});
|
||||
});
|
||||
|
||||
function toArray(historyNavigator: HistoryNavigator<string>): string[] {
|
||||
let result = [];
|
||||
historyNavigator.first();
|
||||
if (historyNavigator.current()) {
|
||||
do {
|
||||
result.push(historyNavigator.current());
|
||||
} while (historyNavigator.next());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import * as nls from 'vs/nls';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import {RunOnceScheduler} from 'vs/base/common/async';
|
||||
import {KeyCode, KeyMod} from 'vs/base/common/keyCodes';
|
||||
import {KeyCode, KeyMod, KeyChord} from 'vs/base/common/keyCodes';
|
||||
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
|
@ -585,7 +585,7 @@ class UnFoldRecursivelyAction extends FoldingAction<void> {
|
|||
precondition: null,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.TextFocus,
|
||||
primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_CLOSE_SQUARE_BRACKET)
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_CLOSE_SQUARE_BRACKET)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -641,7 +641,7 @@ class FoldRecursivelyAction extends FoldingAction<void> {
|
|||
precondition: null,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.TextFocus,
|
||||
primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_OPEN_SQUARE_BRACKET)
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_OPEN_SQUARE_BRACKET)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -662,7 +662,7 @@ class FoldAllAction extends FoldingAction<void> {
|
|||
precondition: null,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.TextFocus,
|
||||
primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_0)
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_0)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -683,7 +683,7 @@ class UnfoldAllAction extends FoldingAction<void> {
|
|||
precondition: null,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.TextFocus,
|
||||
primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_J)
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_J)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -718,7 +718,7 @@ CommonEditorRegistry.registerEditorAction(
|
|||
precondition: null,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.TextFocus,
|
||||
primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_1)
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_1)
|
||||
}
|
||||
})
|
||||
);
|
||||
|
@ -730,7 +730,7 @@ CommonEditorRegistry.registerEditorAction(
|
|||
precondition: null,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.TextFocus,
|
||||
primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_2)
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_2)
|
||||
}
|
||||
})
|
||||
);
|
||||
|
@ -742,7 +742,7 @@ CommonEditorRegistry.registerEditorAction(
|
|||
precondition: null,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.TextFocus,
|
||||
primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_3)
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_3)
|
||||
}
|
||||
})
|
||||
);
|
||||
|
@ -754,7 +754,7 @@ CommonEditorRegistry.registerEditorAction(
|
|||
precondition: null,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.TextFocus,
|
||||
primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_4)
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_4)
|
||||
}
|
||||
})
|
||||
);
|
||||
|
@ -766,7 +766,7 @@ CommonEditorRegistry.registerEditorAction(
|
|||
precondition: null,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.TextFocus,
|
||||
primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_5)
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_5)
|
||||
}
|
||||
})
|
||||
);
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue