|
| 1 | +# Extending the Host Editor |
| 2 | + |
| 3 | +PowerShell Editor Services exposes a common extensibility model which allows |
| 4 | +you to write extension code in PowerShell that works across any editor that |
| 5 | +uses PowerShell Editor Services. |
| 6 | + |
| 7 | +## API Overview |
| 8 | + |
| 9 | +### Introducing `$psEditor` |
| 10 | + |
| 11 | +The entry point for the PowerShell Editor Services extensibility model is the `$psEditor` |
| 12 | +object of the type @Microsoft.PowerShell.EditorServices.Extensions.EditorObject. For |
| 13 | +those familiar with the PowerShell ISE's `$psISE` object, the `$psEditor` object is very |
| 14 | +similar. The primary difference is that this model has been generalized to work against |
| 15 | +any editor which leverages PowerShell Editor Services for its PowerShell editing experience. |
| 16 | + |
| 17 | +> NOTE: For now the `$psEditor` object is limited as it has just been |
| 18 | +> introduced. If you have ideas for other useful APIs it could expose |
| 19 | +> please file an issue on our GitHub page. |
| 20 | +
|
| 21 | +This object gives access to all of the high-level services in the current |
| 22 | +editing session. For example, the @Microsoft.PowerShell.EditorServices.Extensions.EditorObject.Workspace |
| 23 | +property gives access to the editor's workspace, allowing you to create or open files |
| 24 | +in the editor. |
| 25 | + |
| 26 | +### Usage Examples |
| 27 | + |
| 28 | +#### Opening a file in the editor |
| 29 | + |
| 30 | +```powershell |
| 31 | +# Open the current user's profile for this editor |
| 32 | +$psEditor.Workspace.OpenFile($profile) |
| 33 | +``` |
| 34 | + |
| 35 | +#### Manipulating the user's active file buffer |
| 36 | + |
| 37 | +```powershell |
| 38 | +# Insert new text replacing the user's current selection |
| 39 | +$context = $psEditor.GetEditorContext() |
| 40 | +$context.InsertText("# All your script are belong to us", $context.SelectedRange) |
| 41 | +``` |
| 42 | + |
| 43 | +#### Setting the selection based on the cursor position |
| 44 | + |
| 45 | +```powershell |
| 46 | +# Set the selection from their cursor position to the end of the same line |
| 47 | +$context = $psEditor.GetEditorContext() |
| 48 | +$context.SetSelection($context.CursorPosition, $context.CursorPosition.GetLineEnd()) |
| 49 | +``` |
| 50 | + |
| 51 | +## Registering Editor Commands |
| 52 | + |
| 53 | +The `$psEditor` object gives you the ability to write a script that can automate the |
| 54 | +host editor when run inside of it. However, you may not want to give a user a plain |
| 55 | +script that performs some operation. What if you'd prefer to add a new command to the |
| 56 | +editor which can execute your code when the user invokes it? The `Register-EditorCommand` |
| 57 | +cmdlet allows you to register either a function, cmdlet, or ScriptBlock as a |
| 58 | +command in the host editor. |
| 59 | + |
| 60 | +### Registering a cmdlet or function command |
| 61 | + |
| 62 | +```powershell |
| 63 | +function Invoke-MyCommand { |
| 64 | + Write-Output "My command's function was invoked!" |
| 65 | +} |
| 66 | +
|
| 67 | +Register-EditorCommand ` |
| 68 | + -Name "MyModule.MyCommandWithFunction" ` |
| 69 | + -DisplayName "My command with function" ` |
| 70 | + -Function Invoke-MyCommand |
| 71 | +``` |
| 72 | + |
| 73 | +### Registering a script block command |
| 74 | + |
| 75 | +```powershell |
| 76 | +Register-EditorCommand ` |
| 77 | + -Name "MyModule.MyCommandWithScriptBlock" ` |
| 78 | + -DisplayName "My command with script block" ` |
| 79 | + -ScriptBlock { Write-Output "My command's script block was invoked!" } |
| 80 | +``` |
| 81 | + |
| 82 | +### The @Microsoft.PowerShell.EditorServices.Extensions.EditorContext parameter |
| 83 | + |
| 84 | +Your function, cmdlet, or ScriptBlock can optionally accept a single parameter |
| 85 | +of type @Microsoft.PowerShell.EditorServices.Extensions.EditorContext which provides |
| 86 | +information about the state of the host editor at the time your command was |
| 87 | +invoked. With this object you can easily perform operations like manipulatin the |
| 88 | +state of the user's active editor buffer or changing the current selection. |
| 89 | + |
| 90 | +The usual convention is that a `$context` parameter is added to your editor |
| 91 | +command's function. For now it is recommended that you fully specify the |
| 92 | +type of the @Microsoft.PowerShell.EditorServices.Extensions.EditorContext object |
| 93 | +so that you get full IntelliSense on your context parameter. |
| 94 | + |
| 95 | +Here is an example of using the `$context` parameter: |
| 96 | + |
| 97 | +```powershell |
| 98 | +Register-EditorCommand ` |
| 99 | + -Name "MyModule.MyEditorCommandWithContext" ` |
| 100 | + -DisplayName "My command with context usage" ` |
| 101 | + -ScriptBlock { |
| 102 | + param([Microsoft.PowerShell.EditorServices.Extensions.EditorContext]$context) |
| 103 | + Write-Output "The user's cursor is on line $($context.CursorPosition.Line)!" |
| 104 | + } |
| 105 | +``` |
| 106 | + |
| 107 | +### Suppressing command output |
| 108 | + |
| 109 | +If you would like for your editor command to run without its output being |
| 110 | +written to the user's console, you can use the `-SuppressOutput` switch |
| 111 | +parameter of the `Register-EditorCommand` cmdlet. We recommend that you |
| 112 | +use this parameter if your command does not need to write output to the |
| 113 | +user's console. |
| 114 | + |
| 115 | +Regardless of whether the `-SuppressOutput` parameter is used, any errors |
| 116 | +that occur while running your editor command will be written to the user's |
| 117 | +console. |
| 118 | + |
| 119 | +## Using Editor Commands |
| 120 | + |
| 121 | +If you've registered an editor command, either through your own code or |
| 122 | +a module that you've installed, you can launch it using your editor's **Show |
| 123 | +additional commands from PowerShell modules** command. Running this command |
| 124 | +will cause a list of commands to be displayed. |
| 125 | + |
| 126 | +In Visual Studio Code, press `Ctrl+Shift+P` to open the command palette. Type |
| 127 | +the characters `addi` until you see the following item and then press `Enter`: |
| 128 | + |
| 129 | + |
| 130 | + |
| 131 | +The list that appears next will show all of the editor commands that have |
| 132 | +been registered with PowerShell code. Selecting one of them will cause its |
| 133 | +function or ScriptBlock to be executed. |
| 134 | + |
| 135 | + |
| 136 | + |
| 137 | +Other editors should follow a similar pattern, exposing this command list through |
| 138 | +a "Show additional commands" item in the command palette. |
| 139 | + |
| 140 | +> NOTE: In the future we hope to be able to register editor commands at the top level |
| 141 | +> so that these commands are easier to find and so that they also can be bound to |
| 142 | +> hotkeys for quick access. |
| 143 | +
|
| 144 | +## Shipping an Extension Module |
| 145 | + |
| 146 | +You can easily ship a module containing editor commands which get registered |
| 147 | +if the module is loaded into an editor session. Assuming that you've exported |
| 148 | +a function or cmdlet named `Invoke-MyEditorCommand` in your module's psd1 |
| 149 | +file, you can add this code at the very end of your module's psm1 file: |
| 150 | + |
| 151 | +```powershell |
| 152 | +if ($psEditor) { |
| 153 | + Register-EditorCommand ` |
| 154 | + -Name "MyModule.MyEditorCommand" ` |
| 155 | + -DisplayName "My editor command" ` |
| 156 | + -Function Invoke-MyEditorCommand ` |
| 157 | + -SuppressOutput |
| 158 | +} |
| 159 | +``` |
| 160 | + |
| 161 | +The user will now be able to import your module in their host editor's profile and |
| 162 | +your editor command will be immediately available after the PowerShell extension |
| 163 | +in that editor starts up. |
| 164 | + |
| 165 | +> NOTE: In the future we plan to provide an easy way for the user to opt-in |
| 166 | +> to the automatic loading of any editor command modules that they've installed |
| 167 | +> from the PowerShell Gallery. If this interests you, please let us know on |
| 168 | +> [this GitHub issue](https://github.com/PowerShell/PowerShellEditorServices/issues/215). |
0 commit comments