From fdaee599d132026c13917b59a97456d1c3191305 Mon Sep 17 00:00:00 2001 From: Bajdzis Date: Sat, 5 Oct 2019 11:55:53 +0200 Subject: [PATCH] feat: create templates --- icons/awesome-template.svg | 7 ++ package-lock.json | 11 +++- package.json | 22 ++++++- src/__mocks__/vscode.ts | 4 ++ src/commands/saveAsTemplate.ts | 66 +++++++++++++++++++ src/extension.ts | 27 ++------ src/extenstion.test.ts | 10 ++- .../addExtensionToRecommendations.ts | 30 +++++++++ src/fileSystem/createDocument.ts | 15 +++++ src/fileSystem/ensureDirectoryExistence.ts | 11 ++++ 10 files changed, 176 insertions(+), 27 deletions(-) create mode 100644 icons/awesome-template.svg create mode 100644 src/commands/saveAsTemplate.ts create mode 100644 src/fileSystem/addExtensionToRecommendations.ts create mode 100644 src/fileSystem/createDocument.ts create mode 100644 src/fileSystem/ensureDirectoryExistence.ts diff --git a/icons/awesome-template.svg b/icons/awesome-template.svg new file mode 100644 index 0000000..6184e34 --- /dev/null +++ b/icons/awesome-template.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/package-lock.json b/package-lock.json index 9de19bb..306fcf6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -506,8 +506,7 @@ "@types/node": { "version": "10.14.18", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.18.tgz", - "integrity": "sha512-ryO3Q3++yZC/+b8j8BdKd/dn9JlzlHBPdm80656xwYUdmPkpTGTjkAdt6BByiNupGPE8w0FhBgvYy/fX9hRNGQ==", - "dev": true + "integrity": "sha512-ryO3Q3++yZC/+b8j8BdKd/dn9JlzlHBPdm80656xwYUdmPkpTGTjkAdt6BByiNupGPE8w0FhBgvYy/fX9hRNGQ==" }, "@types/stack-utils": { "version": "1.0.1", @@ -515,6 +514,14 @@ "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", "dev": true }, + "@types/uuid": { + "version": "3.4.5", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.5.tgz", + "integrity": "sha512-MNL15wC3EKyw1VLF+RoVO4hJJdk9t/Hlv3rt1OL65Qvuadm4BYo6g9ZJQqoq7X8NBFSsQXgAujWciovh2lpVjA==", + "requires": { + "@types/node": "*" + } + }, "@types/vscode": { "version": "1.38.0", "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.38.0.tgz", diff --git a/package.json b/package.json index c6babcc..0ea55c1 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,26 @@ }, "main": "./out/extension.js", "contributes": { - "commands": [], + "commands": [ + { + "command": "extension.saveAsTemplate", + "title": "Save file as awesome template", + "category": "FILE", + "icon": { + "dark": "icons/awesome-template.svg", + "light": "icons/awesome-template.svg" + } + } + ], + "menus": { + "editor/title": [ + { + "command": "extension.saveAsTemplate", + "group": "navigation@1", + "when": "resourceScheme == file" + } + ] + }, "configuration": { "title": "Awesome Tree", "properties": { @@ -80,6 +99,7 @@ "vscode-test": "^1.2.0" }, "dependencies": { + "@types/uuid": "^3.4.5", "lodash": "^4.17.15" } } diff --git a/src/__mocks__/vscode.ts b/src/__mocks__/vscode.ts index 87dd7f5..305bee6 100644 --- a/src/__mocks__/vscode.ts +++ b/src/__mocks__/vscode.ts @@ -15,3 +15,7 @@ export const window = { createOutputChannel: jest.fn(() => outputChanelMock), showInformationMessage: jest.fn(), } as {[key in keyof typeof vscode.window]: jest.Mock}; + +export const commands = { + registerCommand: jest.fn(), +} as {[key in keyof typeof vscode.commands]: jest.Mock}; diff --git a/src/commands/saveAsTemplate.ts b/src/commands/saveAsTemplate.ts new file mode 100644 index 0000000..c007742 --- /dev/null +++ b/src/commands/saveAsTemplate.ts @@ -0,0 +1,66 @@ +import * as fs from 'fs'; +import * as vscode from 'vscode'; +import * as path from 'path'; +import * as uuid from 'uuid/v4'; +import { getRelativePath } from '../fileSystem/getRelativePath'; +import { getInfoAboutPath } from '../fileInfo/getInfoAboutPath'; +import { createVariableTemplate } from '../variableTemplate/createVariableTemplate'; +import { createDocument } from '../fileSystem/createDocument'; +import { addExtensionToRecommendations } from '../fileSystem/addExtensionToRecommendations'; + +const DIRECTORY_FOR_TEMPLATES = 'awesome-tree-templates'; + +function findWorkspacePath(searchFsPath:string): string | undefined { + const { workspaceFolders } = vscode.workspace; + if(!workspaceFolders){ + return; + } + for (let i = 0; i < workspaceFolders.length; i++) { + const {fsPath} = workspaceFolders[i].uri; + if(searchFsPath.indexOf(fsPath) === 0){ + return fsPath; + } + } +} + +export function saveAsTemplate(file: vscode.Uri) { + const workspacePath = findWorkspacePath(file.fsPath); + if (workspacePath === undefined) { + vscode.window.showWarningMessage(`Can't find workspace directory for file: '${file.fsPath}'`); + return; + } + + const relativePath = getRelativePath(file.fsPath); + const templateId = uuid(); + const templatePath = path.join(workspacePath, DIRECTORY_FOR_TEMPLATES, 'templates', `template-${templateId}.json` ); + const templateDatabasePath = path.join(workspacePath, DIRECTORY_FOR_TEMPLATES, 'database-awesome.json' ); + const infoAboutNewFile = getInfoAboutPath(relativePath); + const lines = fs.readFileSync(file.fsPath).toString().split('\n'); + const templateLines = lines.map(line => createVariableTemplate(line, [infoAboutNewFile])); + + const template = { + baseFilePath: relativePath, + pathsTemplate: [ + createVariableTemplate(relativePath, [infoAboutNewFile]) + ], + templateId + }; + + let currentSavedTemplates: Array; + + try { + currentSavedTemplates = JSON.parse(fs.readFileSync(templateDatabasePath).toString()); + } catch (error) { + currentSavedTemplates = []; + } + + currentSavedTemplates.push(template); + + Promise.all([ + createDocument(templatePath, JSON.stringify(templateLines, null, 4)), + createDocument(templateDatabasePath, JSON.stringify(currentSavedTemplates, null, 4)) + ]).then(() => { + vscode.window.showInformationMessage('Saved success!'); + addExtensionToRecommendations(workspacePath); + }); +} diff --git a/src/extension.ts b/src/extension.ts index 73a7b44..a177f69 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -10,12 +10,15 @@ import { getRelativePath } from './fileSystem/getRelativePath'; import { getSiblingInfo, DirectoriesInfo } from './fileInfo/getSiblingInfo'; import { getPathTemplates } from './fileSystem/getPathTemplates'; import { getFilesContentAsTemplate } from './fileSystem/getFilesContentAsTemplate'; +import { saveAsTemplate } from './commands/saveAsTemplate'; +import { createDocument } from './fileSystem/createDocument'; -export function activate() { +export function activate(context: vscode.ExtensionContext) { const settingProvider = vscode.workspace.getConfiguration('awesomeTree'); const fileSystemWatcher = vscode.workspace.createFileSystemWatcher('**/*',false, true, true); const outputChannel = vscode.window.createOutputChannel('Awesome tree'); - + + context.subscriptions.push(vscode.commands.registerCommand('extension.saveAsTemplate', saveAsTemplate)); outputChannel.appendLine('Listening for file changes started!'); fileSystemWatcher.onDidCreate(async(createdItemUri: vscode.Uri) => { @@ -120,17 +123,6 @@ export function activate() { } }); - function createDocument(filePath: string, content: string): Promise { - return new Promise((resolve, reject) => { - ensureDirectoryExistence(filePath); - fs.writeFile(filePath, content, {}, async (err) => { - if(err){ - return reject(err); - } - vscode.workspace.openTextDocument(filePath).then(resolve); - }); - }); - } function createGithubIssue(error: Error) { const MAX_CHARACTERS_IN_URI: number = 4000; @@ -193,15 +185,6 @@ export function activate() { }, [] as string[]); } - function ensureDirectoryExistence(filePath:string) { - const dirname = path.dirname(filePath); - if (fs.existsSync(dirname)) { - return true; - } - ensureDirectoryExistence(dirname); - fs.mkdirSync(dirname); - } - function isDirectory(uri: vscode.Uri): boolean { return fs.lstatSync(uri.fsPath).isDirectory(); } diff --git a/src/extenstion.test.ts b/src/extenstion.test.ts index 588601d..7ee265c 100644 --- a/src/extenstion.test.ts +++ b/src/extenstion.test.ts @@ -10,18 +10,24 @@ describe('extenstion', () => { let mockWatcher: { [key in keyof vscode.FileSystemWatcher]?: jest.Mock }; + let mockContext: vscode.ExtensionContext; beforeEach(() => { mockWatcher = { onDidCreate: jest.fn() }; + mockContext = { + subscriptions: { + push: jest.fn() + } + } as any as vscode.ExtensionContext; const createSystemWatcher = vscode.workspace.createFileSystemWatcher as jest.Mock; createSystemWatcher.mockReturnValueOnce(mockWatcher); }); it('should start listen for create file', () => { expect(vscode.workspace.createFileSystemWatcher).not.toHaveBeenCalled(); - activate(); + activate(mockContext); expect(vscode.workspace.createFileSystemWatcher).toHaveBeenCalled(); expect(mockWatcher.onDidCreate).toHaveBeenCalled(); @@ -47,7 +53,7 @@ describe('extenstion', () => { }); }); - activate(); + activate(mockContext); }); }); diff --git a/src/fileSystem/addExtensionToRecommendations.ts b/src/fileSystem/addExtensionToRecommendations.ts new file mode 100644 index 0000000..ef54eab --- /dev/null +++ b/src/fileSystem/addExtensionToRecommendations.ts @@ -0,0 +1,30 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import * as process from 'child_process'; + +export function addExtensionToRecommendations(workspaceDirectory: string){ + try { + const extensionsPath = path.join(workspaceDirectory, '.vscode', 'extensions.json'); + let fileData; + if (fs.existsSync(extensionsPath)) { + fileData = JSON.parse(fs.readFileSync(extensionsPath).toString()); + if (!Array.isArray(fileData.recommendations)) { + fileData.recommendations = []; + } + if (fileData.recommendations.includes('bajdzis.awesome-tree')) { + return; + } + } else { + fileData = { + recommendations: [] + }; + } + fileData.recommendations.push('bajdzis.awesome-tree'); + + fs.writeFileSync(extensionsPath, JSON.stringify(fileData, null, 2)); + + process.spawn('git add ".vscode/extensions.json" -f'); + } catch (error) { + console.log(error); + } +} diff --git a/src/fileSystem/createDocument.ts b/src/fileSystem/createDocument.ts new file mode 100644 index 0000000..102304d --- /dev/null +++ b/src/fileSystem/createDocument.ts @@ -0,0 +1,15 @@ +import * as fs from 'fs'; +import * as vscode from 'vscode'; +import { ensureDirectoryExistence } from './ensureDirectoryExistence'; + +export function createDocument(filePath: string, content: string): Promise { + return new Promise((resolve, reject) => { + ensureDirectoryExistence(filePath); + fs.writeFile(filePath, content, {}, async (err) => { + if(err){ + return reject(err); + } + vscode.workspace.openTextDocument(filePath).then(resolve); + }); + }); +} diff --git a/src/fileSystem/ensureDirectoryExistence.ts b/src/fileSystem/ensureDirectoryExistence.ts new file mode 100644 index 0000000..c252050 --- /dev/null +++ b/src/fileSystem/ensureDirectoryExistence.ts @@ -0,0 +1,11 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +export function ensureDirectoryExistence(filePath:string) { + const dirname = path.dirname(filePath); + if (fs.existsSync(dirname)) { + return true; + } + ensureDirectoryExistence(dirname); + fs.mkdirSync(dirname); +}