-
Notifications
You must be signed in to change notification settings - Fork 234
Introduce editor command extensibility model #81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Great idea! Nothing adds more to an editor environment than full programmability. I would strongly support this suggestion and would contribute enthusiastically :-) One of the major omissions, in my opinion, from Windows systems is a proper programmable editor. There are some good editors about, and some ports of other well-known editor from other operating systems (VIM et al), but native Windows editors all lack programmability – which is a real shame – and something this proposal could address in the VSCode editor. C# is good. PowerShell would be much better. ISE includes an object model (in the $PsISE variable) – but is very limited in terms of actually controlling the editor. IseSteroids has some very basic programmability but this is limited to some very specific use cases and is far from being a general purpose facility. Adding programmability to VsCode would ideally allow arbitrary scripts/macros to operate on the editor or its contents. While I agree that Action/Analyzer/Formatter type operations are a good start I would hope that the interface would be entirely general (i.e. having specific cmdlets for these particular operations may be inherently limiting?) I’d strongly suggest you spend a while looking at what’s gone before – as this illustrates what can be achieved. Here are a few thoughts: Emacs and Vi are macro editors – in the sense that a scripting language can be seamlessly used to control not only the content of the file being edited, but also the appearance and operation of the editor itself. It’s been many, many years since I was competent with Vi (and I never learned much Emacs), so I won’t dwell on these… Xedit was the IBM VM/CMS editor (and, I believe is still the system editor on z/VM). This editor is programmable with Rexx (scripting language). The editor exposes almost all its internal state to the Rexx interface (see references/links below). Xedit spawned many third-party clones – for example, Kedit (www.kedit.com) for PCs. On the Amiga (age alert!) there was a great editor called CygnusEd (http://www.vesalia.de/e_cygnused.htm) that was programmable via Rexx (in this case ARexx) in the same way. There’s an open-source Windows version of Xedit/Kedit, called THE (http://hessling-editor.sourceforge.net/) with a lot of documentation that gives a good idea of what’s possible (http://hessling-editor.sourceforge.net/doc/index.html). Although this stuff is old it still illustrates the benefits that programmability can offer. Publishing macros on the PS Gallery is another great idea. A similar old-fashioned resource is available for THE here: http://www.gut-wirtz.de/THE/contrib/index.html. Some good example macros/scripts (in Rexx) would be: Let me know if I can help or if you’d like more musings! Regards, |
Thanks for the great feedback Chris! I am a long time Vim and Emacs user so I definitely understand the value of full programmability :) The current proposal only addresses the types of extensibility that are fairly easy to provide across different editors. My ultimate goal is to provide a more robust automation model. The next phase would be providing more cmdlets that will allow you to automate tasks in the editor, much like what you're suggesting here. One obvious feature would be enumerating and executing the editor's own commands. Another would be manipulating the open buffers and frames in the editor's window. Some automation points may only be available in certain editors, so I was going to provide some form of "capabilities" model where certain parts of the API were turned on/off based on what the user's editor provides. Are there particular automation points in the editors that youv'e used which have been particularly helpful? |
I don't think how the module ships matters to Pester testing (except in the sense that the module will be harder to find if it's in a random location). If I install PSES in multiple editors, do I end up with multiple copies (potentially at different versions, depending on the maintainer)? That would indicate you need to keep the module with the library.
I'm not sure this matters very much. It's unlikely people will write extensions for PSES that are valuable in other languages (I think), since all of the editors you're tackling are inherently extensible already, so I wouldn't worry about that aspect. The only real downside of having it run in the language host would be polluting the name/variable space there during development, or crashing the whole thing...
How is this question different than the previous? Are you contemplating running analyzer extensions separate from others because they'll potentially run in "real time"? Would you spin up a runspace for each analyzer plugin?
Currently supporting 3-5 isn't too hard. It just means that you have to work at the v3 language level. I wouldn't worry about this -- document that the core works to v3, and suggest extensions should too, you can't force the issue. However, it's completely impossible to test backwards compatibility without a v3 machine, since there's no
There are still lots of things C# can do that PowerShell can't, and still more that are incredibly hard or complex to do in PowerShell (especially in a way that's backwards compatible to v3). Threading, events, classes, generic methods ... |
It matters if an extension author wants to be able to run tests on a CI server without installing one of the editors and its PowerShell extension. Though I don't know how many people would end up writing CI tests for their interface to the extension API itself. Maybe this doesn't matter so much until people start asking about it.
That's true, different editor integrations could be using different versions of PSES. I believe PSGallery can install multiple versions of the same module though, so shipping from the Gallery could still be an option in this case.
For the first point, I agree when it comes to the currently proposed extensibility types. However, the PowerShell-based extensibility model becomes more generally useful when I add more commands for automating things inside of the host editor. I'm not exactly sure what this entails yet, but I'm trying to plan ahead a bit incase we can do more cool stuff. The second point is one of the reasons why I'm considering having a separate host. The extensions shouldn't affect the name/variable space of the user's session. I'm also trying to make sure that the editor experience stays quick for things like IntelliSense so keeping extension commands and analyzers in a separate runspace (at least) should allow the mainline features to continue to run smoothly.
Agreed.
Yep, I'm going to set up v3/v4 build servers at some point :)
I'm leaning more toward writing the core extension API code as C# cmdlets to make it easier for the extension service to hook into it. Thanks for the feedback! |
This was shipped in the recent 0.6.0 with some modifications from the original design discussed here. For more information check out the documentation page: http://powershell.github.io/PowerShellEditorServices/guide/extensions.html |
…l-snippets More work on issue PowerShell#63, snippet improvements.
I would like to enable PowerShell modules to provide new commands and behaviors
to any editor that uses PowerShell Editor Services. Instead of learning how to
write an extension for a specific editor, a user should be able to use a simple,
PowerShell-based API to implement their desired feature once and have it be
available anywhere Editor Services is used.
I thought it might be nice to gather some feedback on my current thinking before
I get too deep into the implementation. Please let me know if I'm on the right
track here and feel free to suggest any other ideas you may have. I'll be updating
the text of this issue to capture any ideas or feedback given in the comments
section below.
Overall Design
Extensions will be written either in PowerShell code or as binary modules in
C#. These extensions could even come from simple one-liner code in the
user's profile or be written on the fly in the editor's REPL. The model
should allow extensions to be developed in real-time, easily being
re-registered when the user evaluates their extension code in the editor.
Extensions will be hosted by an "extension service" (similar to the language
and debugging services). For now it is assumed that the extension service
will have its own local runspace which will not follow the session changes
in the user's REPL runspace. This means that all extension commands would
run locally, but in some cases may be able to affect the user's current
session whether it is local or remote.
Generally, extension modules will be installed via the PowerShell Gallery.
If we decide to make the PowerShellEditorServices module installable via
the Gallery this would allow extension modules to take a dependency on the
version of the PowerShellEditorServices module that they support.
In our editor integrations, we will provide commands which will make it easy
to locate and install editor extensions and enable them for use immediately.
Command Types
Here's the proposed list of extension command types. Please feel free to
suggest more!
Action
An Action command represents some operation that can be executed in the user's
local PowerShell session. This would most commonly be some kind of script
that the user has created to boost their productivity or automate some process.
Exposing this type of action as a command could allow the user to bind the action
to a hotkey in their editor for quick execution.
Actions may also need access to the current runspace of the user's REPL session
so that commands can be executed there. There would need to be some way for
the command to choose to execute its action locally or inside of the user's
current session. More use case ideas would be helpful here.
Actions will be registered as individual commands with the editor so that
the user can bind them to hotkeys and launch them on demand.
Analyzer
An Analyzer command provides a function or ScriptBlock which can be invoked to
analyze a ScriptAst and return diagnostic markers that will be displayed in
the user's editor. These diagnostics can also provide "quick fix" actions which
may cause the code to be changed or to run operations in the user's current session.
One obvious use case is PowerShell Script Analyzer. Currently we are bundling
Script Analyzer with PowerShell Editor Services but I'd like to move away from
this. Using the the user's installed Script Analyzer module will allow the them
to freely update Script Analyzer outside of the Editor Services ship cycle. It
would also simplify the direct dependencies and deployment of PowerShell Editor
Services and its various editor integrations.
Another use case would be custom script analysis which doesn't fall under the
umbrella of Script Analyzer. One could write an analyzer extension which identifies
cmdlets that exist in PS Gallery modules that are not yet installed and give the user
a quick fix action to install the necessary modules.
The process of applying registered analyzers will be as follows:
aggregating the returned markers into a single list.
cancel the current analyzer run and start the delay for a new one.
Formatter
A Formatter command provides a function or ScriptBlock that can be invoked to
reformat or insert new text into the user's script file. This could be used
for general code style formatting tools or for operations like Doug's "Expand
Aliases" command which is currently shipped as a built-in action.
One use case I can think of here would be to provide smarter snippets. For
example, an extension could provide a "create cmdlet help" formatter which
analyzes the cmdlet's AST and generates a help comment which includes all of
the parameters and a good starting point for the documentation for each.
Formatters will be registered as individual commands with the editor so that
the user can bind them to hotkeys and launch them on demand.
Extension API
Register-EditorCommand
This command allows an extension to register itself so that it can be made
available to the user in their editor. There will be a unique paramset for
each command type which will expose the necessary configuration parameters
for that type.
Here are the currently proposed signatures:
Action
The
-Action
parameter will accept a command, function, or ScriptBlock whichaccepts the user's current Runspace. Other contextual information may need
to be provided as parameters, would love feedback on what might be useful.
Analyzer
The
-Analyzer
parameter will accept a command, function, or ScriptBlock whichaccepts the file path and ScriptAst of the currently edited file. The command
should return a list of diagnostic objects with the following information:
The
-RunAutomatically
parameter denotes whether the analyzer should be runautomatically when the user changes a file or if it should be invoked manually
by the user. Is this helpful, or should we just simplify it and have every
analyzer be run automatically?
Formatter
The
-Formatter
parameter will accept a command, function, or ScriptBlock whichaccepts the file path and ScriptAst of the currently edited file and also an
object that contains the coordinates of the user's selection range in the file
if applicable. The Formatter would then process the ScriptAst and return a
new ScriptAst after the formatting changes have been applied. We may also
allow a string to be returned.
Get-EditorCommand
Enumerates registered editor commands. Used primarily by the extension service
to get the list of registered commands after the user's profile has been loaded.
Extension Lifecycle
PowerShellEditorServices
module (which contains the API cmdlets) into thelocal runspace.
extension modules. (We may want to have an editor-specific profile for this case)
the
Register-EditorCommand
method.Get-EditorCommand
to get the list of registered commands.
list of extension commands and then make them available to the user.
Register-EditorCommand
command is invoked, these new extension commands willbe loaded and a notification will be sent through Editor Services back to the
editor to make the new command available to the user.
Questions for Feedback
a module installed via the gallery? The former open simplifies distribution and
ensures that the right module version will be used. However, the latter provides
the opportunity for editor extension authors to write Pester tests for their
extension against the real module API. Would love some feedback on this issue.
a separate instance of the host process that is focused purely on extensions? The
former approach would be the most straightforward but the latter would allow general
extensibility of the user's editor through PowerShell. However, in the latter case
we would only make Action commands available in non-PowerShell files since we don't
have ScriptAst types for other languages. Thoughts?
but require support for v4 and v5 as well? I would like for Editor Services to work
on machines that only have v3 or v4 so this requires that extensions either be
version-specific or version-independent.
in pure PowerShell code (or vide versa)? One potential benefit of a C#-based module
is that there might be a way to expose events to the extension service so that it
can be notified when new commands are registered.
that a greedy analyzer will cause other extension commands to stop executing.
/cc @dfinke @adamdriscoll @Jaykul @rkeithhill
The text was updated successfully, but these errors were encountered: