diff --git a/news/1 Enhancements/18514.md b/news/1 Enhancements/18514.md new file mode 100644 index 000000000000..46c1467ca9a9 --- /dev/null +++ b/news/1 Enhancements/18514.md @@ -0,0 +1 @@ +Supported the extract method command. (Thanks [Harry-Hopkinson](https://github.com/Harry-Hopkinson)) diff --git a/package.json b/package.json index fea002930776..cc90889ed361 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "onCommand:python.setShebangInterpreter", "onCommand:python.viewLanguageServerOutput", "onCommand:python.viewOutput", + "onCommand:python.extractMethod", "onCommand:python.execSelectionInTerminal", "onCommand:python.execSelectionInDjangoShell", "onCommand:python.startREPL", @@ -487,6 +488,11 @@ "light": "resources/light/repl.svg" }, "title": "%python.command.python.viewOutput.title%" + }, + { + "category": "Python", + "command": "python.extractMethod", + "title": "Extract Method" } ], "configuration": { @@ -1810,6 +1816,12 @@ "command": "python.viewOutput", "title": "%python.command.python.viewOutput.title%", "when": "!virtualWorkspace && shellExecutionSupported" + }, + { + "category": "Python", + "command": "python.extractMethod", + "title": "Extract Method", + "when": "!virtualWorkspace && shellExecutionSupported" } ], "editor/context": [ diff --git a/sprint-planning.github-issues b/sprint-planning.github-issues old mode 100755 new mode 100644 diff --git a/src/client/common/application/commands.ts b/src/client/common/application/commands.ts index eb4e827d42bb..4060acfe3f12 100644 --- a/src/client/common/application/commands.ts +++ b/src/client/common/application/commands.ts @@ -33,6 +33,7 @@ interface ICommandNameWithoutArgumentTypeMapping { ['editor.action.formatDocument']: []; ['editor.action.rename']: []; [Commands.ViewOutput]: []; + [Commands.ExtractMethod]: []; [Commands.Set_Linter]: []; [Commands.Start_REPL]: []; [Commands.Enable_SourceMap_Support]: []; diff --git a/src/client/common/constants.ts b/src/client/common/constants.ts index 6cd283daab99..9ca8df8de058 100644 --- a/src/client/common/constants.ts +++ b/src/client/common/constants.ts @@ -47,6 +47,7 @@ export namespace Commands { export const Test_Stop_Refreshing = 'python.stopRefreshingTests'; export const Sort_Imports = 'python.sortImports'; export const ViewOutput = 'python.viewOutput'; + export const ExtractMethod = 'python.extractMethod'; export const Start_REPL = 'python.startREPL'; export const Create_Terminal = 'python.createTerminal'; export const Set_Linter = 'python.setLinter'; diff --git a/src/client/extensionActivation.ts b/src/client/extensionActivation.ts index 74b6cc066c7b..cc2cca2fb6b2 100644 --- a/src/client/extensionActivation.ts +++ b/src/client/extensionActivation.ts @@ -3,13 +3,27 @@ 'use strict'; -import { CodeActionKind, debug, DebugConfigurationProvider, languages, OutputChannel, window } from 'vscode'; +import { + CodeActionKind, + debug, + DebugConfigurationProvider, + languages, + OutputChannel, + window, + workspace, + WorkspaceEdit, +} from 'vscode'; import { registerTypes as activationRegisterTypes } from './activation/serviceRegistry'; import { IExtensionActivationManager } from './activation/types'; import { registerTypes as appRegisterTypes } from './application/serviceRegistry'; import { IApplicationDiagnostics } from './application/types'; -import { IApplicationEnvironment, ICommandManager, IWorkspaceService } from './common/application/types'; +import { + IApplicationEnvironment, + IApplicationShell, + ICommandManager, + IWorkspaceService, +} from './common/application/types'; import { Commands, PYTHON, PYTHON_LANGUAGE, STANDARD_OUTPUT_CHANNEL, UseProposedApi } from './common/constants'; import { registerTypes as installerRegisterTypes } from './common/installer/serviceRegistry'; import { IFileSystem } from './common/platform/types'; @@ -150,6 +164,68 @@ async function activateLegacy(ext: ExtensionState): Promise { disposables.push(cmdManager.registerCommand(Commands.ViewOutput, () => outputChannel.show())); cmdManager.executeCommand('setContext', 'python.vscode.channel', applicationEnv.channel).then(noop, noop); + disposables.push( + cmdManager.registerCommand(Commands.ExtractMethod, async () => { + const editor = window.activeTextEditor; + const shell: IApplicationShell = serviceManager.get(IApplicationShell); + if (editor) { + if (editor.selection.isEmpty) { + return shell.showErrorMessage('Please Select Text before Extracting a Method'); + } + if (editor.selection.start.line === editor.selection.end.line) { + const { selection } = editor; + const { document } = editor; + const text = document.getText(selection); + const position = selection.start; + const edit = new WorkspaceEdit(); + const methodName = await window.showInputBox({ prompt: 'Enter Method Name' }); + if (methodName) { + const newText = `def ${methodName}():\n\t${text}`; + edit.delete(document.uri, selection); + edit.insert(document.uri, position, newText); + await workspace.applyEdit(edit); + } else { + return shell.showErrorMessage('Method Name is Required'); + } + } else if (editor.selection.start.line !== editor.selection.end.line) { + const { selection } = editor; + const { document } = editor; + let text = document.getText(selection); + const position = selection.start; + const edit = new WorkspaceEdit(); + const methodName = await window.showInputBox({ prompt: 'Enter Method Name' }); + if (methodName) { + if (selection.start.line !== selection.end.line) { + if (selection.start.character === 0) { + text = text.replace(/\n/g, '\n\t'); + text = `def ${methodName}():\n\t${text}`; + edit.delete(document.uri, selection); + edit.insert(document.uri, position, text); + await workspace.applyEdit(edit); + } else { + text = text.replace(/^\s+/, ''); + const newText = `def ${methodName}():\n\t${text}`; + edit.delete(document.uri, selection); + edit.insert(document.uri, position, newText); + await workspace.applyEdit(edit); + } + } else { + const newText = `def ${methodName}():\n\t${text}`; + edit.delete(document.uri, selection); + edit.insert(document.uri, position, newText); + await workspace.applyEdit(edit); + } + } else { + return shell.showErrorMessage('Method Name is Required'); + } + } + } else { + return shell.showErrorMessage('Open an Active Editor before Extracting a Method'); + } + return Promise.resolve(); + }), + ); + serviceContainer.get(IApplicationDiagnostics).register(); serviceManager.get(ITerminalAutoActivation).register();