Merge branch 'master' into joh/ftp

This commit is contained in:
Johannes Rieken 2017-09-12 09:10:22 +02:00
commit 9c3fb2ffd1
59 changed files with 1000 additions and 883 deletions

View file

@ -50,6 +50,11 @@
"scopeName": "text.git-rebase",
"path": "./syntaxes/git-rebase.tmLanguage.json"
}
]
],
"configurationDefaults": {
"[git-commit]": {
"editor.rulers": [72]
}
}
}
}

View file

@ -7,6 +7,13 @@
"foreground": "#6688cc"
}
},
{
"scope": "meta.embedded",
"settings": {
"background": "#000c18",
"foreground": "#6688cc"
}
},
{
"name": "Comment",
"scope": "comment",

View file

@ -54,6 +54,13 @@
"foreground": "#d3af86"
}
},
{
"scope": "meta.embedded",
"settings": {
"background": "#221a0f",
"foreground": "#d3af86"
}
},
{
"name": "Text",
"scope": "variable.parameter.function",

View file

@ -51,6 +51,13 @@
"foreground": "#c5c8c6ff"
}
},
{
"scope": "meta.embedded",
"settings": {
"background": "#1e1e1e",
"foreground": "#C5C8C6"
}
},
{
"name": "Comment",
"scope": "comment",

View file

@ -96,6 +96,13 @@
"foreground": "#F8F8F2"
}
},
{
"scope": "meta.embedded",
"settings": {
"background": "#272822",
"foreground": "#F8F8F2"
}
},
{
"name": "Comment",
"scope": "comment",

View file

@ -7,6 +7,13 @@
"foreground": "#333333"
}
},
{
"scope": "meta.embedded",
"settings": {
"background": "#F5F5F5",
"foreground": "#333333"
}
},
{
"name": "Comments",
"scope": [

View file

@ -1,5 +1,5 @@
{
"tokenColors": "./red.tmTheme",
"name": "Red",
"colors": {
// window
"activityBar.background": "#580000",
@ -57,5 +57,342 @@
"extensionButton.prominentBackground": "#cc3333",
"extensionButton.prominentHoverBackground": "#cc333388"
},
"name": "Red"
"tokenColors": [
{
"settings": {
"background": "#390000",
"caret": "#970000",
"foreground": "#F8F8F8",
"invisibles": "#c10000",
"lineHighlight": "#0000004A",
"selection": "#750000"
}
},
{
"scope": "meta.embedded",
"settings": {
"background": "#390000",
"foreground": "#F8F8F8"
}
},
{
"name": "Comment",
"scope": "comment",
"settings": {
"fontStyle": "italic",
"foreground": "#e7c0c0ff"
}
},
{
"name": "Constant",
"scope": "constant",
"settings": {
"fontStyle": "",
"foreground": "#994646ff"
}
},
{
"name": "Keyword",
"scope": "keyword",
"settings": {
"fontStyle": "",
"foreground": "#f12727ff"
}
},
{
"name": "Entity",
"scope": "entity",
"settings": {
"fontStyle": "",
"foreground": "#fec758ff"
}
},
{
"name": "Storage",
"scope": "storage",
"settings": {
"fontStyle": "bold",
"foreground": "#ff6262ff"
}
},
{
"name": "String",
"scope": "string",
"settings": {
"fontStyle": "",
"foreground": "#cd8d8dff"
}
},
{
"name": "Support",
"scope": "support",
"settings": {
"fontStyle": "",
"foreground": "#9df39fff"
}
},
{
"name": "Variable",
"scope": "variable",
"settings": {
"fontStyle": "italic",
"foreground": "#fb9a4bff"
}
},
{
"name": "Invalid",
"scope": "invalid",
"settings": {
"background": "#fd6209ff",
"foreground": "#ffffffff"
}
},
{
"name": "Embedded Source",
"scope": "text source",
"settings": {
"background": "#b0b3ba14"
}
},
{
"name": "Embedded Source (Bright)",
"scope": "text.html.ruby source",
"settings": {
"background": "#b1b3ba21"
}
},
{
"name": "Entity inherited-class",
"scope": "entity.other.inherited-class",
"settings": {
"fontStyle": "underline",
"foreground": "#aa5507ff"
}
},
{
"name": "String embedded-source",
"scope": "string.quoted source",
"settings": {
"fontStyle": "",
"foreground": "#9df39fff"
}
},
{
"name": "String constant",
"scope": "string constant",
"settings": {
"fontStyle": "",
"foreground": "#ffe862ff"
}
},
{
"name": "String.regexp",
"scope": "string.regexp",
"settings": {
"foreground": "#ffb454ff"
}
},
{
"name": "String variable",
"scope": "string variable",
"settings": {
"foreground": "#edef7dff"
}
},
{
"name": "Support.function",
"scope": "support.function",
"settings": {
"fontStyle": "",
"foreground": "#ffb454ff"
}
},
{
"name": "Support.constant",
"scope": "support.constant",
"settings": {
"fontStyle": "",
"foreground": "#eb939aff"
}
},
{
"name": "Doctype/XML Processing",
"scope": [
"declaration.sgml.html declaration.doctype",
"declaration.sgml.html declaration.doctype entity",
"declaration.sgml.html declaration.doctype string",
"declaration.xml-processing",
"declaration.xml-processing entity",
"declaration.xml-processing string"
],
"settings": {
"fontStyle": "",
"foreground": "#73817dff"
}
},
{
"name": "Meta.tag.A",
"scope": [
"declaration.tag",
"declaration.tag entity",
"meta.tag",
"meta.tag entity"
],
"settings": {
"fontStyle": "",
"foreground": "#ec0d1eff"
}
},
{
"name": "css tag-name",
"scope": "meta.selector.css entity.name.tag",
"settings": {
"fontStyle": "",
"foreground": "#aa5507ff"
}
},
{
"name": "css#id",
"scope": "meta.selector.css entity.other.attribute-name.id",
"settings": {
"foreground": "#fec758ff"
}
},
{
"name": "css.class",
"scope": "meta.selector.css entity.other.attribute-name.class",
"settings": {
"fontStyle": "",
"foreground": "#41a83eff"
}
},
{
"name": "css property-name:",
"scope": "support.type.property-name.css",
"settings": {
"fontStyle": "",
"foreground": "#96dd3bff"
}
},
{
"name": "css property-value;",
"scope": [
"meta.property-group support.constant.property-value.css",
"meta.property-value support.constant.property-value.css"
],
"settings": {
"fontStyle": "italic",
"foreground": "#ffe862ff"
}
},
{
"name": "css additional-constants",
"scope": [
"meta.property-value support.constant.named-color.css",
"meta.property-value constant"
],
"settings": {
"fontStyle": "",
"foreground": "#ffe862ff"
}
},
{
"name": "css @at-rule",
"scope": "meta.preprocessor.at-rule keyword.control.at-rule",
"settings": {
"foreground": "#fd6209ff"
}
},
{
"name": "css constructor.argument",
"scope": "meta.constructor.argument.css",
"settings": {
"fontStyle": "",
"foreground": "#ec9799ff"
}
},
{
"name": "diff.header",
"scope": [
"meta.diff",
"meta.diff.header"
],
"settings": {
"background": "#0b2f20ff",
"fontStyle": "italic",
"foreground": "#f8f8f8ff"
}
},
{
"name": "diff.deleted",
"scope": "markup.deleted",
"settings": {
"background": "#fedcddff",
"foreground": "#ec9799ff"
}
},
{
"name": "diff.changed",
"scope": "markup.changed",
"settings": {
"background": "#c4b14aff",
"foreground": "#f8f8f8ff"
}
},
{
"name": "diff.inserted",
"scope": "markup.inserted",
"settings": {
"background": "#9bf199ff",
"foreground": "#41a83eff"
}
},
{
"name": "Markup Quote",
"scope": "markup.quote",
"settings": {
"foreground": "#f12727ff"
}
},
{
"name": "Markup Lists",
"scope": "markup.list",
"settings": {
"foreground": "#ff6262ff"
}
},
{
"name": "Markup Styling",
"scope": [
"markup.bold",
"markup.italic"
],
"settings": {
"foreground": "#fb9a4bff"
}
},
{
"name": "Markup Inline",
"scope": "markup.inline.raw",
"settings": {
"fontStyle": "",
"foreground": "#cd8d8dff"
}
},
{
"name": "Markup Headings",
"scope": "markup.heading",
"settings": {
"foreground": "#fec758ff"
}
},
{
"name": "Markup Setext Header",
"scope": "markup.heading.setext",
"settings": {
"fontStyle": "",
"foreground": "#fec758ff"
}
}
]
}

View file

@ -1,514 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>name</key>
<string>Red</string>
<key>settings</key>
<array>
<dict>
<key>settings</key>
<dict>
<key>background</key>
<string>#390000</string>
<key>caret</key>
<string>#970000</string>
<key>foreground</key>
<string>#F8F8F8</string>
<key>invisibles</key>
<string>#c10000</string>
<key>lineHighlight</key>
<string>#0000004A</string>
<key>selection</key>
<string>#750000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Comment</string>
<key>scope</key>
<string>comment</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#e7c0c0ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Constant</string>
<key>scope</key>
<string>constant</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#994646ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Keyword</string>
<key>scope</key>
<string>keyword</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#f12727ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Entity</string>
<key>scope</key>
<string>entity</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#fec758ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Storage</string>
<key>scope</key>
<string>storage</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#ff6262ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>String</string>
<key>scope</key>
<string>string</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#cd8d8dff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Support</string>
<key>scope</key>
<string>support</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#9df39fff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Variable</string>
<key>scope</key>
<string>variable</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#fb9a4bff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Invalid</string>
<key>scope</key>
<string>invalid</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#fd6209ff</string>
<key>foreground</key>
<string>#ffffffff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Embedded Source</string>
<key>scope</key>
<string>text source</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#b0b3ba14</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Embedded Source (Bright)</string>
<key>scope</key>
<string>text.html.ruby source</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#b1b3ba21</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Entity inherited-class</string>
<key>scope</key>
<string>entity.other.inherited-class</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>underline</string>
<key>foreground</key>
<string>#aa5507ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>String embedded-source</string>
<key>scope</key>
<string>string.quoted source</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#9df39fff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>String constant</string>
<key>scope</key>
<string>string constant</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#ffe862ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>String.regexp</string>
<key>scope</key>
<string>string.regexp</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ffb454ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>String variable</string>
<key>scope</key>
<string>string variable</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#edef7dff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Support.function</string>
<key>scope</key>
<string>support.function</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#ffb454ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Support.constant</string>
<key>scope</key>
<string>support.constant</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#eb939aff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Doctype&#x2f;XML Processing</string>
<key>scope</key>
<string>declaration.sgml.html declaration.doctype, declaration.sgml.html declaration.doctype entity, declaration.sgml.html declaration.doctype string, declaration.xml-processing, declaration.xml-processing entity, declaration.xml-processing string</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#73817dff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Meta.tag.A</string>
<key>scope</key>
<string>declaration.tag, declaration.tag entity, meta.tag, meta.tag entity</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#ec0d1eff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css tag-name</string>
<key>scope</key>
<string>meta.selector.css entity.name.tag</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#aa5507ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css#id</string>
<key>scope</key>
<string>meta.selector.css entity.other.attribute-name.id</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#fec758ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css.class</string>
<key>scope</key>
<string>meta.selector.css entity.other.attribute-name.class</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#41a83eff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css property-name:</string>
<key>scope</key>
<string>support.type.property-name.css</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#96dd3bff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css property-value;</string>
<key>scope</key>
<string>meta.property-group support.constant.property-value.css, meta.property-value support.constant.property-value.css</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#ffe862ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css additional-constants</string>
<key>scope</key>
<string>meta.property-value support.constant.named-color.css, meta.property-value constant</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#ffe862ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css @at-rule</string>
<key>scope</key>
<string>meta.preprocessor.at-rule keyword.control.at-rule</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#fd6209ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css constructor.argument</string>
<key>scope</key>
<string>meta.constructor.argument.css</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#ec9799ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>diff.header</string>
<key>scope</key>
<string>meta.diff, meta.diff.header</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#0b2f20ff</string>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#f8f8f8ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>diff.deleted</string>
<key>scope</key>
<string>markup.deleted</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#fedcddff</string>
<key>foreground</key>
<string>#ec9799ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>diff.changed</string>
<key>scope</key>
<string>markup.changed</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#c4b14aff</string>
<key>foreground</key>
<string>#f8f8f8ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>diff.inserted</string>
<key>scope</key>
<string>markup.inserted</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#9bf199ff</string>
<key>foreground</key>
<string>#41a83eff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup Quote</string>
<key>scope</key>
<string>markup.quote</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f12727ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup Lists</string>
<key>scope</key>
<string>markup.list</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ff6262ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup Styling</string>
<key>scope</key>
<string>markup.bold, markup.italic</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#fb9a4bff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup Inline</string>
<key>scope</key>
<string>markup.inline.raw</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#cd8d8dff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup Headings</string>
<key>scope</key>
<string>markup.heading</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#fec758ff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup Setext Header</string>
<key>scope</key>
<string>markup.heading.setext</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#fec758ff</string>
</dict>
</dict>
</array>
<key>uuid</key>
<string>AC0A28C5-65E6-42A6-AD05-4D01735652EE</string>
<key>colorSpaceName</key>
<string>sRGB</string>
<key>semanticClass</key>
<string>theme.dark.django</string>
</dict>
</plist>

View file

@ -7,6 +7,13 @@
"foreground": "#93A1A1"
}
},
{
"scope": "meta.embedded",
"settings": {
"background": "#002B36",
"foreground": "#93A1A1"
}
},
{
"name": "Comment",
"scope": "comment",

View file

@ -7,6 +7,13 @@
"foreground": "#657B83"
}
},
{
"scope": "meta.embedded",
"settings": {
"background": "#FDF6E3",
"foreground": "#657B83"
}
},
{
"name": "Comment",
"scope": "comment",

View file

@ -60,6 +60,13 @@
"foreground": "#FFFFFF"
}
},
{
"scope": "meta.embedded",
"settings": {
"background": "#002451",
"foreground": "#FFFFFF"
}
},
{
"name": "Comment",
"scope": "comment",

View file

@ -251,7 +251,7 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
const detail = details[0];
item.detail = Previewer.plain(detail.displayParts);
item.documentation = Previewer.plainDocumentation(detail.documentation, detail.tags);
item.documentation = Previewer.markdownDocumentation(detail.documentation, detail.tags);
if (detail && this.config.useCodeSnippetsOnMethodSuggest && (item.kind === CompletionItemKind.Function || item.kind === CompletionItemKind.Method)) {
return this.isValidFunctionCompletionContext(filepath, item.position).then(shouldCompleteFunction => {

View file

@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as Proto from '../protocol';
import { MarkdownString } from 'vscode';
export function plain(parts: Proto.SymbolDisplayPart[]): string {
if (!parts) {
@ -24,20 +25,15 @@ export function tagsMarkdownPreview(tags: Proto.JSDocTagInfo[]): string {
.join(' \n\n');
}
function tagsPlainPreview(tags: Proto.JSDocTagInfo[]): string {
return (tags || [])
.map(tag => {
const label = `@${tag.name}`;
if (!tag.text) {
return label;
}
return label + (tag.text.match(/\r\n|\n/g) ? '\n' + tag.text : `${tag.text}`);
})
.join('\n\ngit');
}
export function plainDocumentation(documentation: Proto.SymbolDisplayPart[], tags: Proto.JSDocTagInfo[]): string {
const processedDocumentation = plain(documentation).replace(/\n([ \t]*\n)?/gm, (x) => x.length >= 2 ? '\n\n' : ' ');
const parts = [processedDocumentation, tagsPlainPreview(tags)];
return parts.filter(x => x).join('\n\n');
export function markdownDocumentation(
documentation: Proto.SymbolDisplayPart[],
tags: Proto.JSDocTagInfo[]
): MarkdownString {
const out = new MarkdownString();
out.appendMarkdown(plain(documentation));
const tagsPreview = tagsMarkdownPreview(tags);
if (tagsPreview) {
out.appendMarkdown('\n\n' + tagsPreview);
}
return out;
}

View file

@ -59,7 +59,7 @@ export default class TypeScriptSignatureHelpProvider implements SignatureHelpPro
}
});
signature.label += Previewer.plain(item.suffixDisplayParts);
signature.documentation = Previewer.plainDocumentation(item.documentation, item.tags);
signature.documentation = Previewer.markdownDocumentation(item.documentation, item.tags);
result.signatures.push(signature);
});

2
npm-shrinkwrap.json generated
View file

@ -574,7 +574,7 @@
"xterm": {
"version": "3.0.0",
"from": "Tyriar/xterm.js#vscode-release/1.17",
"resolved": "git+https://github.com/Tyriar/xterm.js.git#fb7de4e8d90d20a94d3847ea857b5394a09bd771"
"resolved": "git+https://github.com/Tyriar/xterm.js.git#c3039b4d63b5c0e4a0c993e04714ad62fd056185"
},
"yauzl": {
"version": "2.8.0",

View file

@ -87,7 +87,7 @@
"gulp-replace": "^0.5.4",
"gulp-shell": "^0.5.2",
"gulp-sourcemaps": "^1.11.0",
"gulp-tsb": "^2.0.4",
"gulp-tsb": "2.0.4",
"gulp-tslint": "^7.0.1",
"gulp-uglify": "^3.0.0",
"gulp-util": "^3.0.6",

View file

@ -411,8 +411,8 @@ export class IPCServer implements IChannelServer, IRoutingChannelClient, IDispos
}
dispose(): void {
this.channels = null;
this.channelClients = null;
this.channels = Object.create(null);
this.channelClients = Object.create(null);
this.onClientAdded.dispose();
}
}

View file

@ -105,7 +105,7 @@ export class LaunchService implements ILaunchService {
cli: args,
userEnv,
forceNewWindow: args['new-window'],
preferNewWindow: !args['reuse-window'],
preferNewWindow: !args['reuse-window'] && !args.wait,
forceReuseWindow: args['reuse-window'],
diffMode: args.diff,
addMode: args.add

View file

@ -176,11 +176,6 @@ export class WindowsManager implements IWindowsMainService {
state.folderPath = state.workspacePath;
state.workspacePath = void 0;
}
// TODO@Ben migration to new workspace ID
if (state.workspace) {
state.workspace.id = this.workspacesService.getWorkspaceId(state.workspace.configPath);
}
});
}
@ -277,7 +272,6 @@ export class WindowsManager implements IWindowsMainService {
private onBeforeQuit(): void {
const currentWindowsState: ILegacyWindowsState = {
openedWindows: [],
openedFolders: [], // TODO@Ben migration so that old clients do not fail over data (prevents NPEs)
lastPluginDevelopmentHostWindow: this.windowsState.lastPluginDevelopmentHostWindow,
lastActiveWindow: this.lastClosedWindowState
};

View file

@ -45,6 +45,9 @@
.monaco-editor .parameter-hints-widget .docs {
padding: 0 10px 0 5px;
}
.monaco-editor .parameter-hints-widget .docs .code {
white-space: pre-wrap;
}

View file

@ -25,7 +25,7 @@ import { CharacterSet } from 'vs/editor/common/core/characterClassifier';
import { IConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions';
import { ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
import { registerThemingParticipant, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService';
import { editorHoverBackground, editorHoverBorder } from 'vs/platform/theme/common/colorRegistry';
import { editorHoverBackground, editorHoverBorder, textLinkForeground } from 'vs/platform/theme/common/colorRegistry';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IModeService } from 'vs/editor/common/services/modeService';
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/browser/markdownRenderer';
@ -507,4 +507,9 @@ registerThemingParticipant((theme, collector) => {
if (background) {
collector.addRule(`.monaco-editor .parameter-hints-widget { background-color: ${background}; }`);
}
const link = theme.getColor(textLinkForeground);
if (link) {
collector.addRule(`.monaco-editor .parameter-hints-widget a { color: ${link}; }`);
}
});

View file

@ -213,7 +213,6 @@
box-sizing: border-box;
height: 100%;
width: 100%;
white-space: pre-wrap;
}
.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .header > .type {
@ -231,6 +230,11 @@
padding: 4px 5px;
}
.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .docs .code {
white-space: pre-wrap;
word-wrap: break-word;
}
.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > p:empty {
display: none;
}

View file

@ -28,7 +28,7 @@ import { alert } from 'vs/base/browser/ui/aria/aria';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { attachListStyler } from 'vs/platform/theme/common/styler';
import { IThemeService, ITheme, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { registerColor, editorWidgetBackground, listFocusBackground, activeContrastBorder, listHighlightForeground, editorForeground, editorWidgetBorder, focusBorder } from 'vs/platform/theme/common/colorRegistry';
import { registerColor, editorWidgetBackground, listFocusBackground, activeContrastBorder, listHighlightForeground, editorForeground, editorWidgetBorder, focusBorder, textLinkForeground } from 'vs/platform/theme/common/colorRegistry';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/browser/markdownRenderer';
import { IModeService } from 'vs/editor/common/services/modeService';
@ -1079,4 +1079,9 @@ registerThemingParticipant((theme, collector) => {
if (foreground) {
collector.addRule(`.monaco-editor .suggest-widget { color: ${foreground}; }`);
}
const link = theme.getColor(textLinkForeground);
if (link) {
collector.addRule(`.monaco-editor .suggest-widget a { color: ${link}; }`);
}
});

View file

@ -225,22 +225,6 @@ export class BackupMainService implements IBackupMainService {
const hasBackups = this.hasBackupsSync(backupPath);
const missingWorkspace = hasBackups && !fs.existsSync(workspacePath);
// TODO@Ben migration from old workspace ID to new
if (hasBackups && !missingWorkspace && !isSingleFolderWorkspaceIdentifier(workspaceId) && workspaceId.id !== this.workspacesService.getWorkspaceId(workspacePath)) {
staleBackupWorkspaces.push({ workspaceIdentifier: workspaceId, backupPath, target: workspaceOrFolder.target });
const identifier = { id: this.workspacesService.getWorkspaceId(workspacePath), configPath: workspacePath } as IWorkspaceIdentifier;
this.pushBackupPathsSync(identifier, this.backups.rootWorkspaces);
const newWorkspaceBackupPath = path.join(this.backupHome, identifier.id);
try {
fs.renameSync(backupPath, newWorkspaceBackupPath);
} catch (ex) {
this.logService.error(`Backup: Could not rename backup folder for legacy workspace: ${ex.toString()}`);
this.removeBackupPathSync(identifier, this.backups.rootWorkspaces);
}
}
// If the workspace/folder has no backups, make sure to delete it
// If the workspace/folder has backups, but the target workspace is missing, convert backups to empty ones
if (!hasBackups || missingWorkspace) {

View file

@ -204,7 +204,7 @@ export interface IEditorInput extends IDisposable {
/**
* Returns the display description of this input.
*/
getDescription(verbose?: boolean): string;
getDescription(verbosity?: Verbosity): string;
/**
* Returns the display title of this input.

View file

@ -79,6 +79,12 @@ export interface IView {
name: string;
}
export interface IColor {
id: string;
description: string;
defaults: { light: string, dark: string, highContrast: string };
}
export interface IExtensionContributions {
commands?: ICommand[];
configuration?: IConfiguration;
@ -90,7 +96,9 @@ export interface IExtensionContributions {
menus?: { [context: string]: IMenu[] };
snippets?: ISnippet[];
themes?: ITheme[];
iconThemes?: ITheme[];
views?: { [location: string]: IView[] };
colors: IColor[];
}
export interface IExtensionManifest {

View file

@ -780,6 +780,16 @@ export const SUPPORTED_ENCODINGS: { [encoding: string]: { labelLong: string; lab
labelLong: 'Simplified Chinese (GB 2312)',
labelShort: 'GB 2312',
order: 45
},
cp865: {
labelLong: 'Nordic DOS (CP 865)',
labelShort: 'CP 865',
order: 46
},
cp850: {
labelLong: 'Western European DOS (CP 850)',
labelShort: 'CP 850',
order: 47
}
};

View file

@ -141,8 +141,7 @@ export class LifecycleService implements ILifecycleService {
// Windows/Linux: we quit when all windows have closed
// Mac: we only quit when quit was requested
// --wait: we quit when all windows are closed
if (this.quitRequested || process.platform !== 'darwin' || this.environmentService.wait) {
if (this.quitRequested || process.platform !== 'darwin') {
app.quit();
}
});

View file

@ -105,7 +105,7 @@ export class ColorExtensionPoint {
return;
}
let defaults = extension.defaults;
if (typeof defaults !== 'object' || typeof defaults.light !== 'string' || typeof defaults.dark !== 'string' || typeof defaults.highContrast !== 'string') {
if (!defaults || typeof defaults !== 'object' || typeof defaults.light !== 'string' || typeof defaults.dark !== 'string' || typeof defaults.highContrast !== 'string') {
collector.error(nls.localize('invalid.defaults', "'configuration.colors.defaults' must be defined and must contain 'light', 'dark' and 'highContrast'"));
return;
}

View file

@ -19,15 +19,8 @@ import { ILogService } from 'vs/platform/log/common/log';
import { isEqual, isEqualOrParent } from 'vs/base/common/paths';
import { coalesce } from 'vs/base/common/arrays';
import { createHash } from 'crypto';
import URI from 'vs/base/common/uri';
import * as json from 'vs/base/common/json';
// TODO@Ben migration
export interface ILegacyStoredWorkspace {
id: string;
folders: string[];
}
export class WorkspacesMainService implements IWorkspacesMainService {
public _serviceBrand: any;
@ -108,13 +101,6 @@ export class WorkspacesMainService implements IWorkspacesMainService {
throw new Error(`${path} cannot be parsed as JSON file (${error}).`);
}
// TODO@Ben migration
const legacyStoredWorkspace = (<any>storedWorkspace) as ILegacyStoredWorkspace;
if (legacyStoredWorkspace.folders.some(folder => typeof folder === 'string')) {
storedWorkspace.folders = legacyStoredWorkspace.folders.map(folder => ({ path: URI.parse(folder).fsPath }));
writeFileSync(path, JSON.stringify(storedWorkspace, null, '\t'));
}
// Filter out folders which do not have a path set
if (Array.isArray(storedWorkspace.folders)) {
storedWorkspace.folders = storedWorkspace.folders.filter(folder => !!folder.path);

View file

@ -20,7 +20,7 @@ import { RunOnceScheduler } from 'vs/base/common/async';
import { isMacintosh } from 'vs/base/common/platform';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { Position, POSITIONS } from 'vs/platform/editor/common/editor';
import { IEditorGroupService, ITabOptions, GroupArrangement, GroupOrientation } from 'vs/workbench/services/group/common/groupService';
import { IEditorGroupService, IEditorTabOptions, GroupArrangement, GroupOrientation } from 'vs/workbench/services/group/common/groupService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
@ -115,7 +115,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
private layoutVertically: boolean;
private tabOptions: ITabOptions;
private tabOptions: IEditorTabOptions;
private silos: Builder[];
private silosSize: number[];
@ -225,7 +225,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
this.extensionService.onReady().then(() => this.onExtensionsReady());
}
private updateTabOptions(tabOptions: ITabOptions, refresh?: boolean): void {
private updateTabOptions(tabOptions: IEditorTabOptions, refresh?: boolean): void {
const tabCloseButton = this.tabOptions ? this.tabOptions.tabCloseButton : 'right';
this.tabOptions = tabOptions;

View file

@ -24,7 +24,7 @@ import { BaseEditor, EditorDescriptor } from 'vs/workbench/browser/parts/editor/
import { IEditorRegistry, Extensions as EditorExtensions, EditorInput, EditorOptions, ConfirmResult, IWorkbenchEditorConfiguration, IEditorDescriptor, TextEditorOptions, SideBySideEditorInput, TextCompareEditorVisible, TEXT_DIFF_EDITOR_ID } from 'vs/workbench/common/editor';
import { EditorGroupsControl, Rochade, IEditorGroupsControl, ProgressState } from 'vs/workbench/browser/parts/editor/editorGroupsControl';
import { WorkbenchProgressService } from 'vs/workbench/services/progress/browser/progressService';
import { IEditorGroupService, GroupOrientation, GroupArrangement, ITabOptions, IMoveOptions } from 'vs/workbench/services/group/common/groupService';
import { IEditorGroupService, GroupOrientation, GroupArrangement, IEditorTabOptions, IMoveOptions } from 'vs/workbench/services/group/common/groupService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IEditorPart } from 'vs/workbench/services/editor/browser/editorService';
import { IPartService } from 'vs/workbench/services/part/common/partService';
@ -91,7 +91,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
private editorGroupsControl: IEditorGroupsControl;
private memento: object;
private stacks: EditorStacksModel;
private tabOptions: ITabOptions;
private tabOptions: IEditorTabOptions;
private forceHideTabs: boolean;
private doNotFireTabOptionsChanged: boolean;
private revealIfOpen: boolean;
@ -100,7 +100,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
private _onEditorsMoved: Emitter<void>;
private _onEditorOpenFail: Emitter<EditorInput>;
private _onGroupOrientationChanged: Emitter<void>;
private _onTabOptionsChanged: Emitter<ITabOptions>;
private _onTabOptionsChanged: Emitter<IEditorTabOptions>;
private textCompareEditorVisible: IContextKey<boolean>;
@ -134,7 +134,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
this._onEditorsMoved = new Emitter<void>();
this._onEditorOpenFail = new Emitter<EditorInput>();
this._onGroupOrientationChanged = new Emitter<void>();
this._onTabOptionsChanged = new Emitter<ITabOptions>();
this._onTabOptionsChanged = new Emitter<IEditorTabOptions>();
this.visibleEditors = [];
@ -159,7 +159,8 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
previewEditors: editorConfig.enablePreview,
showIcons: editorConfig.showIcons,
showTabs: editorConfig.showTabs,
tabCloseButton: editorConfig.tabCloseButton
tabCloseButton: editorConfig.tabCloseButton,
labelFormat: editorConfig.labelFormat,
};
this.revealIfOpen = editorConfig.revealIfOpen;
@ -170,7 +171,8 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
previewEditors: true,
showIcons: false,
showTabs: true,
tabCloseButton: 'right'
tabCloseButton: 'right',
labelFormat: 'default',
};
this.revealIfOpen = false;
@ -221,7 +223,8 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
previewEditors: newPreviewEditors,
showIcons: editorConfig.showIcons,
tabCloseButton: editorConfig.tabCloseButton,
showTabs: this.forceHideTabs ? false : editorConfig.showTabs
showTabs: this.forceHideTabs ? false : editorConfig.showTabs,
labelFormat: editorConfig.labelFormat,
};
if (!this.doNotFireTabOptionsChanged && !objects.equals(oldTabOptions, this.tabOptions)) {
@ -278,11 +281,11 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
return this._onGroupOrientationChanged.event;
}
public get onTabOptionsChanged(): Event<ITabOptions> {
public get onTabOptionsChanged(): Event<IEditorTabOptions> {
return this._onTabOptionsChanged.event;
}
public getTabOptions(): ITabOptions {
public getTabOptions(): IEditorTabOptions {
return this.tabOptions;
}

View file

@ -33,7 +33,7 @@ import { IEditor as IBaseEditor, IEditorInput } from 'vs/platform/editor/common/
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IQuickOpenService, IPickOpenEntry, IFilePickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen';
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
import { SUPPORTED_ENCODINGS, IFileService } from 'vs/platform/files/common/files';
import { SUPPORTED_ENCODINGS, IFileService, IFilesConfiguration } from 'vs/platform/files/common/files';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IModelService } from 'vs/editor/common/services/modelService';
@ -46,6 +46,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile
import { getCodeEditor as getEditorWidget } from 'vs/editor/common/services/codeEditorService';
import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
import { IConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
// TODO@Sandeep layer breaker
// tslint:disable-next-line:import-patterns
@ -1058,7 +1059,7 @@ export class ChangeEncodingAction extends Action {
actionLabel: string,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService,
@ITextResourceConfigurationService private textResourceConfigurationService: ITextResourceConfigurationService,
@IFileService private fileService: IFileService
) {
super(actionId, actionLabel);
@ -1112,7 +1113,10 @@ export class ChangeEncodingAction extends Action {
})
.then((guessedEncoding: string) => {
const isReopenWithEncoding = (action === reopenWithEncodingPick);
const configuredEncoding = this.configurationService.lookup('files.encoding', { resource }).value;
const config = this.textResourceConfigurationService.getConfiguration(resource) as IFilesConfiguration;
const configuredEncoding = config && config.files && config.files.encoding;
let directMatchIndex: number;
let aliasMatchIndex: number;

View file

@ -118,7 +118,15 @@ export class NoTabsTitleControl extends TitleControl {
// Editor Label
const resource = toResource(editor, { supportSideBySide: true });
const name = editor.getName() || '';
const description = isActive ? (editor.getDescription() || '') : '';
const labelFormat = this.editorGroupService.getTabOptions().labelFormat;
let description: string;
if (labelFormat === 'default' && !isActive) {
description = ''; // hide description when group is not active and style is 'default'
} else {
description = editor.getDescription(this.getVerbosity(labelFormat)) || '';
}
let title = editor.getTitle(Verbosity.LONG);
if (description === title) {
title = ''; // dont repeat what is already shown
@ -134,4 +142,12 @@ export class NoTabsTitleControl extends TitleControl {
// Update Editor Actions Toolbar
this.updateEditorActionsToolbar();
}
private getVerbosity(style: string): Verbosity {
switch (style) {
case 'short': return Verbosity.SHORT;
case 'long': return Verbosity.LONG;
default: return Verbosity.MEDIUM;
}
}
}

View file

@ -47,11 +47,12 @@ import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
interface IEditorInputLabel {
name: string;
hasAmbiguousName?: boolean;
description?: string;
title?: string;
}
type AugmentedLabel = IEditorInputLabel & { editor: IEditorInput };
export class TabsTitleControl extends TitleControl {
private titleContainer: HTMLElement;
private tabsContainer: HTMLElement;
@ -264,7 +265,7 @@ export class TabsTitleControl extends TitleControl {
// Compute labels and protect against duplicates
const editorsOfGroup = this.context.getEditors();
const labels = this.getUniqueTabLabels(editorsOfGroup);
const labels = this.getTabLabels(editorsOfGroup);
// Tab label and styles
editorsOfGroup.forEach((editor, index) => {
@ -276,7 +277,7 @@ export class TabsTitleControl extends TitleControl {
const label = labels[index];
const name = label.name;
const description = label.hasAmbiguousName && label.description ? label.description : '';
const description = label.description || '';
const title = label.title || '';
// Container
@ -338,56 +339,108 @@ export class TabsTitleControl extends TitleControl {
this.layout();
}
private getUniqueTabLabels(editors: IEditorInput[]): IEditorInputLabel[] {
const labels: IEditorInputLabel[] = [];
const mapLabelToDuplicates = new Map<string, IEditorInputLabel[]>();
const mapLabelAndDescriptionToDuplicates = new Map<string, IEditorInputLabel[]>();
private getTabLabels(editors: IEditorInput[]): IEditorInputLabel[] {
const labelFormat = this.editorGroupService.getTabOptions().labelFormat;
const { verbosity, shortenDuplicates } = this.getLabelConfigFlags(labelFormat);
// Build labels and descriptions for each editor
editors.forEach(editor => {
const name = editor.getName();
let description = editor.getDescription();
if (mapLabelAndDescriptionToDuplicates.has(`${name}${description}`)) {
description = editor.getDescription(true); // try verbose description if name+description already exists
}
const labels = editors.map(editor => ({
editor,
name: editor.getName(),
description: editor.getDescription(verbosity),
title: editor.getTitle(Verbosity.LONG)
}));
const item: IEditorInputLabel = {
name,
description,
title: editor.getTitle(Verbosity.LONG)
};
labels.push(item);
getOrSet(mapLabelToDuplicates, item.name, []).push(item);
if (typeof description === 'string') {
getOrSet(mapLabelAndDescriptionToDuplicates, `${item.name}${item.description}`, []).push(item);
}
});
// Mark duplicates and shorten their descriptions
mapLabelToDuplicates.forEach(duplicates => {
if (duplicates.length > 1) {
duplicates = duplicates.filter(d => {
// we could have items with equal label and description. in that case it does not make much
// sense to produce a shortened version of the label, so we ignore those kind of items
return typeof d.description === 'string' && mapLabelAndDescriptionToDuplicates.get(`${d.name}${d.description}`).length === 1;
});
if (duplicates.length > 1) {
const shortenedDescriptions = shorten(duplicates.map(duplicate => duplicate.description));
duplicates.forEach((duplicate, i) => {
duplicate.description = shortenedDescriptions[i];
duplicate.hasAmbiguousName = true;
});
}
}
});
// Shorten labels as needed
if (shortenDuplicates) {
this.shortenTabLabels(labels);
}
return labels;
}
private shortenTabLabels(labels: AugmentedLabel[]): void {
// Gather duplicate titles, while filtering out invalid descriptions
const mapTitleToDuplicates = new Map<string, AugmentedLabel[]>();
for (const label of labels) {
if (typeof label.description === 'string' && label.description) {
getOrSet(mapTitleToDuplicates, label.name, []).push(label);
} else {
label.description = '';
}
}
// Identify duplicate titles and shorten descriptions
mapTitleToDuplicates.forEach(duplicateTitles => {
// Remove description if the title isn't duplicated
if (duplicateTitles.length === 1) {
duplicateTitles[0].description = '';
return;
}
// Identify duplicate descriptions
const mapDescriptionToDuplicates = new Map<string, AugmentedLabel[]>();
for (const label of duplicateTitles) {
getOrSet(mapDescriptionToDuplicates, label.description, []).push(label);
}
// For editors with duplicate descriptions, check whether any long descriptions differ
let useLongDescriptions = false;
mapDescriptionToDuplicates.forEach((duplicateDescriptions, name) => {
if (!useLongDescriptions && duplicateDescriptions.length > 1) {
const [first, ...rest] = duplicateDescriptions.map(({ editor }) => editor.getDescription(Verbosity.LONG));
useLongDescriptions = rest.some(description => description !== first);
}
});
// If so, replace all descriptions with long descriptions
if (useLongDescriptions) {
mapDescriptionToDuplicates.clear();
duplicateTitles.forEach(label => {
label.description = label.editor.getDescription(Verbosity.LONG);
getOrSet(mapDescriptionToDuplicates, label.description, []).push(label);
});
}
// Obtain final set of descriptions
const descriptions: string[] = [];
mapDescriptionToDuplicates.forEach((_, description) => descriptions.push(description));
// Remove description if all descriptions are identical
if (descriptions.length === 1) {
for (const label of mapDescriptionToDuplicates.get(descriptions[0])) {
label.description = '';
}
return;
}
// Shorten descriptions
const shortenedDescriptions = shorten(descriptions);
descriptions.forEach((description, i) => {
for (const label of mapDescriptionToDuplicates.get(description)) {
label.description = shortenedDescriptions[i];
}
});
});
}
private getLabelConfigFlags(value: string) {
switch (value) {
case 'short':
return { verbosity: Verbosity.SHORT, shortenDuplicates: false };
case 'medium':
return { verbosity: Verbosity.MEDIUM, shortenDuplicates: false };
case 'long':
return { verbosity: Verbosity.LONG, shortenDuplicates: false };
default:
return { verbosity: Verbosity.MEDIUM, shortenDuplicates: true };
}
}
protected doRefresh(): void {
const group = this.context;
const editor = group && group.activeEditor;

View file

@ -265,6 +265,17 @@ export class TitlebarPart extends Part implements ITitleService {
}
});
// Since the title area is used to drag the window, we do not want to steal focus from the
// currently active element. So we restore focus after a timeout back to where it was.
this.titleContainer.on([DOM.EventType.MOUSE_DOWN], () => {
const active = document.activeElement;
setTimeout(() => {
if (active instanceof HTMLElement) {
active.focus();
}
}, 0 /* need a timeout because we are in capture phase */);
}, void 0, true /* use capture to know the currently active element properly */);
return this.titleContainer;
}

View file

@ -176,7 +176,7 @@ export abstract class EditorInput implements IEditorInput {
* Returns the description of this input that can be shown to the user. Examples include showing the description of
* the input above the editor area to the side of the name of the input.
*/
public getDescription(): string {
public getDescription(verbosity?: Verbosity): string {
return null;
}
@ -806,7 +806,8 @@ export interface IWorkbenchEditorConfiguration {
closeOnFileDelete: boolean;
openPositioning: 'left' | 'right' | 'first' | 'last';
revealIfOpen: boolean;
swipeToNavigate: boolean
swipeToNavigate: boolean,
labelFormat: 'default' | 'short' | 'medium' | 'long';
}
};
}

View file

@ -19,6 +19,7 @@ import Event, { Emitter } from 'vs/base/common/event';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { telemetryURIDescriptor } from 'vs/platform/telemetry/common/telemetryUtils';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { Verbosity } from 'vs/platform/editor/common/editor';
/**
* An editor input to be used for untitled text buffers.
@ -36,6 +37,14 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport
private toUnbind: IDisposable[];
private shortDescription: string;
private mediumDescription: string;
private longDescription: string;
private shortTitle: string;
private mediumTitle: string;
private longTitle: string;
constructor(
private resource: URI,
hasAssociatedFilePath: boolean,
@ -88,8 +97,47 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport
return this.hasAssociatedFilePath ? paths.basename(this.resource.fsPath) : this.resource.fsPath;
}
public getDescription(): string {
return this.hasAssociatedFilePath ? labels.getPathLabel(paths.dirname(this.resource.fsPath), this.contextService, this.environmentService) : null;
public getDescription(verbosity: Verbosity = Verbosity.MEDIUM): string {
if (!this.hasAssociatedFilePath) {
return null;
}
let description: string;
switch (verbosity) {
case Verbosity.SHORT:
description = this.shortDescription ? this.shortDescription : (this.shortDescription = paths.basename(labels.getPathLabel(paths.dirname(this.resource.fsPath), void 0, this.environmentService)));
break;
case Verbosity.LONG:
description = this.longDescription ? this.longDescription : (this.longDescription = labels.getPathLabel(paths.dirname(this.resource.fsPath), void 0, this.environmentService));
break;
case Verbosity.MEDIUM:
default:
description = this.mediumDescription ? this.mediumDescription : (this.mediumDescription = labels.getPathLabel(paths.dirname(this.resource.fsPath), this.contextService, this.environmentService));
break;
}
return description;
}
public getTitle(verbosity: Verbosity): string {
if (!this.hasAssociatedFilePath) {
return this.getName();
}
let title: string;
switch (verbosity) {
case Verbosity.SHORT:
title = this.shortTitle ? this.shortTitle : (this.shortTitle = this.getName());
break;
case Verbosity.MEDIUM:
title = this.mediumTitle ? this.mediumTitle : (this.mediumTitle = labels.getPathLabel(this.resource, this.contextService, this.environmentService));
break;
case Verbosity.LONG:
title = this.longTitle ? this.longTitle : (this.longTitle = labels.getPathLabel(this.resource, void 0, this.environmentService));
break;
}
return title;
}
public isDirty(): boolean {

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { TPromise } from 'vs/base/common/winjs.base';
import { IEncodingSupport } from 'vs/workbench/common/editor';
import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel';
@ -12,7 +12,6 @@ import URI from 'vs/base/common/uri';
import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
import { EndOfLinePreference } from 'vs/editor/common/editorCommon';
import { IFilesConfiguration, CONTENT_CHANGE_EVENT_BUFFER_DELAY } from 'vs/platform/files/common/files';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IMode } from 'vs/editor/common/modes';
@ -20,13 +19,13 @@ import Event, { Emitter } from 'vs/base/common/event';
import { RunOnceScheduler } from 'vs/base/common/async';
import { IBackupFileService, BACKUP_FILE_RESOLVE_OPTIONS } from 'vs/workbench/services/backup/common/backup';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
export class UntitledEditorModel extends BaseTextEditorModel implements IEncodingSupport {
public static DEFAULT_CONTENT_CHANGE_BUFFER_DELAY = CONTENT_CHANGE_EVENT_BUFFER_DELAY;
private textModelChangeListener: IDisposable;
private configurationChangeListener: IDisposable;
private toDispose: IDisposable[];
private dirty: boolean;
private _onDidChangeContent: Emitter<void>;
@ -49,18 +48,25 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin
@IModelService modelService: IModelService,
@IBackupFileService private backupFileService: IBackupFileService,
@ITextFileService private textFileService: ITextFileService,
@IConfigurationService private configurationService: IConfigurationService
@ITextResourceConfigurationService private configurationService: ITextResourceConfigurationService
) {
super(modelService, modeService);
this.dirty = false;
this.versionId = 0;
this.toDispose = [];
this._onDidChangeContent = new Emitter<void>();
this.toDispose.push(this._onDidChangeContent);
this._onDidChangeDirty = new Emitter<void>();
this.toDispose.push(this._onDidChangeDirty);
this._onDidChangeEncoding = new Emitter<void>();
this.toDispose.push(this._onDidChangeEncoding);
this.contentChangeEventScheduler = new RunOnceScheduler(() => this._onDidChangeContent.fire(), UntitledEditorModel.DEFAULT_CONTENT_CHANGE_BUFFER_DELAY);
this.toDispose.push(this.contentChangeEventScheduler);
this.registerListeners();
}
@ -88,11 +94,20 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin
private registerListeners(): void {
// Config Changes
this.configurationChangeListener = this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationChange(this.configurationService.getConfiguration<IFilesConfiguration>()));
this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationChange()));
}
private onConfigurationChange(configuration: IFilesConfiguration): void {
this.configuredEncoding = configuration && configuration.files && configuration.files.encoding;
private onConfigurationChange(): void {
const configuration = this.configurationService.getConfiguration<IFilesConfiguration>(this.resource);
const configuredEncoding = configuration && configuration.files && configuration.files.encoding;
if (this.configuredEncoding !== configuredEncoding) {
this.configuredEncoding = configuredEncoding;
if (!this.preferredEncoding) {
this._onDidChangeEncoding.fire(); // do not fire event if we have a preferred encoding set
}
}
}
public getVersionId(): number {
@ -170,13 +185,16 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin
this.setDirty(this.hasAssociatedFilePath || !!backupContent);
return this.doLoad(backupContent || this.initialValue || '').then(model => {
const configuration = this.configurationService.getConfiguration<IFilesConfiguration>();
const configuration = this.configurationService.getConfiguration<IFilesConfiguration>(this.resource);
// Encoding
this.configuredEncoding = configuration && configuration.files && configuration.files.encoding;
// Listen to content changes
this.textModelChangeListener = this.textEditorModel.onDidChangeContent(() => this.onModelContentChanged());
this.toDispose.push(this.textEditorModel.onDidChangeContent(() => this.onModelContentChanged()));
// Listen to mode changes
this.toDispose.push(this.textEditorModel.onDidChangeLanguage(() => this.onModelModeChanged()));
return model;
});
@ -216,23 +234,13 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin
this.contentChangeEventScheduler.schedule();
}
private onModelModeChanged(): void {
this.onConfigurationChange(); // mode change can have impact on config
}
public dispose(): void {
super.dispose();
if (this.textModelChangeListener) {
this.textModelChangeListener.dispose();
this.textModelChangeListener = null;
}
if (this.configurationChangeListener) {
this.configurationChangeListener.dispose();
this.configurationChangeListener = null;
}
this.contentChangeEventScheduler.dispose();
this._onDidChangeContent.dispose();
this._onDidChangeDirty.dispose();
this._onDidChangeEncoding.dispose();
this.toDispose = dispose(this.toDispose);
}
}

View file

@ -129,6 +129,23 @@ let workbenchProperties: { [path: string]: IJSONSchema; } = {
'description': nls.localize('showEditorTabs', "Controls if opened editors should show in tabs or not."),
'default': true
},
'workbench.editor.labelFormat': {
'type': 'string',
'enum': ['default', 'short', 'medium', 'long'],
'enumDescriptions': [
nls.localize('workbench.editor.labelFormat.default', "Show the name of the file. When tabs are enabled and two files have the same name in one group the distinguinshing sections of each file's path is added. When tabs are disabled, the path relative to workspace root is shown if the editor is active."),
nls.localize('workbench.editor.labelFormat.short', "Show the name of the file followed by it's directory name."),
nls.localize('workbench.editor.labelFormat.medium', "Show the name of the file followed by it's path relative to the workspace root."),
nls.localize('workbench.editor.labelFormat.long', "Show the name of the file followed by it's absolute path.")
],
'default': 'default',
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by parenthesis are not to be translated.'], key: 'tabDescription' },
`Controls the format of the label for an editor. Changing this setting can for example make it easier to understand the location of a file:
- short: 'parent'
- medium: 'workspace/src/parent'
- long: '/home/user/workspace/src/parent'
- default: '.../parent', when another tab shares the same title, or the relative workspace path if tabs are disabled`),
},
'workbench.editor.tabCloseButton': {
'type': 'string',
'enum': ['left', 'right', 'off'],

View file

@ -20,7 +20,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import { EmptyWorkspaceServiceImpl, WorkspaceServiceImpl, WorkspaceService } from 'vs/workbench/services/configuration/node/configuration';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { realpath, readFile, writeFile } from 'vs/base/node/pfs';
import { realpath } from 'vs/base/node/pfs';
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
import path = require('path');
import gracefulFs = require('graceful-fs');
@ -42,7 +42,6 @@ import { WorkspacesChannelClient } from 'vs/platform/workspaces/common/workspace
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
import { CredentialsChannelClient } from 'vs/platform/credentials/node/credentialsIpc';
import { migrateStorageToMultiRootWorkspace } from 'vs/platform/storage/common/migration';
import fs = require('fs');
gracefulFs.gracefulify(fs); // enable gracefulFs
@ -112,43 +111,18 @@ function openWorkbench(configuration: IWindowConfiguration): TPromise<void> {
}
function createAndInitializeWorkspaceService(configuration: IWindowConfiguration, environmentService: EnvironmentService, workspacesService: IWorkspacesService): TPromise<WorkspaceService> {
return migrateWorkspaceId(configuration).then(() => {
return validateWorkspacePath(configuration).then(() => {
let workspaceService: WorkspaceServiceImpl | EmptyWorkspaceServiceImpl;
if (configuration.workspace || configuration.folderPath) {
workspaceService = new WorkspaceServiceImpl(configuration.workspace || configuration.folderPath, environmentService, workspacesService);
} else {
workspaceService = new EmptyWorkspaceServiceImpl(environmentService);
}
return validateWorkspacePath(configuration).then(() => {
let workspaceService: WorkspaceServiceImpl | EmptyWorkspaceServiceImpl;
if (configuration.workspace || configuration.folderPath) {
workspaceService = new WorkspaceServiceImpl(configuration.workspace || configuration.folderPath, environmentService, workspacesService);
} else {
workspaceService = new EmptyWorkspaceServiceImpl(environmentService);
}
return workspaceService.initialize().then(() => workspaceService, error => new EmptyWorkspaceServiceImpl(environmentService));
});
return workspaceService.initialize().then(() => workspaceService, error => new EmptyWorkspaceServiceImpl(environmentService));
});
}
// TODO@Ben migration
function migrateWorkspaceId(configuration: IWindowConfiguration): TPromise<void> {
if (!configuration.workspace || !configuration.workspace.configPath) {
return TPromise.as(null);
}
return readFile(configuration.workspace.configPath).then(data => {
try {
const raw = JSON.parse(data.toString());
if (raw.id) {
const previousWorkspaceId = raw.id;
delete raw.id;
migrateStorageToMultiRootWorkspace(uri.from({ path: previousWorkspaceId, scheme: 'root' }).toString(), configuration.workspace, window.localStorage);
return writeFile(configuration.workspace.configPath, JSON.stringify(raw, null, '\t'));
}
} catch (error) { };
return void 0;
}).then(() => void 0, () => void 0);
}
function validateWorkspacePath(configuration: IWindowConfiguration): TPromise<void> {
if (!configuration.folderPath) {
return TPromise.as(null);

View file

@ -54,6 +54,7 @@ import { IContextKeyService, RawContextKey, ContextKeyExpr, IContextKey } from '
import { Command, ICommandOptions } from 'vs/editor/common/editorCommonExtensions';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { Color } from 'vs/base/common/color';
/** A context key that is set when an extension editor webview has focus. */
export const KEYBINDING_CONTEXT_EXTENSIONEDITOR_WEBVIEW_FOCUS = new RawContextKey<boolean>('extensionEditorWebviewFocus', undefined);
@ -428,7 +429,9 @@ export class ExtensionEditor extends BaseEditor {
this.renderSettings(content, manifest, layout),
this.renderCommands(content, manifest, layout),
this.renderLanguages(content, manifest, layout),
this.renderThemes(content, manifest, layout),
this.renderColorThemes(content, manifest, layout),
this.renderIconThemes(content, manifest, layout),
this.renderColors(content, manifest, layout),
this.renderJSONValidation(content, manifest, layout),
this.renderDebuggers(content, manifest, layout),
this.renderViews(content, manifest, layout)
@ -536,6 +539,8 @@ export class ExtensionEditor extends BaseEditor {
return true;
}
private renderDebuggers(container: HTMLElement, manifest: IExtensionManifest, onDetailsToggle: Function): boolean {
const contributes = manifest.contributes;
const contrib = contributes && contributes.debuggers || [];
@ -587,7 +592,7 @@ export class ExtensionEditor extends BaseEditor {
return true;
}
private renderThemes(container: HTMLElement, manifest: IExtensionManifest, onDetailsToggle: Function): boolean {
private renderColorThemes(container: HTMLElement, manifest: IExtensionManifest, onDetailsToggle: Function): boolean {
const contributes = manifest.contributes;
const contrib = contributes && contributes.themes || [];
@ -596,7 +601,7 @@ export class ExtensionEditor extends BaseEditor {
}
const details = $('details', { open: true, ontoggle: onDetailsToggle },
$('summary', null, localize('themes', "Themes ({0})", contrib.length)),
$('summary', null, localize('colorThemes', "Color Themes ({0})", contrib.length)),
$('ul', null, ...contrib.map(theme => $('li', null, theme.label)))
);
@ -604,6 +609,68 @@ export class ExtensionEditor extends BaseEditor {
return true;
}
private renderIconThemes(container: HTMLElement, manifest: IExtensionManifest, onDetailsToggle: Function): boolean {
const contributes = manifest.contributes;
const contrib = contributes && contributes.iconThemes || [];
if (!contrib.length) {
return false;
}
const details = $('details', { open: true, ontoggle: onDetailsToggle },
$('summary', null, localize('iconThemes', "Icon Themes ({0})", contrib.length)),
$('ul', null, ...contrib.map(theme => $('li', null, theme.label)))
);
append(container, details);
return true;
}
private renderColors(container: HTMLElement, manifest: IExtensionManifest, onDetailsToggle: Function): boolean {
const contributes = manifest.contributes;
const colors = contributes && contributes.colors;
if (!colors || !colors.length) {
return false;
}
function colorPreview(colorReference: string): Node[] {
let result: Node[] = [];
if (colorReference && colorReference[0] === '#') {
let color = Color.fromHex(colorReference);
if (color) {
result.push($('span', { class: 'colorBox', style: 'background-color: ' + Color.Format.CSS.format(color) }, ''));
}
}
result.push($('code', null, colorReference));
return result;
}
const details = $('details', { open: true, ontoggle: onDetailsToggle },
$('summary', null, localize('colors', "Colors ({0})", colors.length)),
$('table', null,
$('tr', null,
$('th', null, localize('colorId', "Id")),
$('th', null, localize('description', "Description")),
$('th', null, localize('defaultDark', "Dark Default")),
$('th', null, localize('defaultLight', "Light Default")),
$('th', null, localize('defaultHC', "High Contrast Default"))
),
...colors.map(color => $('tr', null,
$('td', null, $('code', null, color.id)),
$('td', null, color.description),
$('td', null, ...colorPreview(color.defaults.dark)),
$('td', null, ...colorPreview(color.defaults.light)),
$('td', null, ...colorPreview(color.defaults.highContrast))
))
)
);
append(container, details);
return true;
}
private renderJSONValidation(container: HTMLElement, manifest: IExtensionManifest, onDetailsToggle: Function): boolean {
const contributes = manifest.contributes;
const contrib = contributes && contributes.jsonValidation || [];

View file

@ -223,6 +223,23 @@
padding: 1px 4px;
}
.extension-editor > .body > .content table .colorBox {
box-sizing: border-box;
width: 0.8em;
height: 0.8em;
display: inline-block;
border-width: 0.1em;
border-style: solid;
border-color: rgb(0, 0, 0);
margin: 0em 0.2em;
vertical-align: middle;
}
.vs-dark .extension-editor > .body > .content table .colorBox,
.hc-black .extension-editor > .body > .content table .colorBox {
border-color: rgb(238, 238, 238);
}
.extension-editor .subcontent .monaco-tree-row .content .unknown-dependency {
line-height: 62px;
}

View file

@ -201,15 +201,18 @@ configurationRegistry.registerConfiguration({
},
'files.encoding': {
'type': 'string',
'overridable': true,
'enum': Object.keys(SUPPORTED_ENCODINGS),
'default': 'utf8',
'description': nls.localize('encoding', "The default character set encoding to use when reading and writing files."),
'scope': ConfigurationScope.RESOURCE
'description': nls.localize('encoding', "The default character set encoding to use when reading and writing files. This setting can be configured per language too."),
'scope': ConfigurationScope.RESOURCE,
'enumDescriptions': Object.keys(SUPPORTED_ENCODINGS).map(key => SUPPORTED_ENCODINGS[key].labelLong)
},
'files.autoGuessEncoding': {
'type': 'boolean',
'overridable': true,
'default': false,
'description': nls.localize('autoGuessEncoding', "When enabled, will attempt to guess the character set encoding when opening files"),
'description': nls.localize('autoGuessEncoding', "When enabled, will attempt to guess the character set encoding when opening files. This setting can be configured per language too."),
'scope': ConfigurationScope.RESOURCE
},
'files.eol': {

View file

@ -32,8 +32,10 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput {
private textModelReference: TPromise<IReference<ITextEditorModel>>;
private name: string;
private description: string;
private verboseDescription: string;
private shortDescription: string;
private mediumDescription: string;
private longDescription: string;
private shortTitle: string;
private mediumTitle: string;
@ -128,18 +130,22 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput {
return this.decorateOrphanedFiles(this.name);
}
public getDescription(verbose?: boolean): string {
if (verbose) {
if (!this.verboseDescription) {
this.verboseDescription = labels.getPathLabel(paths.dirname(this.resource.fsPath), void 0, this.environmentService);
}
} else {
if (!this.description) {
this.description = labels.getPathLabel(paths.dirname(this.resource.fsPath), this.contextService, this.environmentService);
}
public getDescription(verbosity: Verbosity = Verbosity.MEDIUM): string {
let description: string;
switch (verbosity) {
case Verbosity.SHORT:
description = this.shortDescription ? this.shortDescription : (this.shortDescription = paths.basename(labels.getPathLabel(paths.dirname(this.resource.fsPath), void 0, this.environmentService)));
break;
case Verbosity.LONG:
description = this.longDescription ? this.longDescription : (this.longDescription = labels.getPathLabel(paths.dirname(this.resource.fsPath), void 0, this.environmentService));
break;
case Verbosity.MEDIUM:
default:
description = this.mediumDescription ? this.mediumDescription : (this.mediumDescription = labels.getPathLabel(paths.dirname(this.resource.fsPath), this.contextService, this.environmentService));
break;
}
return verbose ? this.verboseDescription : this.description;
return description;
}
public getTitle(verbosity: Verbosity): string {
@ -274,4 +280,4 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput {
return false;
}
}
}

View file

@ -33,6 +33,7 @@ import { QUICKOPEN_ACTION_ID, getQuickNavigateHandler } from 'vs/workbench/brows
import { IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen';
import { Scope, IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbench/browser/actions';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { TogglePanelAction } from 'vs/workbench/browser/parts/panel/panelActions';
const quickOpenRegistry = (<IQuickOpenRegistry>Registry.as(QuickOpenExtensions.Quickopen));
@ -230,6 +231,7 @@ configurationRegistry.registerConfiguration({
NavigateLeftAction.ID,
DeleteWordLeftTerminalAction.ID,
DeleteWordRightTerminalAction.ID,
TogglePanelAction.ID,
'workbench.action.quickOpenView'
].sort()
},

View file

@ -412,10 +412,8 @@ export class TerminalInstance implements ITerminalInstance {
}
public notifyFindWidgetFocusChanged(isFocused: boolean): void {
// In order to support escape to close the find widget when the terminal
// is focused terminalFocus needs to be true when either the terminal or
// the find widget are focused.
this._terminalFocusContextKey.set(isFocused || document.activeElement === this._xterm.textarea);
const terminalFocused = !isFocused && (document.activeElement === this._xterm.textarea || document.activeElement === this._xterm.element);
this._terminalFocusContextKey.set(terminalFocused);
}
public dispose(): void {

View file

@ -20,9 +20,8 @@ const pathSeparatorClause = '\\/';
// '":; are allowed in paths but they are often separators so ignore them
// Also disallow \\ to prevent a catastropic backtracking case #24798
const excludedPathCharactersClause = '[^\\0\\s!$`&*()\\[\\]+\'":;\\\\]';
const escapedExcludedPathCharactersClause = '(\\\\s|\\\\!|\\\\$|\\\\`|\\\\&|\\\\*|(|)|\\+)';
/** A regex that matches paths in the form /foo, ~/foo, ./foo, ../foo, foo/bar */
const unixLocalLinkClause = '((' + pathPrefix + '|(' + excludedPathCharactersClause + '|' + escapedExcludedPathCharactersClause + ')+)?(' + pathSeparatorClause + '(' + excludedPathCharactersClause + '|' + escapedExcludedPathCharactersClause + ')+)+)';
const unixLocalLinkClause = '((' + pathPrefix + '|(' + excludedPathCharactersClause + ')+)?(' + pathSeparatorClause + '(' + excludedPathCharactersClause + ')+)+)';
const winDrivePrefix = '[a-zA-Z]:';
const winPathPrefix = '(' + winDrivePrefix + '|\\.\\.?|\\~)';

View file

@ -134,24 +134,25 @@ suite('Workbench - TerminalLinkHandler', () => {
const supportedLinkFormats: LinkFormatInfo[] = [
{ urlFormat: '{0}' },
{ urlFormat: '{0} on line {1}', line: '5' },
{ urlFormat: '{0} on line {1}, column {2}', line: '5', column: '3' },
{ urlFormat: '{0}:line {1}', line: '5' },
{ urlFormat: '{0}:line {1}, column {2}', line: '5', column: '3' },
{ urlFormat: '{0}({1})', line: '5' },
{ urlFormat: '{0} ({1})', line: '5' },
{ urlFormat: '{0}({1},{2})', line: '5', column: '3' },
{ urlFormat: '{0} ({1},{2})', line: '5', column: '3' },
{ urlFormat: '{0}:{1}', line: '5' },
{ urlFormat: '{0}:{1}:{2}', line: '5', column: '3' },
{ urlFormat: '{0}[{1}]', line: '5' },
{ urlFormat: '{0} [{1}]', line: '5' },
{ urlFormat: '{0}[{1},{2}]', line: '5', column: '3' },
{ urlFormat: '{0} [{1},{2}]', line: '5', column: '3' }
// { urlFormat: '{0} on line {1}', line: '5' },
// { urlFormat: '{0} on line {1}, column {2}', line: '5', column: '3' },
// { urlFormat: '{0}:line {1}', line: '5' },
// { urlFormat: '{0}:line {1}, column {2}', line: '5', column: '3' },
// { urlFormat: '{0}({1})', line: '5' },
// { urlFormat: '{0} ({1})', line: '5' },
// { urlFormat: '{0}({1},{2})', line: '5', column: '3' },
// { urlFormat: '{0} ({1},{2})', line: '5', column: '3' },
// { urlFormat: '{0}:{1}', line: '5' },
// { urlFormat: '{0}:{1}:{2}', line: '5', column: '3' },
// { urlFormat: '{0}[{1}]', line: '5' },
// { urlFormat: '{0} [{1}]', line: '5' },
// { urlFormat: '{0}[{1},{2}]', line: '5', column: '3' },
// { urlFormat: '{0} [{1},{2}]', line: '5', column: '3' }
];
linkUrls.forEach(linkUrl => {
supportedLinkFormats.forEach(linkFormatInfo => {
console.log('linkFormatInfo: ', linkFormatInfo);
testLink(
strings.format(linkFormatInfo.urlFormat, linkUrl, linkFormatInfo.line, linkFormatInfo.column),
linkUrl,

View file

@ -19,7 +19,7 @@ import { FileService } from 'vs/workbench/services/files/node/fileService';
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
import { parseArgs } from 'vs/platform/environment/node/argv';
import { RawTextSource } from 'vs/editor/common/model/textSource';
import { TestContextService } from 'vs/workbench/test/workbenchTestServices';
import { TestContextService, TestTextResourceConfigurationService } from 'vs/workbench/test/workbenchTestServices';
import { Workspace } from 'vs/platform/workspace/common/workspace';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
@ -44,19 +44,18 @@ const fooFile = Uri.file(platform.isWindows ? 'c:\\Foo' : '/Foo');
const barFile = Uri.file(platform.isWindows ? 'c:\\Bar' : '/Bar');
const untitledFile = Uri.from({ scheme: 'untitled', path: 'Untitled-1' });
const fooBackupPath = path.join(workspaceBackupPath, 'file', crypto.createHash('md5').update(fooFile.fsPath).digest('hex'));
const fooBackupPathLegacy = path.join(workspaceBackupPath, 'file', crypto.createHash('md5').update(fooFile.fsPath.toLowerCase()).digest('hex'));
const barBackupPath = path.join(workspaceBackupPath, 'file', crypto.createHash('md5').update(barFile.fsPath).digest('hex'));
const untitledBackupPath = path.join(workspaceBackupPath, 'untitled', crypto.createHash('md5').update(untitledFile.fsPath).digest('hex'));
class TestBackupFileService extends BackupFileService {
constructor(workspace: Uri, backupHome: string, workspacesJsonPath: string) {
const fileService = new FileService(new TestContextService(new Workspace(workspace.fsPath, workspace.fsPath, [workspace])), new TestConfigurationService(), { disableWatcher: true });
const fileService = new FileService(new TestContextService(new Workspace(workspace.fsPath, workspace.fsPath, [workspace])), new TestTextResourceConfigurationService(), new TestConfigurationService(), { disableWatcher: true });
super(workspaceBackupPath, fileService);
}
public getBackupResource(resource: Uri, legacyMacWindowsFormat?: boolean): Uri {
return super.getBackupResource(resource, legacyMacWindowsFormat);
public getBackupResource(resource: Uri): Uri {
return super.getBackupResource(resource);
}
}
@ -115,47 +114,6 @@ suite('BackupFileService', () => {
});
});
});
test('should return whether a backup resource exists - legacy support (read old lowercase format as fallback)', done => {
if (platform.isLinux) {
done();
return; // only on mac and windows
}
pfs.mkdirp(path.dirname(fooBackupPath)).then(() => {
fs.writeFileSync(fooBackupPathLegacy, 'foo');
service = new TestBackupFileService(workspaceResource, backupHome, workspacesJsonPath);
service.loadBackupResource(fooFile).then(resource => {
assert.ok(resource);
assert.equal(path.basename(resource.fsPath), path.basename(fooBackupPathLegacy));
return service.hasBackups().then(hasBackups => {
assert.ok(hasBackups);
done();
});
});
});
});
test('should return whether a backup resource exists - legacy support #2 (both cases present, return case sensitive backup)', done => {
if (platform.isLinux) {
done();
return; // only on mac and windows
}
pfs.mkdirp(path.dirname(fooBackupPath)).then(() => {
fs.writeFileSync(fooBackupPath, 'foo');
fs.writeFileSync(fooBackupPathLegacy, 'foo');
service = new TestBackupFileService(workspaceResource, backupHome, workspacesJsonPath);
service.loadBackupResource(fooFile).then(resource => {
assert.ok(resource);
assert.equal(path.basename(resource.fsPath), path.basename(fooBackupPath));
return service.hasBackups().then(hasBackups => {
assert.ok(hasBackups);
done();
});
});
});
});
});
suite('backupResource', () => {
@ -200,27 +158,6 @@ suite('BackupFileService', () => {
});
});
});
test('text file - legacy support (dicard lowercase backup file if present)', done => {
if (platform.isLinux) {
done();
return; // only on mac and windows
}
pfs.mkdirp(path.dirname(fooBackupPath)).then(() => {
fs.writeFileSync(fooBackupPathLegacy, 'foo');
service = new TestBackupFileService(workspaceResource, backupHome, workspacesJsonPath);
service.backupResource(fooFile, 'test').then(() => {
assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 2);
service.discardResourceBackup(fooFile).then(() => {
assert.equal(fs.existsSync(fooBackupPath), false);
assert.equal(fs.existsSync(fooBackupPathLegacy), false);
assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 0);
done();
});
});
});
});
});
suite('discardAllWorkspaceBackups', () => {

View file

@ -18,7 +18,7 @@ import { parseArgs } from 'vs/platform/environment/node/argv';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
import extfs = require('vs/base/node/extfs');
import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService } from 'vs/workbench/test/workbenchTestServices';
import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestTextResourceConfigurationService } from 'vs/workbench/test/workbenchTestServices';
import uuid = require('vs/base/common/uuid');
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { WorkspaceService, EmptyWorkspaceServiceImpl, WorkspaceServiceImpl } from 'vs/workbench/services/configuration/node/configuration';
@ -125,7 +125,7 @@ suite('ConfigurationEditingService', () => {
instantiationService.stub(ITelemetryService, NullTelemetryService);
instantiationService.stub(IModeService, ModeServiceImpl);
instantiationService.stub(IModelService, instantiationService.createInstance(ModelServiceImpl));
instantiationService.stub(IFileService, new FileService(workspaceService, new TestConfigurationService(), { disableWatcher: true }));
instantiationService.stub(IFileService, new FileService(workspaceService, new TestTextResourceConfigurationService(), new TestConfigurationService(), { disableWatcher: true }));
instantiationService.stub(IUntitledEditorService, instantiationService.createInstance(UntitledEditorService));
instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService));
instantiationService.stub(ITextModelService, <ITextModelService>instantiationService.createInstance(TextModelResolverService));

View file

@ -27,6 +27,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import Event, { Emitter } from 'vs/base/common/event';
import { shell } from 'electron';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
export class FileService implements IFileService {
@ -52,7 +53,8 @@ export class FileService implements IFileService {
@IEditorGroupService private editorGroupService: IEditorGroupService,
@ILifecycleService private lifecycleService: ILifecycleService,
@IMessageService private messageService: IMessageService,
@IStorageService private storageService: IStorageService
@IStorageService private storageService: IStorageService,
@ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService
) {
this.toUnbind = [];
this.activeOutOfWorkspaceWatchers = new ResourceMap<uri>();
@ -80,7 +82,7 @@ export class FileService implements IFileService {
};
// create service
this.raw = new NodeFileService(contextService, configurationService, fileServiceConfig);
this.raw = new NodeFileService(contextService, textResourceConfigurationService, configurationService, fileServiceConfig);
// Listeners
this.registerListeners();

View file

@ -36,6 +36,7 @@ import { FileWatcher as WindowsWatcherService } from 'vs/workbench/services/file
import { toFileChangesEvent, normalize, IRawFileChange } from 'vs/workbench/services/files/node/watcher/common';
import Event, { Emitter } from 'vs/base/common/event';
import { FileWatcher as NsfwWatcherService } from 'vs/workbench/services/files/node/watcher/nsfw/watcherService';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
export interface IEncodingOverride {
@ -93,8 +94,9 @@ export class FileService implements IFileService {
constructor(
private contextService: IWorkspaceContextService,
private textResourceConfigurationService: ITextResourceConfigurationService,
private configurationService: IConfigurationService,
options: IFileServiceOptions,
options: IFileServiceOptions
) {
this.toDispose = [];
this.options = options || Object.create(null);
@ -638,13 +640,13 @@ export class FileService implements IFileService {
}
private configuredAutoGuessEncoding(resource: uri): boolean {
const config = this.configurationService.getConfiguration(void 0, { resource }) as IFilesConfiguration;
const config = this.textResourceConfigurationService.getConfiguration(resource) as IFilesConfiguration;
return config && config.files && config.files.autoGuessEncoding === true;
}
private configuredEncoding(resource: uri): string {
const config = this.configurationService.getConfiguration(void 0, { resource }) as IFilesConfiguration;
const config = this.textResourceConfigurationService.getConfiguration(resource) as IFilesConfiguration;
return config && config.files && config.files.encoding;
}

View file

@ -19,26 +19,26 @@ import extfs = require('vs/base/node/extfs');
import encodingLib = require('vs/base/node/encoding');
import utils = require('vs/workbench/services/files/test/node/utils');
import { onError } from 'vs/base/test/common/utils';
import { TestContextService } from 'vs/workbench/test/workbenchTestServices';
import { TestContextService, TestTextResourceConfigurationService } from 'vs/workbench/test/workbenchTestServices';
import { Workspace } from 'vs/platform/workspace/common/workspace';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
suite('FileService', () => {
let service: FileService;
let parentDir = path.join(os.tmpdir(), 'vsctests', 'service');
const parentDir = path.join(os.tmpdir(), 'vsctests', 'service');
let testDir: string;
setup(function (done) {
let id = uuid.generateUuid();
const id = uuid.generateUuid();
testDir = path.join(parentDir, id);
let sourceDir = require.toUrl('./fixtures/service');
const sourceDir = require.toUrl('./fixtures/service');
extfs.copy(sourceDir, testDir, (error) => {
if (error) {
return onError(error, done);
}
service = new FileService(new TestContextService(new Workspace(testDir, testDir, [uri.file(testDir)])), new TestConfigurationService(), { disableWatcher: true });
service = new FileService(new TestContextService(new Workspace(testDir, testDir, [uri.file(testDir)])), new TestTextResourceConfigurationService(), new TestConfigurationService(), { disableWatcher: true });
done();
});
});
@ -487,7 +487,7 @@ suite('FileService', () => {
service.resolveFile(uri.file(testDir), { resolveTo: [uri.file(path.join(testDir, 'deep'))] }).done(r => {
assert.equal(r.children.length, 6);
let deep = utils.getByName(r, 'deep');
const deep = utils.getByName(r, 'deep');
assert.equal(deep.children.length, 4);
done();
@ -503,7 +503,7 @@ suite('FileService', () => {
assert.equal(r1.children.length, 6);
let deep = utils.getByName(r1, 'deep');
const deep = utils.getByName(r1, 'deep');
assert.equal(deep.children.length, 4);
const r2 = res[1].stat;
@ -527,7 +527,7 @@ suite('FileService', () => {
});
test('updateContent', function (done: () => void) {
let resource = uri.file(path.join(testDir, 'small.txt'));
const resource = uri.file(path.join(testDir, 'small.txt'));
service.resolveContent(resource).done(c => {
assert.equal(c.value, 'Small File');
@ -543,8 +543,8 @@ suite('FileService', () => {
});
test('updateContent - use encoding (UTF 16 BE)', function (done: () => void) {
let resource = uri.file(path.join(testDir, 'small.txt'));
let encoding = 'utf16be';
const resource = uri.file(path.join(testDir, 'small.txt'));
const encoding = 'utf16be';
service.resolveContent(resource).done(c => {
c.encoding = encoding;
@ -564,8 +564,8 @@ suite('FileService', () => {
});
test('updateContent - encoding preserved (UTF 16 LE)', function (done: () => void) {
let encoding = 'utf16le';
let resource = uri.file(path.join(testDir, 'some_utf16le.css'));
const encoding = 'utf16le';
const resource = uri.file(path.join(testDir, 'some_utf16le.css'));
service.resolveContent(resource).done(c => {
assert.equal(c.encoding, encoding);
@ -587,7 +587,7 @@ suite('FileService', () => {
});
test('resolveContent - FILE_IS_BINARY', function (done: () => void) {
let resource = uri.file(path.join(testDir, 'binary.txt'));
const resource = uri.file(path.join(testDir, 'binary.txt'));
service.resolveContent(resource, { acceptTextOnly: true }).done(null, (e: FileOperationError) => {
assert.equal(e.fileOperationResult, FileOperationResult.FILE_IS_BINARY);
@ -601,7 +601,7 @@ suite('FileService', () => {
});
test('resolveContent - FILE_IS_DIRECTORY', function (done: () => void) {
let resource = uri.file(path.join(testDir, 'deep'));
const resource = uri.file(path.join(testDir, 'deep'));
service.resolveContent(resource).done(null, (e: FileOperationError) => {
assert.equal(e.fileOperationResult, FileOperationResult.FILE_IS_DIRECTORY);
@ -611,7 +611,7 @@ suite('FileService', () => {
});
test('resolveContent - FILE_NOT_FOUND', function (done: () => void) {
let resource = uri.file(path.join(testDir, '404.html'));
const resource = uri.file(path.join(testDir, '404.html'));
service.resolveContent(resource).done(null, (e: FileOperationError) => {
assert.equal(e.fileOperationResult, FileOperationResult.FILE_NOT_FOUND);
@ -621,7 +621,7 @@ suite('FileService', () => {
});
test('resolveContent - FILE_NOT_MODIFIED_SINCE', function (done: () => void) {
let resource = uri.file(path.join(testDir, 'index.html'));
const resource = uri.file(path.join(testDir, 'index.html'));
service.resolveContent(resource).done(c => {
return service.resolveContent(resource, { etag: c.etag }).then(null, (e: FileOperationError) => {
@ -633,7 +633,7 @@ suite('FileService', () => {
});
test('resolveContent - FILE_MODIFIED_SINCE', function (done: () => void) {
let resource = uri.file(path.join(testDir, 'index.html'));
const resource = uri.file(path.join(testDir, 'index.html'));
service.resolveContent(resource).done(c => {
fs.writeFileSync(resource.fsPath, 'Updates Incoming!');
@ -647,8 +647,8 @@ suite('FileService', () => {
});
test('resolveContent - encoding picked up', function (done: () => void) {
let resource = uri.file(path.join(testDir, 'index.html'));
let encoding = 'windows1252';
const resource = uri.file(path.join(testDir, 'index.html'));
const encoding = 'windows1252';
service.resolveContent(resource, { encoding: encoding }).done(c => {
assert.equal(c.encoding, encoding);
@ -658,7 +658,7 @@ suite('FileService', () => {
});
test('resolveContent - user overrides BOM', function (done: () => void) {
let resource = uri.file(path.join(testDir, 'some_utf16le.css'));
const resource = uri.file(path.join(testDir, 'some_utf16le.css'));
service.resolveContent(resource, { encoding: 'windows1252' }).done(c => {
assert.equal(c.encoding, 'windows1252');
@ -668,7 +668,7 @@ suite('FileService', () => {
});
test('resolveContent - BOM removed', function (done: () => void) {
let resource = uri.file(path.join(testDir, 'some_utf8_bom.txt'));
const resource = uri.file(path.join(testDir, 'some_utf8_bom.txt'));
service.resolveContent(resource).done(c => {
assert.equal(encodingLib.detectEncodingByBOMFromBuffer(new Buffer(c.value), 512), null);
@ -678,7 +678,7 @@ suite('FileService', () => {
});
test('resolveContent - invalid encoding', function (done: () => void) {
let resource = uri.file(path.join(testDir, 'index.html'));
const resource = uri.file(path.join(testDir, 'index.html'));
service.resolveContent(resource, { encoding: 'superduper' }).done(c => {
assert.equal(c.encoding, 'utf8');
@ -688,7 +688,7 @@ suite('FileService', () => {
});
test('watchFileChanges', function (done: () => void) {
let toWatch = uri.file(path.join(testDir, 'index.html'));
const toWatch = uri.file(path.join(testDir, 'index.html'));
service.watchFileChanges(toWatch);
@ -705,7 +705,7 @@ suite('FileService', () => {
});
test('watchFileChanges - support atomic save', function (done: () => void) {
let toWatch = uri.file(path.join(testDir, 'index.html'));
const toWatch = uri.file(path.join(testDir, 'index.html'));
service.watchFileChanges(toWatch);
@ -729,21 +729,23 @@ suite('FileService', () => {
test('options - encoding', function (done: () => void) {
// setup
let _id = uuid.generateUuid();
let _testDir = path.join(parentDir, _id);
let _sourceDir = require.toUrl('./fixtures/service');
const _id = uuid.generateUuid();
const _testDir = path.join(parentDir, _id);
const _sourceDir = require.toUrl('./fixtures/service');
extfs.copy(_sourceDir, _testDir, () => {
let encodingOverride: IEncodingOverride[] = [];
const encodingOverride: IEncodingOverride[] = [];
encodingOverride.push({
resource: uri.file(path.join(testDir, 'deep')),
encoding: 'utf16le'
});
let configurationService = new TestConfigurationService();
const configurationService = new TestConfigurationService();
configurationService.setUserConfiguration('files', { encoding: 'windows1252' });
let _service = new FileService(new TestContextService(new Workspace(_testDir, _testDir, [uri.file(_testDir)])), configurationService, {
const textResourceConfigurationService = new TestTextResourceConfigurationService(configurationService);
const _service = new FileService(new TestContextService(new Workspace(_testDir, _testDir, [uri.file(_testDir)])), textResourceConfigurationService, configurationService, {
encodingOverride,
disableWatcher: true
});
@ -765,12 +767,12 @@ suite('FileService', () => {
test('UTF 8 BOMs', function (done: () => void) {
// setup
let _id = uuid.generateUuid();
let _testDir = path.join(parentDir, _id);
let _sourceDir = require.toUrl('./fixtures/service');
let resource = uri.file(path.join(testDir, 'index.html'));
const _id = uuid.generateUuid();
const _testDir = path.join(parentDir, _id);
const _sourceDir = require.toUrl('./fixtures/service');
const resource = uri.file(path.join(testDir, 'index.html'));
let _service = new FileService(new TestContextService(new Workspace(_testDir, _testDir, [uri.file(_testDir)])), new TestConfigurationService(), {
const _service = new FileService(new TestContextService(new Workspace(_testDir, _testDir, [uri.file(_testDir)])), new TestTextResourceConfigurationService(), new TestConfigurationService(), {
disableWatcher: true
});

View file

@ -19,11 +19,12 @@ export type GroupOrientation = 'vertical' | 'horizontal';
export const IEditorGroupService = createDecorator<IEditorGroupService>('editorGroupService');
export interface ITabOptions {
export interface IEditorTabOptions {
showTabs?: boolean;
tabCloseButton?: 'left' | 'right' | 'off';
showIcons?: boolean;
previewEditors?: boolean;
labelFormat?: 'default' | 'short' | 'medium' | 'long';
}
export interface IMoveOptions {
@ -62,7 +63,7 @@ export interface IEditorGroupService {
/**
* Emitted when tab options changed.
*/
onTabOptionsChanged: Event<ITabOptions>;
onTabOptionsChanged: Event<IEditorTabOptions>;
/**
* Keyboard focus the editor group at the provided position.
@ -130,5 +131,5 @@ export interface IEditorGroupService {
/**
* Returns tab options.
*/
getTabOptions(): ITabOptions;
getTabOptions(): IEditorTabOptions;
}

View file

@ -79,9 +79,9 @@ export class TextEditorState {
}
}
interface ISerializedFileHistoryEntry {
resource?: string;
resourceJSON: object;
interface ISerializedEditorHistoryEntry {
resourceJSON?: object;
editorInputJSON?: { typeId: string; deserialized: string; };
}
interface IEditorIdentifier {
@ -224,7 +224,7 @@ export class HistoryService extends BaseHistoryService implements IHistoryServic
}
private registerListeners(): void {
this.toUnbind.push(this.lifecycleService.onShutdown(reason => this.save()));
this.toUnbind.push(this.lifecycleService.onShutdown(reason => this.saveHistory()));
this.toUnbind.push(this.editorGroupService.onEditorOpenFail(editor => this.remove(editor)));
this.toUnbind.push(this.editorGroupService.getStacksModel().onEditorClosed(event => this.onEditorClosed(event)));
this.toUnbind.push(this.fileService.onFileChanges(e => this.onFileChanges(e)));
@ -710,34 +710,58 @@ export class HistoryService extends BaseHistoryService implements IHistoryServic
this.loaded = true;
}
private save(): void {
private saveHistory(): void {
if (!this.history) {
return; // nothing to save because history was not used
}
const entries: ISerializedFileHistoryEntry[] = this.history.map(input => {
const registry = Registry.as<IEditorRegistry>(Extensions.Editors);
const entries: ISerializedEditorHistoryEntry[] = this.history.map(input => {
// Editor input: try via factory
if (input instanceof EditorInput) {
return void 0; // only file resource inputs are serializable currently
const factory = registry.getEditorInputFactory(input.getTypeId());
if (factory) {
return { editorInputJSON: { typeId: input.getTypeId(), deserialized: factory.serialize(input) } } as ISerializedEditorHistoryEntry;
}
}
return { resourceJSON: (input as IResourceInput).resource.toJSON() };
// File resource: via URI.toJSON()
else {
return { resourceJSON: (input as IResourceInput).resource.toJSON() } as ISerializedEditorHistoryEntry;
}
return void 0;
}).filter(serialized => !!serialized);
this.storageService.store(HistoryService.STORAGE_KEY, JSON.stringify(entries), StorageScope.WORKSPACE);
}
private loadHistory(): void {
let entries: ISerializedFileHistoryEntry[] = [];
let entries: ISerializedEditorHistoryEntry[] = [];
const entriesRaw = this.storageService.get(HistoryService.STORAGE_KEY, StorageScope.WORKSPACE);
if (entriesRaw) {
entries = JSON.parse(entriesRaw);
}
const registry = Registry.as<IEditorRegistry>(Extensions.Editors);
this.history = entries.map(entry => {
const serializedFileInput = entry as ISerializedFileHistoryEntry;
if (serializedFileInput.resource || serializedFileInput.resourceJSON) {
return { resource: !!serializedFileInput.resourceJSON ? URI.revive(serializedFileInput.resourceJSON) : URI.parse(serializedFileInput.resource) } as IResourceInput;
const serializedEditorHistoryEntry = entry as ISerializedEditorHistoryEntry;
// File resource: via URI.revive()
if (serializedEditorHistoryEntry.resourceJSON) {
return { resource: URI.revive(serializedEditorHistoryEntry.resourceJSON) } as IResourceInput;
}
// Editor input: via factory
if (serializedEditorHistoryEntry.editorInputJSON) {
const factory = registry.getEditorInputFactory(serializedEditorHistoryEntry.editorInputJSON.typeId);
if (factory) {
return factory.deserialize(this.instantiationService, serializedEditorHistoryEntry.editorInputJSON.deserialized);
}
}
return void 0;

View file

@ -17,7 +17,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { KeyCode, SimpleKeybinding, ChordKeybinding } from 'vs/base/common/keyCodes';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import extfs = require('vs/base/node/extfs');
import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestContextService } from 'vs/workbench/test/workbenchTestServices';
import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestContextService, TestTextResourceConfigurationService } from 'vs/workbench/test/workbenchTestServices';
import { IWorkspaceContextService, Workspace } from 'vs/platform/workspace/common/workspace';
import uuid = require('vs/base/common/uuid');
import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
@ -74,7 +74,7 @@ suite('Keybindings Editing', () => {
instantiationService.stub(ITelemetryService, NullTelemetryService);
instantiationService.stub(IModeService, ModeServiceImpl);
instantiationService.stub(IModelService, instantiationService.createInstance(ModelServiceImpl));
instantiationService.stub(IFileService, new FileService(new TestContextService(new Workspace(testDir, testDir, [uri.file(testDir)])), new TestConfigurationService(), { disableWatcher: true }));
instantiationService.stub(IFileService, new FileService(new TestContextService(new Workspace(testDir, testDir, [uri.file(testDir)])), new TestTextResourceConfigurationService(), new TestConfigurationService(), { disableWatcher: true }));
instantiationService.stub(IUntitledEditorService, instantiationService.createInstance(UntitledEditorService));
instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService));
instantiationService.stub(ITextModelService, <ITextModelService>instantiationService.createInstance(TextModelResolverService));

View file

@ -215,8 +215,18 @@ export class FileWalker {
let leftover = '';
let first = true;
const tree = this.initDirectoryTree();
const useRipgrep = this.config.useRipgrep;
const cmd = useRipgrep ? spawnRipgrepCmd(folderQuery, this.config.includePattern, this.folderExcludePatterns.get(folderQuery.folder)).cmd : this.spawnFindCmd(folderQuery);
let cmd: childProcess.ChildProcess;
let noSiblingsClauses: boolean;
if (useRipgrep) {
const ripgrep = spawnRipgrepCmd(folderQuery, this.config.includePattern, this.folderExcludePatterns.get(folderQuery.folder));
cmd = ripgrep.cmd;
noSiblingsClauses = !Object.keys(ripgrep.siblingClauses).length;
} else {
cmd = this.spawnFindCmd(folderQuery);
}
this.collectStdout(cmd, 'utf8', (err: Error, stdout?: string, last?: boolean) => {
if (err) {
done(err);
@ -246,6 +256,19 @@ export class FileWalker {
return;
}
this.cmdResultCount += relativeFiles.length;
if (useRipgrep && noSiblingsClauses) {
for (const relativePath of relativeFiles) {
const basename = path.basename(relativePath);
this.matchFile(onResult, { base: rootFolder, relativePath, basename });
}
if (last) {
done();
}
return;
}
// TODO: Optimize siblings clauses with ripgrep here.
this.addDirectoryEntries(tree, rootFolder, relativeFiles, onResult);
@ -382,8 +405,6 @@ export class FileWalker {
}
private addDirectoryEntries({ pathToEntries }: IDirectoryTree, base: string, relativeFiles: string[], onResult: (result: IRawFileMatch) => void) {
this.cmdResultCount += relativeFiles.length;
// Support relative paths to files from a root resource (ignores excludes)
if (relativeFiles.indexOf(this.filePattern) !== -1) {
const basename = path.basename(this.filePattern);

View file

@ -32,7 +32,7 @@ import { ILifecycleService, ShutdownEvent, ShutdownReason, StartupKind, Lifecycl
import { EditorStacksModel } from 'vs/workbench/common/editor/editorStacksModel';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IEditorGroupService, GroupArrangement, GroupOrientation, ITabOptions, IMoveOptions } from 'vs/workbench/services/group/common/groupService';
import { IEditorGroupService, GroupArrangement, GroupOrientation, IEditorTabOptions, IMoveOptions } from 'vs/workbench/services/group/common/groupService';
import { TextFileService } from 'vs/workbench/services/textfile/common/textFileService';
import { FileOperationEvent, IFileService, IResolveContentOptions, FileOperationError, IFileStat, IResolveFileResult, IImportResult, FileChangesEvent, IResolveFileOptions, IContent, IUpdateContentOptions, IStreamContent } from 'vs/platform/files/common/files';
import { IModelService } from 'vs/editor/common/services/modelService';
@ -56,6 +56,8 @@ import { generateUuid } from 'vs/base/common/uuid';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IRecentlyOpened } from 'vs/platform/history/common/history';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
import { IPosition } from 'vs/editor/common/core/position';
export function createFileInput(instantiationService: IInstantiationService, resource: URI): FileEditorInput {
return instantiationService.createInstance(FileEditorInput, resource, void 0);
@ -220,7 +222,9 @@ export class TestTextFileService extends TextFileService {
export function workbenchInstantiationService(): IInstantiationService {
let instantiationService = new TestInstantiationService(new ServiceCollection([ILifecycleService, new TestLifecycleService()]));
instantiationService.stub(IWorkspaceContextService, new TestContextService(TestWorkspace));
instantiationService.stub(IConfigurationService, new TestConfigurationService());
const configService = new TestConfigurationService();
instantiationService.stub(IConfigurationService, configService);
instantiationService.stub(ITextResourceConfigurationService, new TestTextResourceConfigurationService(configService));
instantiationService.stub(IUntitledEditorService, instantiationService.createInstance(UntitledEditorService));
instantiationService.stub(IStorageService, new TestStorageService());
instantiationService.stub(IWorkbenchEditorService, new TestEditorService());
@ -436,14 +440,14 @@ export class TestEditorGroupService implements IEditorGroupService {
private _onEditorOpenFail: Emitter<IEditorInput>;
private _onEditorsMoved: Emitter<void>;
private _onGroupOrientationChanged: Emitter<void>;
private _onTabOptionsChanged: Emitter<ITabOptions>;
private _onTabOptionsChanged: Emitter<IEditorTabOptions>;
constructor(callback?: (method: string) => void) {
this._onEditorsMoved = new Emitter<void>();
this._onEditorsChanged = new Emitter<void>();
this._onGroupOrientationChanged = new Emitter<void>();
this._onEditorOpenFail = new Emitter<IEditorInput>();
this._onTabOptionsChanged = new Emitter<ITabOptions>();
this._onTabOptionsChanged = new Emitter<IEditorTabOptions>();
let services = new ServiceCollection();
@ -479,7 +483,7 @@ export class TestEditorGroupService implements IEditorGroupService {
return this._onGroupOrientationChanged.event;
}
public get onTabOptionsChanged(): Event<ITabOptions> {
public get onTabOptionsChanged(): Event<IEditorTabOptions> {
return this._onTabOptionsChanged.event;
}
@ -536,7 +540,7 @@ export class TestEditorGroupService implements IEditorGroupService {
return this.stacksModel;
}
public getTabOptions(): ITabOptions {
public getTabOptions(): IEditorTabOptions {
return {};
}
}
@ -1162,3 +1166,21 @@ export class TestWindowsService implements IWindowsService {
}
}
export class TestTextResourceConfigurationService implements ITextResourceConfigurationService {
_serviceBrand: any;
constructor(private configurationService = new TestConfigurationService()) {
}
public onDidUpdateConfiguration() {
return { dispose() { } };
}
public getConfiguration(resource: URI, section?: string): any;
public getConfiguration(resource: URI, position?: IPosition, section?: string): any;
public getConfiguration(resource: any, position?: any, section?: any): any;
public getConfiguration(resource: any, position?: any, section?: any): any {
return this.configurationService.getConfiguration(section, { resource });
}
}