diff --git a/.vscode/launch.json b/.vscode/launch.json index 8482791..c6115de 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,6 +6,7 @@ "type": "extensionHost", "request": "launch", "args": [ + "--disable-extensions", "--extensionDevelopmentPath=${workspaceFolder}" ], "outFiles": [ diff --git a/.vscode/settings.json b/.vscode/settings.json index 8084fa3..a793b40 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,10 +1,10 @@ { "files.exclude": { "out": false, - ".vscode-test": true, }, "search.exclude": { - "out": true + "out": true, + ".vscode-test": true, }, "typescript.tsc.autoDetect": "off", "git.branchProtection": [ ] diff --git a/.vscodeignore b/.vscodeignore index 72aa0fe..dd881d8 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -2,10 +2,7 @@ .vscode-test/** src/** .gitignore -.yarnrc -vsc-extension-quickstart.md **/tsconfig.json **/.eslintrc.json **/*.map **/*.ts -**/.vscode-test.* diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f027b3..1699ad4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ # Changelog +### v1.0.1 + +- Refactor Configuration to a separate class + ### v1.0.0 - Add example to readme diff --git a/package-lock.json b/package-lock.json index 3d2e265..628c621 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "dotfiles", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dotfiles", - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", "devDependencies": { "@types/mocha": "^10.0.6", diff --git a/package.json b/package.json index 64a73f5..f37ce40 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ }, "description": "Apply dotfiles from settings", "icon": "images/icon-small.png", - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", "preview": true, "engines": { diff --git a/src/Configuration.ts b/src/Configuration.ts new file mode 100644 index 0000000..2b07ec3 --- /dev/null +++ b/src/Configuration.ts @@ -0,0 +1,37 @@ +import path from 'path'; +import * as vscode from "vscode"; + +export default class Configuration { + readonly namespace: string; + readonly logger?: (msg: string) => void; + + constructor(namespace: string, logger: (msg: string) => void) { + this.namespace = namespace; + this.logger = logger; + } + + getDirectoryPath() { + let directory = vscode.workspace.getConfiguration(this.namespace).get("directory") || process.env["XDG_CONFIG_HOME"] || path.join(process.env["HOME"]!, ".config"); + if (directory.endsWith("/")) { + return directory.slice(directory.length - 1); + } + return directory; + } + + getFiles() { + return vscode.workspace.getConfiguration(this.namespace).get<{ [key: string]: string; }>("files", {}); + } + + async setFiles(files: { [key: string]: string; }) { + try { + await vscode.workspace.getConfiguration(this.namespace).update("files", files, vscode.ConfigurationTarget.Global); + } catch (err) { + this.logger?.(`${new Date().toLocaleString()}: failed to update files: ${err}`); + vscode.window.showErrorMessage("Unable to update dotfiles.files: " + err); + } + } + + shouldAutoUpdate() { + return vscode.workspace.getConfiguration(this.namespace).get("autoUpdate", false); + } +} diff --git a/src/extension.ts b/src/extension.ts index 0e4bbc0..9ca7b53 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,38 +1,15 @@ import * as fs from "fs/promises"; import path from 'path'; import * as vscode from 'vscode'; +import Configuration from "./Configuration"; -const configNamespace = "dotfiles"; +export const configNamespace = "dotfiles"; const outputChannel = vscode.window.createOutputChannel(configNamespace); -function getDirectoryPath() { - let directory = vscode.workspace.getConfiguration(configNamespace).get("directory") || process.env["XDG_CONFIG_HOME"] || path.join(process.env["HOME"]!, ".config"); - if (directory.endsWith("/")) { - return directory.slice(directory.length - 1); - } - return directory; -} - -function getFiles() { - return vscode.workspace.getConfiguration(configNamespace).get<{ [key: string]: string; }>("files", {}); -} - -async function setFiles(files: { [key: string]: string; }) { - try { - await vscode.workspace.getConfiguration(configNamespace).update("files", files, vscode.ConfigurationTarget.Global); - } catch (err) { - outputChannel.appendLine(`${new Date().toLocaleString()}: failed to update files: ${err}`); - vscode.window.showErrorMessage("Unable to update dotfiles.files: " + err); - } -} - -function shouldAutoUpdate() { - return vscode.workspace.getConfiguration(configNamespace).get("autoUpdate", false); -} - async function apply() { - const directory = getDirectoryPath(); - for (const [file, content] of Object.entries(getFiles())) { + const configuration = new Configuration(configNamespace, outputChannel.appendLine); + const directory = configuration.getDirectoryPath(); + for (const [file, content] of Object.entries(configuration.getFiles())) { const filePath = path.join(directory, file); try { await fs.stat(filePath); @@ -45,24 +22,25 @@ async function apply() { } function didSave(doc: vscode.TextDocument) { - if (!shouldAutoUpdate()) { + const configuration = new Configuration(configNamespace, outputChannel.appendLine); + if (!configuration.shouldAutoUpdate()) { return; } if (doc.uri.scheme !== "file") { return; } - const directory = getDirectoryPath(); + const directory = configuration.getDirectoryPath(); if (!doc.uri.path.startsWith(directory + "/")) { return; } - const files = getFiles(); + const files = configuration.getFiles(); const relativePath = doc.uri.path.slice(directory.length + 1); if (!files[relativePath]) { outputChannel.appendLine(`${new Date().toLocaleString()}: file ${relativePath} in ${directory} not found in settings`); return; } files[relativePath] = doc.getText(); - setFiles(files); + configuration.setFiles(files); outputChannel.appendLine(`${new Date().toLocaleString()}: updated ${relativePath}`); } @@ -71,7 +49,8 @@ export function activate(context: vscode.ExtensionContext) { vscode.commands.registerCommand("dotfiles.apply", apply), vscode.workspace.onDidSaveTextDocument(didSave) ); - if (shouldAutoUpdate()) { + const configuration = new Configuration(configNamespace, outputChannel.appendLine); + if (configuration.shouldAutoUpdate()) { apply(); } } diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index 4ca0ab4..6f4eebf 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -1,15 +1,17 @@ -import * as assert from 'assert'; +import * as assert from "assert"; +import * as vscode from "vscode"; +import Configuration from "../Configuration"; -// You can import and use all API from the 'vscode' module -// as well as import your extension to test it -import * as vscode from 'vscode'; -// import * as myExtension from '../../extension'; - -suite('Extension Test Suite', () => { - vscode.window.showInformationMessage('Start all tests.'); - - test('Sample test', () => { - assert.strictEqual(-1, [1, 2, 3].indexOf(5)); - assert.strictEqual(-1, [1, 2, 3].indexOf(0)); +suite("Extension", () => { + suiteSetup(() => { + vscode.extensions.getExtension("grg.dotfiles")!.activate(); + }); + test("setFiles is idempotent", () => { + const testNamespace = "dotfiles"; + const configuration = new Configuration(testNamespace, () => { }); + const files = configuration.getFiles(); + configuration.setFiles(files); + configuration.setFiles(files); + assert.deepStrictEqual(configuration.getFiles(), files); }); });