|
| 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 | +**TODO** |
| 31 | + |
| 32 | +#### Manipulating the user's active file buffer |
| 33 | + |
| 34 | +**TODO** |
| 35 | + |
| 36 | +#### Setting the selection based on the cursor position |
| 37 | + |
| 38 | +**TODO** |
| 39 | + |
| 40 | + |
| 41 | +The `$psEditor` object gives you the ability to write a script that can automate the |
| 42 | +host editor when run inside of it. However, you may not want to give a user a plan |
| 43 | +script to run to perform some operation. |
| 44 | +within the host editor, automate operations in the editor. What if you'd like to |
| 45 | + |
| 46 | +## Registering Editor Commands |
| 47 | + |
| 48 | +It might be helpful to register a command with the editor so that your extension |
| 49 | +functionality is easily accessible to the user. The `Register-EditorCommand` |
| 50 | +cmdlet can be used to register either a function, cmdlet, or ScriptBlock as a |
| 51 | +command in the host editor. |
| 52 | + |
| 53 | +### Registering a cmdlet or function command |
| 54 | + |
| 55 | +```powershell |
| 56 | +function Invoke-MyCommand { |
| 57 | + Write-Output "My extension function was invoked!" |
| 58 | +} |
| 59 | +
|
| 60 | +Register-EditorCommand ` |
| 61 | + -Name "MyExt.MyExtensionFunction" ` |
| 62 | + -DisplayName "My extension function" ` |
| 63 | + -Function MyExtensionFunction |
| 64 | +``` |
| 65 | + |
| 66 | +### Registering a script block command |
| 67 | + |
| 68 | +```powershell |
| 69 | +Register-EditorCommand ` |
| 70 | + -Name "MyExt.MyExtensionScriptBlock" ` |
| 71 | + -DisplayName "My extension script block" ` |
| 72 | + -ScriptBlock { Write-Output "My extension script block was invoked!" } |
| 73 | +``` |
| 74 | + |
| 75 | +### The @Microsoft.PowerShell.EditorServices.Extensions.EditorContext parameter |
| 76 | + |
| 77 | +Your function, cmdlet, or ScriptBlock can optionally accept a single parameter |
| 78 | +of type @Microsoft.PowerShell.EditorServices.Extensions.EditorContext which provides |
| 79 | +information about the state of the host editor at the time your command was |
| 80 | +invoked. With this object you can easily perform operations like manipulatin the |
| 81 | +state of the user's active editor buffer or changing the current selection. |
| 82 | + |
| 83 | +The usual convention is that a `$context` parameter is added to your editor |
| 84 | +command's function. For now it is recommended that you fully specify the |
| 85 | +type of the @Microsoft.PowerShell.EditorServices.Extensions.EditorContext object |
| 86 | +so that you get full IntelliSense on your context parameter. |
| 87 | + |
| 88 | +Here is an example of using the `$context` parameter: |
| 89 | + |
| 90 | +```powershell |
| 91 | +Register-EditorCommand ` |
| 92 | + -Name "MyExt.MyExtensionScriptBlockWithContext" ` |
| 93 | + -DisplayName "My extension script block with context" ` |
| 94 | + -ScriptBlock { |
| 95 | + param([Microsoft.PowerShell.EditorServices.Extensions.EditorContext]$context) |
| 96 | + Write-Output "The user's cursor is on line $($context.CursorPosition.Line)!" |
| 97 | + } |
| 98 | +``` |
| 99 | + |
| 100 | +### Suppressing command output |
| 101 | + |
| 102 | +If you would like for your editor command to run without its output being |
| 103 | +written to the user's console, you can use the `-SuppressOutput` switch |
| 104 | +parameter of the `Register-EditorCommand` cmdlet. We recommend that you |
| 105 | +use this parameter if your command does not need to write output to the |
| 106 | +user's console. |
| 107 | + |
| 108 | +Regardless of whether the `-SuppressOutput` parameter is used, any errors |
| 109 | +that occur while running your editor command will be written to the user's |
| 110 | +console. |
| 111 | + |
| 112 | +## Using Editor Commands |
| 113 | + |
| 114 | +If you've registered an editor command, either through your own code or |
| 115 | +a module that you've installed, you can launch it using your editor's **Show |
| 116 | +additional commands from PowerShell modules** command. Running this command |
| 117 | +will cause a list of commands to be displayed. Here's an example of how this |
| 118 | +looks in Visual Studio Code: |
| 119 | + |
| 120 | +**TODO TODO TODO** |
| 121 | + |
| 122 | +> NOTE: In the future we hope to be able to register editor commands at the top level |
| 123 | +> so that these commands are easier to find and so that they also can be bound to |
| 124 | +> hotkeys for quick access. |
| 125 | +
|
| 126 | +## Shipping an Extension Module |
| 127 | + |
| 128 | +You can easily ship a module containing editor commands which get registered |
| 129 | +if the module is loaded into an editor session. Assuming that you've exported |
| 130 | +a function or cmdlet named `Invoke-MyExtensionCommand` in your module's psd1 |
| 131 | +file, you can add this code at the very end of your module's psm1 file: |
| 132 | + |
| 133 | +```powershell |
| 134 | +if ($psEditor) { |
| 135 | + Register-EditorCommand ` |
| 136 | + -Name "MyModule.MyExtensionCommand" ` |
| 137 | + -DisplayName "My extension command" ` |
| 138 | + -Function Invoke-MyExtensionCommand ` |
| 139 | + -SuppressOutput |
| 140 | +} |
| 141 | +``` |
| 142 | + |
| 143 | +The user will now be able to import your module in their host editor's profile and |
| 144 | +your editor command will be immediately available after the PowerShell extension |
| 145 | +in that editor starts up. |
| 146 | + |
| 147 | +> NOTE: In the future we plan to provide an easy way for the user to opt-in |
| 148 | +> to the automatic loading of any editor command modules that they've installed |
| 149 | +> from the PowerShell Gallery. If this interests you, please let us know on |
| 150 | +> [this GitHub issue](https://github.com/PowerShell/PowerShellEditorServices/issues/215). |
0 commit comments