├── .gitignore
├── src
├── .editorconfig
└── editorConfigMain.ts
├── typings
├── node.d.ts
├── vscode-typings.d.ts
└── editorconfig.d.ts
├── EditorConfig_icon.png
├── .vscodeignore
├── tsconfig.json
├── .vscode
├── settings.json
├── launch.json
└── tasks.json
├── .editorconfig
├── test
├── index.ts
└── extension.test.ts
├── LICENSE.md
├── README.md
├── package.json
└── ThirdPartyNotices.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | node_modules
3 | .DS_Store
4 | Thumbs.db
5 | *.log
--------------------------------------------------------------------------------
/src/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.ts]
2 | indent_style = space
3 | indent_size = 4
4 |
--------------------------------------------------------------------------------
/typings/node.d.ts:
--------------------------------------------------------------------------------
1 | ///
--------------------------------------------------------------------------------
/typings/vscode-typings.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/EditorConfig_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/vscode-editorconfig/HEAD/EditorConfig_icon.png
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | typings/**
3 | out/test/**
4 | test/**
5 | src/**
6 | **/*.map
7 | .gitignore
8 | tsconfig.json
9 | vsc-extension-quickstart.md
10 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "ES5",
5 | "outDir": "out",
6 | "noLib": true,
7 | "sourceMap": true
8 | },
9 | "exclude": [
10 | "node_modules"
11 | ]
12 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "out": false // set this to true to hide the "out" folder with the compiled JS files
5 | },
6 | "search.exclude": {
7 | "out": true // set this to false to include "out" folder in search results
8 | },
9 | "files.trimTrailingWhitespace": true,
10 | "typescript.tsdk": "./node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version
11 | }
--------------------------------------------------------------------------------
/typings/editorconfig.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'editorconfig' {
2 |
3 | export interface knownProps {
4 | end_of_line?: string,
5 | indent_style?: string,
6 | indent_size?: any,
7 | insert_final_newline?: boolean,
8 | tab_width?: number,
9 | trim_trailing_whitespace?: boolean,
10 | charset?: string
11 | }
12 |
13 | export interface options {config:string, version: string, root:string}
14 |
15 | export function parse(filepath:string, options?:options): any;
16 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Unix-style newlines with a newline ending every file
7 | [*]
8 | end_of_line = lf
9 | insert_final_newline = true
10 |
11 | [*.ts]
12 | indent_style = tab
13 | indent_size = 4
14 |
15 | # Matches multiple files with brace expansion notation
16 | # Set default charset
17 | [*.{js,py}]
18 | charset = utf-8
19 |
20 | # 4 space indentation
21 | [*.py]
22 | indent_style = space
23 | indent_size = 4
24 |
25 | # Tab indentation (no size specified)
26 | [Makefile]
27 | indent_style = tab
28 |
29 | # Indentation override for all JS under lib directory
30 | [lib/**.js]
31 | indent_style = space
32 | indent_size = 2
33 |
34 | # Matches the exact files either package.json or .travis.yml
35 | [{package.json,.travis.yml}]
36 | indent_style = space
37 | indent_size = 2
38 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | // A launch configuration that compiles the extension and then opens it inside a new window
2 | {
3 | "version": "0.1.0",
4 | "configurations": [
5 | {
6 | "name": "Launch Extension",
7 | "type": "extensionHost",
8 | "request": "launch",
9 | "runtimeExecutable": "${execPath}",
10 | "args": ["--extensionDevelopmentPath=${workspaceRoot}" ],
11 | "stopOnEntry": false,
12 | "sourceMaps": true,
13 | "outDir": "out/src",
14 | "preLaunchTask": "npm"
15 | },
16 | {
17 | "name": "Launch Tests",
18 | "type": "extensionHost",
19 | "request": "launch",
20 | "runtimeExecutable": "${execPath}",
21 | "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ],
22 | "stopOnEntry": false,
23 | "sourceMaps": true,
24 | "outDir": "out/test",
25 | "preLaunchTask": "npm"
26 | }
27 | ]
28 | }
--------------------------------------------------------------------------------
/test/index.ts:
--------------------------------------------------------------------------------
1 | //
2 | // PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
3 | //
4 | // This file is providing the test runner to use when running extension tests.
5 | // By default the test runner in use is Mocha based.
6 | //
7 | // You can provide your own test runner if you want to override it by exporting
8 | // a function run(testRoot: string, clb: (error:Error) => void) that the extension
9 | // host can call to run the tests. The test runner is expected to use console.log
10 | // to report the results back to the caller. When the tests are finished, return
11 | // a possible error to the callback or null if none.
12 |
13 | var testRunner = require('vscode/lib/testrunner');
14 |
15 | // You can directly control Mocha options by uncommenting the following lines
16 | // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
17 | testRunner.configure({
18 | ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.)
19 | useColors: true // colored output from test results
20 | });
21 |
22 | module.exports = testRunner;
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // Available variables which can be used inside of strings.
2 | // ${workspaceRoot}: the root folder of the team
3 | // ${file}: the current opened file
4 | // ${fileBasename}: the current opened file's basename
5 | // ${fileDirname}: the current opened file's dirname
6 | // ${fileExtname}: the current opened file's extension
7 | // ${cwd}: the current working directory of the spawned process
8 |
9 | // A task runner that calls a custom npm script that compiles the extension.
10 | {
11 | "version": "0.1.0",
12 |
13 | // we want to run npm
14 | "command": "npm",
15 |
16 | // the command is a shell script
17 | "isShellCommand": true,
18 |
19 | // show the output window only if unrecognized errors occur.
20 | "showOutput": "silent",
21 |
22 | // we run the custom script "compile" as defined in package.json
23 | "args": ["run", "compile", "--loglevel", "silent"],
24 |
25 | // The tsc compiler is started in watching mode
26 | "isWatching": true,
27 |
28 | // use the standard tsc in watch mode problem matcher to find compile problems in the output.
29 | "problemMatcher": "$tsc-watch"
30 | }
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) Microsoft Corporation
2 |
3 | All rights reserved.
4 |
5 | MIT License
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Editor Config for Visual Studio Code
2 |
3 | > **This version of the Editor Config extension has been deprecated.**
4 |
5 | > Please see [editorconfig/editorconfig-vscode](https://github.com/editorconfig/editorconfig-vscode) for the latest Editor Config extension for VS Code.
6 |
7 | The `microsoft/vscode-editorconfig` extension was initially created to validate the VS Code extension API. This has been a very popular extension that is now actively being enhanced and maintained by the community at [editorconfig/editorconfig-vscode](https://github.com/editorconfig/editorconfig-vscode).
8 |
9 | We are excited to see the community take ownership of this extension. As a result, we are no longer maintaining this version. We recommend that you uninstall the Microsoft version (published by `Chris Dias`) by bringing up the Command Palette, typing in `ext Editor Config`, and clicking on the Uninstall icon:
10 |
11 | 
12 |
13 | Afte restarting VS Code, you can install the latest from the `EditorConfig` publisher:
14 |
15 | 
16 |
17 | We apologize for the inconvenience and thank the community for taking this on!
18 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vscodeEditorConfig",
3 | "displayName": "Editor Config for VS Code",
4 | "description": "DEPRECATED - See Read Me for more information",
5 | "publisher": "chrisdias",
6 | "version": "0.1.7",
7 | "icon": "./EditorConfig_icon.png",
8 | "engines": {
9 | "vscode": "^0.10.1"
10 | },
11 | "author": "Microsoft Corporation",
12 | "license": "MIT",
13 | "categories": [
14 | "Other"
15 | ],
16 | "homepage": "https://github.com/Microsoft/vscode-editorconfig/blob/master/README.md",
17 | "repository": {
18 | "type": "git",
19 | "url": "https://github.com/Microsoft/vscode-editorconfig.git"
20 | },
21 | "bugs": {
22 | "url": "https://github.com/Microsoft/vscode-editorconfig/issues"
23 | },
24 | "galleryBanner": {
25 | "color": "#37699A",
26 | "theme": "dark"
27 | },
28 | "activationEvents": [
29 | "*"
30 | ],
31 | "main": "./out/src/editorConfigMain",
32 | "contributes": {
33 | "commands": [
34 | {
35 | "command": "vscode.generateeditorconfig",
36 | "title": "EditorConfig: Generate"
37 | }
38 | ]
39 | },
40 | "dependencies": {
41 | "editorconfig": "0.12.2",
42 | "open": "0.0.5"
43 | },
44 | "devDependencies": {
45 | "typescript": "^1.6.2",
46 | "vscode": "0.10.x"
47 | },
48 | "scripts": {
49 | "vscode:prepublish": "node ./node_modules/vscode/bin/compile",
50 | "compile": "node ./node_modules/vscode/bin/compile -watch -p ./"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/ThirdPartyNotices.txt:
--------------------------------------------------------------------------------
1 | THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
2 | Do Not Translate or Localize
3 |
4 | This project incorporates material from the project(s) listed below (collectively, “Third Party Code”).
5 | Microsoft is not the original author of the Third Party Code. The original copyright notice and license
6 | under which Microsoft received such Third Party Code are set out below. This Third Party Code is licensed
7 | to you under their original license terms set forth below. Microsoft reserves all other rights not
8 | expressly granted, whether by implication, estoppel or otherwise.
9 |
10 | ============================================================
11 | editorconfig https://github.com/editorconfig/editorconfig-core-js
12 |
13 | Copyright © 2012 EditorConfig Team
14 |
15 | Permission is hereby granted, free of charge, to any person obtaining a copy
16 | of this software and associated documentation files (the “Software”), to deal
17 | in the Software without restriction, including without limitation the rights
18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19 | copies of the Software, and to permit persons to whom the Software is
20 | furnished to do so, subject to the following conditions:
21 |
22 | The above copyright notice and this permission notice shall be included in
23 | all copies or substantial portions of the Software.
24 |
25 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31 | THE SOFTWARE.
32 |
33 | ============================================================
34 |
35 | node-open https://github.com/pwnall/node-open
36 |
37 | Copyright (c) 2012 Jay Jordan
38 |
39 | Permission is hereby granted, free of charge, to any person
40 | obtaining a copy of this software and associated documentation
41 | files (the "Software"), to deal in the Software without
42 | restriction, including without limitation the rights to use,
43 | copy, modify, merge, publish, distribute, sublicense, and/or sell
44 | copies of the Software, and to permit persons to whom the
45 | Software is furnished to do so, subject to the following
46 | conditions:
47 |
48 | The above copyright notice and this permission notice shall be
49 | included in all copies or substantial portions of the Software.
50 |
51 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
52 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
53 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
54 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
55 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
56 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
57 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
58 | OTHER DEALINGS IN THE SOFTWARE.
59 |
60 | ============================================================
61 |
--------------------------------------------------------------------------------
/test/extension.test.ts:
--------------------------------------------------------------------------------
1 | import * as assert from 'assert';
2 | import * as vscode from 'vscode';
3 | import {Utils} from '../src/editorConfigMain';
4 |
5 | suite('.editorconfig extension', () => {
6 |
7 | // Defines a Mocha unit test
8 | test('Utils.fromEditorConfig', () => {
9 | [
10 | {
11 | config: {
12 | indent_style: 'tab',
13 | indent_size: 5
14 | },
15 | defaults: {
16 | insertSpaces: false,
17 | tabSize: 4
18 | },
19 | expected: {
20 | insertSpaces: false,
21 | tabSize: 5
22 | }
23 | },
24 | {
25 | config: {
26 | indent_style: 'tab',
27 | tab_width: 5
28 | },
29 | defaults: {
30 | insertSpaces: false,
31 | tabSize: 4
32 | },
33 | expected: {
34 | insertSpaces: false,
35 | tabSize: 5
36 | }
37 | },
38 | {
39 | config: {
40 | indent_style: 'space',
41 | indent_size: 5
42 | },
43 | defaults: {
44 | insertSpaces: false,
45 | tabSize: 4
46 | },
47 | expected: {
48 | insertSpaces: true,
49 | tabSize: 5
50 | }
51 | },
52 | {
53 | config: {
54 | indent_size: 5
55 | },
56 | defaults: {
57 | insertSpaces: false,
58 | tabSize: 4
59 | },
60 | expected: {
61 | insertSpaces: false,
62 | tabSize: 5
63 | }
64 | },
65 | {
66 | config: {
67 | tab_width: 5
68 | },
69 | defaults: {
70 | insertSpaces: false,
71 | tabSize: 4
72 | },
73 | expected: {
74 | insertSpaces: false,
75 | tabSize: 5
76 | }
77 | },
78 | {
79 | config: {
80 | indent_size: 5
81 | },
82 | defaults: {
83 | insertSpaces: true,
84 | tabSize: 4
85 | },
86 | expected: {
87 | insertSpaces: true,
88 | tabSize: 5
89 | }
90 | },
91 | {
92 | config: {
93 | tab_width: 5
94 | },
95 | defaults: {
96 | insertSpaces: true,
97 | tabSize: 4
98 | },
99 | expected: {
100 | insertSpaces: true,
101 | tabSize: 5
102 | }
103 | },
104 | {
105 | config: {
106 | indent_style: 'space'
107 | },
108 | defaults: {
109 | insertSpaces: false,
110 | tabSize: 4
111 | },
112 | expected: {
113 | insertSpaces: true,
114 | tabSize: 4
115 | }
116 | },
117 | {
118 | config: {
119 | indent_style: 'space'
120 | },
121 | defaults: {
122 | insertSpaces: false,
123 | tabSize: 5
124 | },
125 | expected: {
126 | insertSpaces: true,
127 | tabSize: 5
128 | }
129 | },
130 | {
131 | config: {
132 | indent_size: 'tab',
133 | tab_width: 3
134 | },
135 | defaults: {
136 | insertSpaces: false,
137 | tabSize: 5
138 | },
139 | expected: {
140 | insertSpaces: false,
141 | tabSize: 3
142 | }
143 | },
144 | {
145 | config: {},
146 | defaults: {
147 | insertSpaces: false,
148 | tabSize: 5
149 | },
150 | expected: {
151 | insertSpaces: false,
152 | tabSize: 5
153 | }
154 | },
155 | {
156 | config: {},
157 | defaults: {
158 | insertSpaces: true,
159 | tabSize: 4
160 | },
161 | expected: {
162 | insertSpaces: true,
163 | tabSize: 4
164 | }
165 | }
166 | ].forEach(({ config, defaults, expected }) => {
167 | assert.deepEqual(Utils.fromEditorConfig.call(this, config, defaults), expected);
168 | });
169 | });
170 |
171 | test('Utils.toEditorConfig', () => {
172 | [
173 | {
174 | options: {
175 | insertSpaces: true,
176 | tabSize: 5
177 | },
178 | expected: {
179 | indent_style: 'space',
180 | indent_size: 5
181 | }
182 | },
183 | {
184 | options: {
185 | insertSpaces: false,
186 | tabSize: 6
187 | },
188 | expected: {
189 | indent_style: 'tab',
190 | tab_width: 6
191 | }
192 | },
193 | {
194 | options: {
195 | insertSpaces: false,
196 | tabSize: 'auto'
197 | },
198 | expected: {
199 | indent_style: 'tab',
200 | tab_width: 4
201 | }
202 | },
203 | {
204 | options: {
205 | insertSpaces: 'auto',
206 | tabSize: 7
207 | },
208 | expected: {
209 | indent_style: 'tab',
210 | tab_width: 7
211 | }
212 | },
213 | {
214 | options: {
215 | insertSpaces: 'auto',
216 | tabSize: 'auto'
217 | },
218 | expected: {
219 | indent_style: 'tab',
220 | tab_width: 4
221 | }
222 | }
223 | ].forEach(({ options, expected }) => {
224 | assert.deepEqual(Utils.toEditorConfig.call(this, options), expected);
225 | });
226 | });
227 | });
--------------------------------------------------------------------------------
/src/editorConfigMain.ts:
--------------------------------------------------------------------------------
1 | import * as editorconfig from 'editorconfig';
2 | import * as fs from 'fs';
3 | import {commands, window, workspace, ExtensionContext, TextEditorOptions,
4 | TextEditor, TextEdit, TextDocument, Disposable, Position} from 'vscode';
5 |
6 | var open = require('open');
7 |
8 | export function activate(ctx: ExtensionContext): void {
9 |
10 | if (ctx.globalState.get('chrisdias.vscodeEditorConfig.informUser', true)) {
11 | window.showInformationMessage("This version of EditorConfig has been deprecated, more information is available online.", "How to Upgrade").then(selection => {
12 | if (selection) {
13 | open("https://marketplace.visualstudio.com/items?itemName=chrisdias.vscodeEditorConfig");
14 | }
15 | });
16 | // only prompt one time
17 | ctx.globalState.update('chrisdias.vscodeEditorConfig.informUser', false);
18 | }
19 |
20 | let documentWatcher = new DocumentWatcher();
21 |
22 | ctx.subscriptions.push(documentWatcher);
23 | ctx.subscriptions.push(window.onDidChangeActiveTextEditor((textEditor) => {
24 | applyEditorConfigToTextEditor(textEditor, documentWatcher);
25 | }));
26 | applyEditorConfigToTextEditor(window.activeTextEditor, documentWatcher);
27 |
28 | // register a command handler to generate a .editorconfig file
29 | commands.registerCommand('vscode.generateeditorconfig', generateEditorConfig);
30 | }
31 |
32 | interface IEditorConfigProvider {
33 | getSettingsForDocument(document: TextDocument): editorconfig.knownProps;
34 | }
35 |
36 | /**
37 | * Listens to vscode document open and maintains a map (Document => editor config settings)
38 | */
39 | class DocumentWatcher implements IEditorConfigProvider {
40 |
41 | private _documentToConfigMap: { [uri: string]: editorconfig.knownProps };
42 | private _disposable: Disposable;
43 |
44 | constructor() {
45 |
46 | let subscriptions: Disposable[] = []
47 |
48 | // Listen for new documents being openend
49 | subscriptions.push(workspace.onDidOpenTextDocument((doc) => this._onDidOpenDocument(doc)));
50 |
51 | // Listen for saves to ".editorconfig" files and rebuild the map
52 | subscriptions.push(workspace.onDidSaveTextDocument(savedDocument => {
53 | if (/\.editorconfig$/.test(savedDocument.fileName)) {
54 | // Saved an .editorconfig file => rebuild map entirely
55 | this._rebuildConfigMap();
56 | }
57 | applyOnSaveTransformations(savedDocument, this);
58 | }));
59 |
60 | // dispose event subscriptons upon disposal
61 | this._disposable = Disposable.from(...subscriptions);
62 |
63 | // Build the map (cover the case that documents were opened before my activation)
64 | this._rebuildConfigMap();
65 | }
66 |
67 | public dispose(): void {
68 | this._disposable.dispose();
69 | }
70 |
71 | public getSettingsForDocument(document: TextDocument): editorconfig.knownProps {
72 | return this._documentToConfigMap[document.fileName];
73 | }
74 |
75 | private _rebuildConfigMap(): void {
76 | this._documentToConfigMap = {};
77 | workspace.textDocuments.forEach(document => this._onDidOpenDocument(document));
78 | }
79 |
80 | private _onDidOpenDocument(document: TextDocument): void {
81 | if (document.isUntitled) {
82 | // Does not have a fs path
83 | return;
84 | }
85 |
86 | let path = document.fileName;
87 | editorconfig.parse(path).then((config: editorconfig.knownProps) => {
88 | // workaround for the fact that sometimes indent_size is set to "tab":
89 | // see https://github.com/editorconfig/editorconfig-core-js/blob/b2e00d96fcf3be242d4bf748829b8e3a778fd6e2/editorconfig.js#L56
90 | if (config.indent_size === 'tab') {
91 | delete config.indent_size;
92 | }
93 |
94 | // console.log('storing ' + path + ' to ' + JSON.stringify(config, null, '\t'));
95 | this._documentToConfigMap[path] = config;
96 |
97 | applyEditorConfigToTextEditor(window.activeTextEditor, this);
98 | });
99 | }
100 | }
101 |
102 | function applyEditorConfigToTextEditor(textEditor: TextEditor, provider: IEditorConfigProvider): void {
103 | if (!textEditor) {
104 | // No more open editors
105 | return;
106 | }
107 |
108 | let doc = textEditor.document;
109 | let editorconfig = provider.getSettingsForDocument(doc);
110 |
111 | if (!editorconfig) {
112 | // no configuration found for this file
113 | return;
114 | }
115 |
116 | let { insertSpaces, tabSize } = textEditor.options;
117 | let newOptions = Utils.fromEditorConfig(
118 | editorconfig,
119 | {
120 | insertSpaces,
121 | tabSize
122 | }
123 | );
124 |
125 | // console.log('setting ' + textEditor.document.fileName + ' to ' + JSON.stringify(newOptions, null, '\t'));
126 |
127 | window.setStatusBarMessage('EditorConfig: ' + (newOptions.insertSpaces ? "Spaces:" : "Tabs:") + ' ' + newOptions.tabSize, 1500);
128 |
129 | textEditor.options = newOptions;
130 | }
131 |
132 | function applyOnSaveTransformations(
133 | textDocument: TextDocument,
134 | provider: IEditorConfigProvider): void {
135 |
136 | let editorconfig = provider.getSettingsForDocument(textDocument);
137 |
138 | if (!editorconfig) {
139 | // no configuration found for this file
140 | return;
141 | }
142 |
143 | insertFinalNewlineTransform(editorconfig, textDocument);
144 | }
145 |
146 | function insertFinalNewlineTransform(
147 | editorconfig: editorconfig.knownProps,
148 | textDocument: TextDocument): void {
149 |
150 | if (editorconfig.insert_final_newline && textDocument.lineCount > 0) {
151 | let lastLine = textDocument.lineAt(textDocument.lineCount - 1);
152 | let lastLineLength = lastLine.text.length;
153 | if (lastLineLength < 1) {
154 | return;
155 | }
156 | let editor = findEditor(textDocument);
157 | if (!editor) {
158 | return;
159 | }
160 | editor.edit(edit => {
161 | let pos = new Position(lastLine.lineNumber, lastLineLength);
162 | return edit.insert(pos, newline(editorconfig));
163 | }).then(() => textDocument.save());
164 | }
165 | }
166 |
167 | function newline(editorconfig: editorconfig.knownProps): string {
168 | if (editorconfig.end_of_line === 'cr') {
169 | return '\r';
170 | } else if (editorconfig.end_of_line == 'crlf') {
171 | return '\r\n';
172 | }
173 | return '\n';
174 | }
175 |
176 | function findEditor(textDocument: TextDocument): TextEditor {
177 | for (let editor of window.visibleTextEditors) {
178 | if (editor.document === textDocument) {
179 | return editor;
180 | }
181 | }
182 |
183 | return null;
184 | }
185 |
186 | /**
187 | * Generate an .editorconfig file in the root of the workspace based on the current vscode settings.
188 | */
189 | function generateEditorConfig() {
190 | if (!workspace.rootPath) {
191 | window.showInformationMessage("Please open a folder before generating an .editorconfig file");
192 | return;
193 | }
194 |
195 | let editorConfigurationNode = workspace.getConfiguration('editor');
196 | let settings = Utils.toEditorConfig({
197 | insertSpaces: editorConfigurationNode.get('insertSpaces'),
198 | tabSize: editorConfigurationNode.get('tabSize')
199 | });
200 |
201 | let fileContents =
202 | `root = true
203 |
204 | [*]
205 | `;
206 |
207 | [
208 | 'indent_style',
209 | 'indent_size',
210 | 'tab_width'
211 | ].forEach(setting => {
212 | if (settings.hasOwnProperty(setting)) {
213 | fileContents += `${setting} = ${settings[setting]}
214 | `;
215 | }
216 | });
217 |
218 | let editorconfigFile = workspace.rootPath + '/.editorconfig';
219 | fs.exists(editorconfigFile, (exists) => {
220 | if (exists) {
221 | window.showInformationMessage('An .editorconfig file already exists in your workspace.');
222 | return;
223 | }
224 |
225 | fs.writeFile(editorconfigFile, fileContents, err => {
226 | if (err) {
227 | window.showErrorMessage(err.toString());
228 | return;
229 | }
230 | });
231 | });
232 | }
233 |
234 | export class Utils {
235 |
236 | /**
237 | * Convert .editorconfig values to vscode editor options
238 | */
239 | public static fromEditorConfig(
240 | config: editorconfig.knownProps,
241 | defaults: {
242 | insertSpaces: boolean;
243 | tabSize: number;
244 | }
245 | ): TextEditorOptions {
246 | return {
247 | insertSpaces: config.indent_style ? (config.indent_style === 'tab' ? false : true) : defaults.insertSpaces,
248 | tabSize: config.tab_width || config.indent_size || defaults.tabSize
249 | };
250 | }
251 |
252 | /**
253 | * Convert vscode editor options to .editorconfig values
254 | */
255 | public static toEditorConfig(
256 | options: {
257 | insertSpaces: boolean | string;
258 | tabSize: number | string;
259 | }
260 | ) {
261 | let result: editorconfig.knownProps = {};
262 |
263 | switch (options.insertSpaces) {
264 | case true:
265 | result.indent_style = 'space';
266 | result.indent_size = Utils.resolveTabSize(options.tabSize);
267 | break;
268 | case false:
269 | case 'auto':
270 | result.indent_style = 'tab';
271 | result.tab_width = Utils.resolveTabSize(options.tabSize);
272 | break;
273 | }
274 |
275 | return result;
276 | }
277 |
278 | /**
279 | * Convert vscode tabSize option into numeric value
280 | */
281 | public static resolveTabSize(tabSize: number | string) {
282 | return (tabSize === 'auto') ? 4 : parseInt(tabSize + '', 10);
283 | }
284 | }
285 |
--------------------------------------------------------------------------------