From cb59d497a15497116d6cfa6350bacbd95baeaa58 Mon Sep 17 00:00:00 2001 From: hakutaku <39969709+allhaileris@users.noreply.github.com> Date: Sun, 23 Mar 2025 01:46:43 +0300 Subject: [PATCH] wip --- package.json | 9 ++-- src/extension.ts | 101 ++++++++++++++++++++++++++++++++------- templates/CMakeLists.txt | 24 ++++++++++ 3 files changed, 113 insertions(+), 21 deletions(-) create mode 100644 templates/CMakeLists.txt diff --git a/package.json b/package.json index a582944..4b975c5 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,8 @@ "contributes": { "commands": [ { - "command": "hakutaku.initSymfonyFlexRepo", - "title": "New Objective-C class..." + "command": "hakutaku.objc.initCmake", + "title": "New CMake project..." }, { "command": "hakutaku.initSymfonyFlexRepo", @@ -32,12 +32,13 @@ "explorer/context": [ { "submenu": "sparkup.submenu", - "group": "navigation" + "group": "navigation", + "when": "explorerResourceIsFolder" } ], "sparkup.submenu": [ { - "command": "hakutaku.initSymfonyFlexRepo" + "command": "hakutaku.objc.initCmake" }, { "command": "hakutaku.initSymfonyFlexRepo" diff --git a/src/extension.ts b/src/extension.ts index 72cb53a..f27db8c 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -2,6 +2,35 @@ import * as vscode from 'vscode'; import * as fs from 'fs'; import * as path from 'path'; +/** + * + * @param uri + * @returns + */ +function isRootFolder(uri: vscode.Uri): boolean { + const workspaceFolders = vscode.workspace.workspaceFolders; + const workspaceFsPaths = workspaceFolders?.map((folder: vscode.WorkspaceFolder) => folder.uri.fsPath); + + if (!workspaceFsPaths?.includes(uri.fsPath)) { + return false; + } + + return true; +} + +/** + * + * @param dirPath + * @returns + */ +function isDirectoryExists(dirPath: string): boolean { + try { + return fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory(); + } catch (err: unknown) { + return false; + } +} + // Функция для преобразования в PascalCase const toPascalCase = (input: string): string => { return input @@ -11,8 +40,8 @@ const toPascalCase = (input: string): string => { const toCamelCase = (input: string): string => { return input - .trim() - .replace(/[^a-zA-Z0-9]+(.)?/g, (_, char) => (char ? char.toUpperCase() : '')) + .trim() + .replace(/[^a-zA-Z0-9]+(.)?/g, (_, char) => (char ? char.toUpperCase() : '')) .replace(/^(.)/, (match) => match.toLowerCase()); }; @@ -40,11 +69,11 @@ function getBundlePaths(uri: vscode.Uri, userInput: string): [vendorPath: string } function prepareBundlePaths(vendorPath: string, bundlePath: string): true { - if (!directoryExists(vendorPath)) { + if (!isDirectoryExists(vendorPath)) { fs.mkdirSync(vendorPath); } - if (directoryExists(bundlePath)) { + if (isDirectoryExists(bundlePath)) { throw new Error('Already exists'); } @@ -53,23 +82,59 @@ function prepareBundlePaths(vendorPath: string, bundlePath: string): true { return true; } -/** - * - * @param dirPath - * @returns - */ -function directoryExists(dirPath: string): boolean { - try { - return fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory(); - } catch (err: unknown) { - return false; - } -} // This method is called when your extension is activated // Your extension is activated the very first time the command is executed export function activate(context: vscode.ExtensionContext) { + const initNewCmakeProject: vscode.Disposable = vscode + .commands + .registerCommand('hakutaku.objc.initCmake', async ( + uri: vscode.Uri, + ): Promise => { + try { + if (!isRootFolder(uri)) { + throw new Error('Инициализация нового проекта доступна только в корневой директории'); + } + + const userInput: string | undefined = await + vscode.window.showInputBox({ + prompt: 'Название проекта', + placeHolder: 'acme-foo-project' + }); + + if (userInput) { + const templatePath = path.join( + context.extensionPath, 'templates', 'CMakeLists.txt' + ); + + fs.readFile(templatePath, 'utf8', (err, templateContent) => { + if (err) { + throw new Error(`Ошибка при чтении шаблона: ${err.message}`); + } + + const filePath = path.join(uri.fsPath, 'CMakeLists.txt'); + + // Заменяем плейсхолдеры в шаблоне (если есть) + let finalContent = templateContent.replace( + '${NAME}', userInput + ); + + // Создаем файл и записываем в него шаблон + fs.writeFile(filePath, finalContent, (err) => { + if (err) { + throw new Error(`Ошибка при создании файла: ${err.message}`); + } + }); + }); + } + } catch (error: unknown) { + if (error instanceof Error) { + vscode.window.showErrorMessage(error.message); + } + } + }); + const initSymfonyFlexRepo: vscode.Disposable = vscode.commands.registerCommand('hakutaku.initSymfonyFlexRepo', async (uri: vscode.Uri): Promise => { // Проверка на наличие директории "recipes" и flex.lock файла try { @@ -102,7 +167,7 @@ export function activate(context: vscode.ExtensionContext) { const [vendorPath, bundlePath] = getBundlePaths(uri, userInput); if (prepareBundlePaths(vendorPath, bundlePath)) { - + } @@ -145,6 +210,8 @@ export function activate(context: vscode.ExtensionContext) { }); + context.subscriptions.push(initNewCmakeProject); + context.subscriptions.push(initSymfonyFlexRepo); context.subscriptions.push(disposable); } diff --git a/templates/CMakeLists.txt b/templates/CMakeLists.txt new file mode 100644 index 0000000..4b544eb --- /dev/null +++ b/templates/CMakeLists.txt @@ -0,0 +1,24 @@ +project(${NAME}) + +cmake_minimum_required(VERSION 3.16) +set(GNUSTEP gnustep-config) + +IF (UNIX AND NOT APPLE) + find_package(PkgConfig REQUIRED) + + SET(CMAKE_C_COMPILER gcc) + SET(CMAKE_CXX_COMPILER gcc) + SET(GNUSTEP gnustep-config) + + execute_process(COMMAND ${GNUSTEP} --objc-flags + OUTPUT_VARIABLE GNUSTEP_FLAGS + OUTPUT_STRIP_TRAILING_WHITESPACE) + separate_arguments(GNUSTEP_FLAGS UNIX_COMMAND ${GNUSTEP_FLAGS}) + + execute_process(COMMAND ${GNUSTEP} --base-libs + OUTPUT_VARIABLE GNUSTEP_LIBS + OUTPUT_STRIP_TRAILING_WHITESPACE) + +ELSEIF (APPLE) + SET(CMAKE_EXE_LINKER_FLAGS "-framework Cocoa") +ENDIF ()