From 6befa7a3b682cd8e0ef58532e34d7cb4c83ce8f1 Mon Sep 17 00:00:00 2001 From: yaegassy Date: Fri, 1 Apr 2022 13:18:27 +0900 Subject: [PATCH 1/2] feat: add composer command integration --- README.md | 10 ++- package.json | 41 +++++++++++ src/commands/composer.ts | 149 +++++++++++++++++++++++++++++++++++++++ src/index.ts | 6 +- 4 files changed, 203 insertions(+), 3 deletions(-) create mode 100644 src/commands/composer.ts diff --git a/README.md b/README.md index 82e3975..6814bbf 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,9 @@ $ node -e "console.log(os.homedir() + '/intelephense/licence.txt')" - `intelephense.client.snippetsCompletionExclude`: Exclude specific prefix in snippet completion, e.g. `["class", "fun"]`, default: `[]` - `intelephense.server.disableCompletion`: Disable completion only (server), default: `false` - `intelephense.server.disableDefinition`: Disable definition only (server), default: `false` +- `intelephense.composer.path`: Path to composer command. default: `composer` +- `intelephense.composer.runCommandList`: Set the subcommand of the composer you want to execute, default: `["dump-autoload", "clear-cache", "install", "update"]` +- `intelephense.composer.runCommandPlusList`: Set the subcommand of the composer you want to execute. Additional strings can be entered and executed in the subcommand. default: `["require", "require --dev", "remove", "remove --dev", "update"]` - `intelephense.phpunit.disableCodeLens`: Disable code lens only (client), default: `false` - `intelephense.phpunit.codeLensTitle`: CodeLens title. Can be changed to any display, default: `">> [Run PHPUnit]"` - `intelephense.phpunit.path`: Path to phpunit command. If there is no setting, the vendor/bin/phpunit will be used, default: `""` @@ -119,11 +122,14 @@ $ node -e "console.log(os.homedir() + '/intelephense/licence.txt')" > :CocCommand [CommandName] > -> **e.g.**: -> :CocCommand intelephense.phpunit.projectTest +> **e.g.** :CocCommand intelephense.phpunit.projectTest - `intelephense.index.workspace`: Index workspace - `intelephense.cancel.indexing`: Cancel indexing +- `intelephense.composer.runCommand`: Run selected composer command +- `intelephense.composer.runCommandPlus`: Enter and run additional strings to the selected composer commands +- `intelephense.composer.runScriptsCommand`: Run selected composer script + - Select and run the script defined in the "scripts section" of `composer.json`. The `pre-...` and `post-...` event scripts are excluded from the list. - `intelephense.phpunit.projectTest`: Run PHPUnit for current project - `intelephense.phpunit.fileTest`: Run PHPUnit for current file - `intelephense.phpunit.singleTest`: Run PHPUnit for single (nearest) test diff --git a/package.json b/package.json index 29c0e62..290faf8 100644 --- a/package.json +++ b/package.json @@ -98,6 +98,32 @@ "default": false, "description": "Disable definition only (server)." }, + "intelephense.composer.path": { + "type": "string", + "default": "composer", + "description": "Path to composer command." + }, + "intelephense.composer.runCommandList": { + "type": "array", + "default": [ + "dump-autoload", + "clear-cache", + "install", + "update" + ], + "description": "Set the subcommand of the composer you want to execute." + }, + "intelephense.composer.runCommandPlusList": { + "type": "array", + "default": [ + "require", + "require --dev", + "remove", + "remove --dev", + "update" + ], + "description": "Set the subcommand of the composer you want to execute. Additional strings can be entered and executed in the subcommand." + }, "intelephense.phpunit.disableCodeLens": { "type": "boolean", "default": false, @@ -819,6 +845,21 @@ "title": "Cancel indexing", "category": "Intelephense" }, + { + "command": "intelephense.composer.runCommand", + "title": "Run selected composer command", + "category": "Intelephense" + }, + { + "command": "intelephense.composer.runCommandPlus", + "title": "Enter and run additional strings to the selected composer command", + "category": "Intelephense" + }, + { + "command": "intelephense.composer.runScriptsCommand", + "title": "Run selected composer script", + "category": "Intelephense" + }, { "command": "intelephense.phpunit.projectTest", "title": "Run PHPUnit for current project", diff --git a/src/commands/composer.ts b/src/commands/composer.ts new file mode 100644 index 0000000..daf2ffc --- /dev/null +++ b/src/commands/composer.ts @@ -0,0 +1,149 @@ +import { Terminal, window, workspace } from 'coc.nvim'; + +import cp from 'child_process'; +import fs from 'fs'; +import path from 'path'; + +let terminal: Terminal | undefined; + +async function getComposerPath() { + let cmdPath = ''; + const composerPath = workspace.getConfiguration('intelephense').get('composer.path', 'composer'); + if (await existsComposer(composerPath)) { + cmdPath = composerPath; + } + return cmdPath; +} + +async function existsComposer(composerPath: string) { + return new Promise((resolve) => { + cp.exec(`${composerPath} --version`, (err, stdout, stderr) => { + if (stdout.length > 0) { + resolve(true); + } else { + resolve(false); + } + }); + }); +} + +function existsComposerJson() { + let exists = false; + const composerJsonPath = path.join(workspace.root, 'composer.json'); + if (fs.existsSync(composerJsonPath)) { + exists = true; + } + return exists; +} + +async function runComposer(composerPath: string, args: string[]) { + if (!composerPath) { + window.showErrorMessage(`composer command not found!`); + return; + } + + if (terminal) { + terminal.dispose(); + terminal = undefined; + } + + terminal = await window.createTerminal({ name: 'composer', cwd: workspace.root }); + terminal.sendText(`${composerPath} ${args.join(' ')}`); + await workspace.nvim.command('stopinsert'); +} + +export function runCommandCommand() { + return async () => { + const composerPath = await getComposerPath(); + const args: string[] = []; + + const runCommandList = workspace.getConfiguration('intelephense').get('composer.runCommandList', []); + + if (runCommandList.length === 0) { + window.showErrorMessage(`runCommandList is empty`); + return; + } + + // Index of selected item, or -1 when canceled. + const choiceNumber = await window.showQuickpick(runCommandList); + + if (choiceNumber !== -1) { + args.push(runCommandList[choiceNumber]); + runComposer(composerPath, args); + } + }; +} + +export function runCommandPlusCommand() { + return async () => { + const composerPath = await getComposerPath(); + const args: string[] = []; + + const runCommandPlusList = workspace + .getConfiguration('intelephense') + .get('composer.runCommandPlusList', []); + + if (runCommandPlusList.length === 0) { + window.showErrorMessage(`runCommandPlusList is empty`); + return; + } + + // Index of selected item, or -1 when canceled. + const choiceNumber = await window.showQuickpick(runCommandPlusList); + + if (choiceNumber !== -1) { + const input = await window.requestInput(`composer ${runCommandPlusList[choiceNumber]}`); + + if (input) { + args.push(runCommandPlusList[choiceNumber]); + args.push(input); + + runComposer(composerPath, args); + } + } + }; +} + +export function runScriptsCommand() { + return async () => { + const composerPath = await getComposerPath(); + const args: string[] = []; + + const existsComposerJsonFile = existsComposerJson(); + + if (!existsComposerJson()) { + window.showErrorMessage(`composer.json not found!`); + return; + } + + const composerJson = JSON.parse(fs.readFileSync(path.join(workspace.root, 'composer.json'), 'utf8')); + + let scriptsList: string[] = []; + + Object.keys(composerJson).map((key) => { + if (key === 'scripts') { + const scriptsObj = composerJson[key]; + Object.keys(scriptsObj).map((key) => { + if (!key.startsWith('pre-') && !key.startsWith('post-')) { + scriptsList.push(key); + } + }); + } + }); + + if (scriptsList.length >= 1) { + // Index of selected item, or -1 when canceled. + const choiceNumber = await window.showQuickpick(scriptsList); + + if (choiceNumber !== -1) { + args.push('run-script'); + args.push(scriptsList[choiceNumber]); + + runComposer(composerPath, args); + } + } else { + window.showWarningMessage(`scripts not found. events (pre-, post-) are excluded by default`); + return; + } + }; +} diff --git a/src/index.ts b/src/index.ts index ff961eb..999e1d2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,6 +23,7 @@ import { existsSync } from 'fs'; import { IntelephenseSnippetsCompletionProvider } from './completion/IntelephenseSnippetsCompletion'; import { IntelephenseCodeActionProvider } from './actions'; import { IntelephenseCodeLensProvider } from './lenses'; +import { runCommandCommand, runCommandPlusCommand, runScriptsCommand } from './commands/composer'; import { fileTestCommand, singleTestCommand, projectTestCommand } from './commands/phpunit'; const PHP_LANGUAGE_ID = 'php'; @@ -98,7 +99,10 @@ export async function activate(context: ExtensionContext): Promise { context.subscriptions.push( commands.registerCommand('intelephense.phpunit.projectTest', projectTestCommand()), commands.registerCommand('intelephense.phpunit.fileTest', fileTestCommand()), - commands.registerCommand('intelephense.phpunit.singleTest', singleTestCommand()) + commands.registerCommand('intelephense.phpunit.singleTest', singleTestCommand()), + commands.registerCommand('intelephense.composer.runCommand', runCommandCommand()), + commands.registerCommand('intelephense.composer.runCommandPlus', runCommandPlusCommand()), + commands.registerCommand('intelephense.composer.runScriptsCommand', runScriptsCommand()) ); // Add code lens by "client" side From 3171c35df7f3ba933befd2e87e59ee3603d8a9a9 Mon Sep 17 00:00:00 2001 From: yaegassy Date: Fri, 1 Apr 2022 13:53:15 +0900 Subject: [PATCH 2/2] refactor: delete the target terminal buffer just in case --- src/commands/composer.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/commands/composer.ts b/src/commands/composer.ts index daf2ffc..a6e2981 100644 --- a/src/commands/composer.ts +++ b/src/commands/composer.ts @@ -43,6 +43,9 @@ async function runComposer(composerPath: string, args: string[]) { } if (terminal) { + if (terminal.bufnr) { + await workspace.nvim.command(`bd! ${terminal.bufnr}`); + } terminal.dispose(); terminal = undefined; }