From ea296cfd0e684e10ce68c7b772efaf46a939408c Mon Sep 17 00:00:00 2001 From: Grigory Date: Wed, 27 Nov 2024 17:45:40 +0500 Subject: [PATCH] feat: add option to disable context menu entry and hide the entry when editorconfig already exists --- package.json | 14 ++++++---- src/api.ts | 29 +++++++++++++++++++- src/commands/generateEditorConfig.ts | 23 ++++++---------- src/editorConfigMain.ts | 41 ++++++++++++++++++++++++++-- 4 files changed, 84 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 1d3711f..735e860 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,11 @@ "type": "string", "default": "default", "description": "If generateAuto is false, this template path will be used for each newly-generated .editorconfig file." + }, + "editorconfig.showMenuEntry": { + "type": "boolean", + "default": true, + "description": "Show the 'Generate .editorconfig' entry in the context menu of the Explorer view." } } }, @@ -61,13 +66,13 @@ "commandPalette": [ { "command": "EditorConfig.generate", - "when": "explorerResourceIsFolder" + "when": "explorerResourceIsFolder && config.editorconfig.showMenuEntry && editorconfig.showMenuEntry" } ], "explorer/context": [ { "command": "EditorConfig.generate", - "when": "explorerResourceIsFolder", + "when": "explorerResourceIsFolder && config.editorconfig.showMenuEntry && editorconfig.showMenuEntry", "group": "EditorConfig@1" } ] @@ -128,16 +133,13 @@ }, "scripts": { "clean": "rimraf out", - "prebuild": "npm run clean", "build": "tsc", - "postbuild": "cp -r src/test/suite/fixtures out/test/suite && cp -r src/test/untitled-suite/fixtures out/test/untitled-suite && cp src/DefaultTemplate.editorconfig out", "lint": "eslint src/**/*.ts", "pretest": "npm run lint && npm run build", "prewatch": "npm run build", "watch": "tsc -watch", "check-types": "tsc --noEmit", - "test": "node out/test/runTest.js", - "vscode:prepublish": "npm run build" + "test": "node out/test/runTest.js" }, "husky": { "hooks": { diff --git a/src/api.ts b/src/api.ts index 24d4d35..98e86f4 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,5 +1,12 @@ import * as editorconfig from 'editorconfig' -import { TextDocument, TextEditorOptions, Uri, window, workspace } from 'vscode' +import { + TextDocument, + TextEditorOptions, + Uri, + FileType, + window, + workspace, +} from 'vscode' /** * Resolves `TextEditorOptions` for a `TextDocument`, combining the editor's @@ -203,3 +210,23 @@ export function toEditorConfig(options: TextEditorOptions) { return tabSize === 'auto' ? 4 : parseInt(String(tabSize), 10) } } + +/** + * Get the URI of the .editorconfig file in the given folder + */ +export async function getEditorConfigUri(folderUri: Uri) { + const editorConfigUri = Uri.parse(`${folderUri.toString()}/.editorconfig`) + + try { + const stats = await workspace.fs.stat(editorConfigUri) + if (stats.type === FileType.File) { + return editorConfigUri + } + } catch (err) { + if (err && err.name !== 'EntryNotFound (FileSystemError)') { + throw err + } + } + + return +} diff --git a/src/commands/generateEditorConfig.ts b/src/commands/generateEditorConfig.ts index 7fd0326..70276af 100644 --- a/src/commands/generateEditorConfig.ts +++ b/src/commands/generateEditorConfig.ts @@ -2,7 +2,8 @@ import { readFile as _readFile } from 'fs' import { EOL } from 'os' import { resolve } from 'path' import { promisify } from 'util' -import { FileType, Uri, window, workspace } from 'vscode' +import { Uri, window, workspace } from 'vscode' +import { getEditorConfigUri } from '../api' const readFile = promisify(_readFile) @@ -19,27 +20,21 @@ export async function generateEditorConfig(uri: Uri) { return } - const editorConfigUri = Uri.parse(`${currentUri.toString()}/.editorconfig`) - try { - const stats = await workspace.fs.stat(editorConfigUri) - if (stats.type === FileType.File) { + if (await getEditorConfigUri(currentUri)) { window.showErrorMessage( 'An .editorconfig file already exists in this workspace.', ) return } - } catch (err) { - if (err) { - if (err.name === 'EntryNotFound (FileSystemError)') { - writeFile() - } else { - window.showErrorMessage(err.message) - } - return - } + } catch (error) { + window.showErrorMessage(error.message) + return } + const editorConfigUri = Uri.parse(`${currentUri.toString()}/.editorconfig`) + writeFile() + async function writeFile() { const ec = workspace.getConfiguration('editorconfig') const generateAuto = !!ec.get('generateAuto') diff --git a/src/editorConfigMain.ts b/src/editorConfigMain.ts index 346d63b..83cc2c9 100644 --- a/src/editorConfigMain.ts +++ b/src/editorConfigMain.ts @@ -1,10 +1,17 @@ -import { commands, DocumentSelector, ExtensionContext, languages } from 'vscode' +import { + commands, + DocumentSelector, + ExtensionContext, + languages, + workspace, +} from 'vscode' import { applyTextEditorOptions, fromEditorConfig, resolveCoreConfig, resolveTextEditorOptions, toEditorConfig, + getEditorConfigUri, } from './api' import { generateEditorConfig } from './commands/generateEditorConfig' import DocumentWatcher from './DocumentWatcher' @@ -13,7 +20,7 @@ import EditorConfigCompletionProvider from './EditorConfigCompletionProvider' /** * Main entry */ -export function activate(ctx: ExtensionContext) { +export async function activate(ctx: ExtensionContext) { ctx.subscriptions.push(new DocumentWatcher()) // register .editorconfig file completion provider @@ -35,6 +42,13 @@ export function activate(ctx: ExtensionContext) { }, 100) }) + await updateShowMenuEntryContext() + ctx.subscriptions.push( + workspace.onDidCreateFiles(updateShowMenuEntryContext), + workspace.onDidDeleteFiles(updateShowMenuEntryContext), + workspace.onDidRenameFiles(updateShowMenuEntryContext), + ) + // register a command handler to generate a .editorconfig file commands.registerCommand('EditorConfig.generate', generateEditorConfig) @@ -46,3 +60,26 @@ export function activate(ctx: ExtensionContext) { toEditorConfig, } } + +async function updateShowMenuEntryContext() { + const workspaceUri = + workspace.workspaceFolders && workspace.workspaceFolders[0].uri + if (!workspaceUri) { + setShowMenuEntryContext(false) + return + } + + try { + if (await getEditorConfigUri(workspaceUri)) { + setShowMenuEntryContext(false) + } else { + setShowMenuEntryContext(true) + } + } catch { + setShowMenuEntryContext(false) + } +} + +function setShowMenuEntryContext(value: boolean) { + commands.executeCommand('setContext', 'editorconfig.showMenuEntry', value) +}