Compare commits
4 Commits
dev/lhecke
...
dev/migrie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c774d75e5 | ||
|
|
d6f053c828 | ||
|
|
c468ebb603 | ||
|
|
135e20f742 |
319
doc/specs/NorthStar/Markdown Notebooks.md
Normal file
@@ -0,0 +1,319 @@
|
||||
---
|
||||
author: Mike Griese @zadjii-msft
|
||||
created on: 2022-05-18
|
||||
last updated: 2022-10-28
|
||||
issue id: n/a
|
||||
---
|
||||
|
||||
# Markdown Notebooks in the Terminal
|
||||
|
||||
> Note:
|
||||
>
|
||||
> This is a draft document. It's mainly ideating on a novel way of interacting
|
||||
> with the Terminal. There's still a long gap between this and real shipping
|
||||
> code, however.
|
||||
>
|
||||
> It is included with the remainder of my North Star docs, because it was always
|
||||
> a part of that story. As we iterate on this protocol, we'll revise this doc
|
||||
> with the final protocol.
|
||||
|
||||
## Abstract
|
||||
|
||||
"Terminal Notebooks" would allow developers to combine documentation and code in
|
||||
a single file. Blocks of commands could be grouped logically together with their
|
||||
output, for a more semantic experience. By leveraging markdown as a format, we
|
||||
can expand upon an broad ecosystem of pre-existing content developers are
|
||||
already familiar with.
|
||||
|
||||
## Background
|
||||
|
||||
Notebooks have risen to popularity in recent years as a way of combining both
|
||||
code and documentation in a single experience. They enable users to seamlessly
|
||||
write code, and execute it to see the output, write documentation on the code,
|
||||
and share that with others. However, there's not really anything like notebooks
|
||||
for generic commandline experiences.
|
||||
|
||||
There are, however, markdown files. Markdown has become a bit of a lingua franca
|
||||
of the developer experience. It's used prominently on GitHub - the "homepage" of
|
||||
any repo on GitHub is now typically a markdown file. This file will have all
|
||||
sorts of documentation, and notably these READMEs are often filled with commands
|
||||
that one can execute for this project. Downloading, installing its dependencies,
|
||||
building and running the project, etc, all commands that are already listed
|
||||
today in READMEs across the world.
|
||||
|
||||
It would be a major convenience for users to be able to just load a pre-rendered
|
||||
markdown file directly into their terminal windows. These files already include
|
||||
marked blocks of code which identify sets of commands for the command line. It
|
||||
should be as simple as clicking a button to run these commands in the Terminal,
|
||||
or even to run a whole file worth of commands automatically.
|
||||
|
||||
### Inspiration
|
||||
|
||||
[Jupyter notebooks] ([a Jupyter example]) served as the primary inspiration for
|
||||
this feature. Another shoutout to [this comment on HackerNews], which inspired a
|
||||
lot of brainstorming on this topic over the last year since it was posted.
|
||||
|
||||
Many initial brainstorms were focused on more notebook-like features in the
|
||||
Terminal. For example, finding ways to create individual terminal blocks inline
|
||||
with commands, where each input command and its output would be separated from
|
||||
one another, possibly separated by some sort of text/rich markup. This seemed to
|
||||
precipitate the need for a new file syntax to be authored, where we could save
|
||||
commands as they were run. The Terminal would then open this new file type as a
|
||||
set of terminal blocks each pre-populated with these saved commands.
|
||||
|
||||
However, this came with the drawback that projects which would like to leverage
|
||||
this feature would have to author entirely new files, in a new syntax, just to
|
||||
make use of this functionality. It seemed as though it was a niche enough UX
|
||||
that it would be unlikely to broadly catch on.
|
||||
|
||||
The real inspiration here was that there's already a file type with broad
|
||||
adoption that's already filled with commands like this. Markdown files. Take a
|
||||
look at something like
|
||||
[building.md](https://github.com/microsoft/terminal/blob/main/doc/building.md).
|
||||
That file _already_ has a long set of commands for building the Terminal,
|
||||
running tests, deploying, and various other helper scripts. Being able to
|
||||
immediately leverage this existing ecosystem would undobtably lead to quicker
|
||||
adoption.
|
||||
|
||||
### User Stories
|
||||
|
||||
* **A**: The user can perform some commandline action (like `wt open
|
||||
README.md`), which opens a new pane in the Terminal, with the markdown file
|
||||
rendered into that pane.
|
||||
* **B**: Markdown panes have buttons next to code blocks that allow the text of
|
||||
that block to be sent directly to the adjacent terminal as input.
|
||||
* **C**: The user can press different buttons to run some subset of all the
|
||||
commands in the file
|
||||
- **C.1**: Run all the commands in this file
|
||||
- **C.2**: Run all the commands from (the currently selected block) to the end
|
||||
of the file
|
||||
- **C.1**: Run all the commands from (the currently selected block) to the
|
||||
next header. (e.g., run all the commands in this section of the doc.)
|
||||
* **D**: The user can edit the contents of the markdown file directly in the
|
||||
Terminal.
|
||||
* **E**: The Terminal could be configured to automatically open a markdown file
|
||||
when `cd`ing to a directory
|
||||
* **F**: The command for opening a markdown file also supports opening files
|
||||
from the web (e.g. directly from GitHub)
|
||||
* **G**: Code blocks in the markdown file are automatically assigned
|
||||
autoincrementing IDs. The user can perform an action (via keybinding, command
|
||||
palette, whatever) to execute a command block from the file, based on it's
|
||||
assigned ID.
|
||||
* **H**: ...
|
||||
|
||||
|
||||
## Solution Design
|
||||
|
||||
Below are two different structures that could be used for imlpementing notebooks
|
||||
in the Terminal. These are **Side-by-side** notebooks, and **Inline** notebooks.
|
||||
|
||||
* **Side-by-side** notebooks consist of two panes - a standard terminal control
|
||||
in one, and rendered markdown in the other.
|
||||
* **Inline** notebooks are more like traditional notebooks, with the terminal
|
||||
output rendered as a block within the rendered markdown content.
|
||||
|
||||
### Side-by-side notebooks
|
||||
|
||||
Opening Markdown side-by-side with the Terminal output is certainly a little
|
||||
different than the way a notebook traditionally works. Notebooks typically have
|
||||
the code in a block, with output inline, below the block. Blocks could also just
|
||||
be dedicated to text, for documentation mixed between the code. The feature
|
||||
proposed here is different from that, for sure. For this proposal, the Terminal
|
||||
still exists side-by-side from the source markdown. Running commands from the
|
||||
markdown text would then send the command as a string of input to the connected
|
||||
terminal. This approach was elected over attempting to create artificial
|
||||
boundaries between different blocks.
|
||||
|
||||
Oftentimes, the command line is a very stateful experience. Set some environment
|
||||
variables, run some script, use the errorlevel from the previous command, etc.
|
||||
Running each block in wholly separate console instances would likely not be
|
||||
useful.
|
||||
|
||||
Additionally, finding the separation between command line input and its output,
|
||||
and the separation between individual commands is not an entirely trivial
|
||||
process. Should we try to separate out the command input line into one buffer,
|
||||
then the output into another buffer sounds great on paper. Consider, however,
|
||||
something like `cmd.exe`, which does not provide any sort of distinction between
|
||||
its input line and its output. Or `python.exe`, as an interactive REPL, which
|
||||
certainly doesn't tell the terminal the difference. How would we be able to
|
||||
detect something like a multi-line command at the REPL?
|
||||
|
||||
By keeing the command blocks out-of-band from the terminal output, we keep the
|
||||
familiar terminal experience. It acts just as you'd expect, with no additional
|
||||
configuration on the user's side. The commands are something that are already
|
||||
written down, just waiting for the user to run them. They could even be sent to
|
||||
something that isn't necessarily a shell - like pasting a bit of configuration
|
||||
into a text editor like `vim` or `emacs`. The commands in the markdown side are
|
||||
just strings of text to send to the terminal side - nothing more.
|
||||
|
||||
### Inline notebooks
|
||||
|
||||
Is there a way to have a more traditional notebook experience, where the
|
||||
terminal output is rendered as blocks within the markdown itself? I believe
|
||||
there is, by making agressive use of the FTCS mark VT sequences. These are
|
||||
sequences that enable identifying the parts of the buffer as a prompt, the
|
||||
commandline, or the output. We can use these to pull out individual rows of the
|
||||
buffer, and display them as miniature terminal controls within the notebook.
|
||||
|
||||
This involves a single terminal insance backing the entire notebook. When the
|
||||
user runs a code block in the notebook, we'll `sendInput` the text to the
|
||||
backing terminal the same as before. We'll then use the `FTCS_COMMAND_EXECUTED`
|
||||
sequence to know where the actual start of the output of the command is. We'll
|
||||
gather all output from that moment on, and tee that to a separate "front"
|
||||
control, which we use as the display for the output of the command. We'll render
|
||||
that "front" control inline with the rest of the markdown content, immediately
|
||||
below the code block for that command.
|
||||
|
||||
> **Warning**: TODO! How do we want to handle interactive notebooks? Like, the user
|
||||
> wants to run a command, and that creates a new block? We want to make sure
|
||||
> the shell prompt is still just as interactive as ever.
|
||||
|
||||
> **Warning**: TODO! What about users who want to hit play on a whole bunch of
|
||||
> blocks at once? We need a mechanism for queueing them, so that pressing play
|
||||
> on two blocks waits till the first completes before starting the second.
|
||||
|
||||
> **Warning**: TODO! How do we deal with "page editing" multiple commands,
|
||||
> interactively? Like, The user wants to interactively compose `cd
|
||||
> c:\foo\`<kbd>tab</kbd>, then as a part of the same block do `dir | findstr
|
||||
> *.json`? Does each command become it's own block, with a button to
|
||||
> "concatenate" to the preceeding / following block?
|
||||
|
||||
|
||||
### Windows Terminal implementation
|
||||
|
||||
The Terminal will allow for non-terminal content in a pane. This is something
|
||||
that's been prototyped before, just needs a stronger justification for
|
||||
finishing.
|
||||
|
||||
We'll leverage the Terminal's existing `sendInput` command to handle a lot of
|
||||
this. That can be used to send keystrokes to the Terminal. Figuring out which
|
||||
pane to send the `sendInput` command to might be a bit tricky. We'll need to
|
||||
figure out what an action like that does when the active pane is not a terminal
|
||||
pane.
|
||||
|
||||
The side-by-side experience is the easiest to implement today with the current
|
||||
Terminal model. This wouldn't require any major changes to our `TermControl`,
|
||||
which implements the actual terminal control within the Terminal app.
|
||||
|
||||
The inline experience would be more complicated - how do we
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
### Side-by-side
|
||||

|
||||
|
||||
|
||||
### Inline
|
||||
|
||||

|
||||
|
||||
## Tenents
|
||||
|
||||
<table>
|
||||
|
||||
<tr><td><strong>Accessibility</strong></td><td>
|
||||
|
||||
[comment]: # How will the proposed change impact accessibility for users of screen readers, assistive input devices, etc.
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Security</strong></td><td>
|
||||
|
||||
[comment]: # How will the proposed change impact security?
|
||||
|
||||
Opening a file like this will _never_ auto-run commands. Commands must always be
|
||||
intentionally interacted with, to provide a positive confirmation from the user
|
||||
"yes, I intended to run `curl some.website.com/foo.txt`".
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Reliability</strong></td><td>
|
||||
|
||||
[comment]: # Will the proposed change improve reliability? If not, why make the change?
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Compatibility</strong></td><td>
|
||||
|
||||
[comment]: # Will the proposed change break existing code/behaviors? If so, how, and is the breaking change "worth it"?
|
||||
|
||||
It's critically important that nothing about this feature be necessarily Windows
|
||||
Terminal-dependent. These features shouldn't be powered by some new undocumented
|
||||
escape sequence that only we support. They should NOT be powered by new Windows
|
||||
APIs, especially not any extensions to the Console API. There's no reason other
|
||||
terminals couldn't also implement similar functionality.
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Performance, Power, and Efficiency</strong></td><td>
|
||||
|
||||
[comment]: # Will the proposed change break existing code/behaviors? If so, how, and is the breaking change "worth it"?
|
||||
|
||||
</td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
## Potential Issues
|
||||
|
||||
For rendering markdown, we'll either need:
|
||||
* A way to display a WebView in a WinUI2 XAML Island
|
||||
- This is something that's on the backlog currently for MUX 2.x. Theoretically
|
||||
not too hard to add an `IInitializeWithWindow` to `WebView2` which should
|
||||
enable XAML Islands, but needs more research.
|
||||
* To migrate to WinUI 3
|
||||
- In WinUI 3 I believe we should be able to get WebViews for free.
|
||||
- We might still be a XAML Island in WinUI 3, which may complicate that.
|
||||
* A C++ based method of rendering Markdown to UWP XAML
|
||||
- There's a Windows Community Toolkit control for rendering to XAML currently,
|
||||
but that is backed by C#, so we can't use that.
|
||||
|
||||
We'll also need the markdown rendering to be extensible, so that we can insert
|
||||
"play" buttons alongside the blocks.
|
||||
|
||||
## Future considerations
|
||||
|
||||
### Tighter GitHub integration
|
||||
|
||||
GitHub already has the helpful "Open In GitHub" button for opening a repo in the
|
||||
GitHub desktop client, or in Visual Studio.
|
||||
|
||||

|
||||
|
||||
It'd be cool if there was a similar button for opening it up in the Terminal. It
|
||||
could open the README immediately as a new tab, and then provide some sort of
|
||||
InfoBar with a button that would allow the user to immediately clone the repo to
|
||||
some location on their PC. This would likely need a protocol handler installed
|
||||
by the Terminal to help connect the browser to the Terminal.
|
||||
|
||||
### Collapsible Blocks
|
||||
|
||||
One of the key features of notebooks is the ability to easily collapse regions
|
||||
of the notebook. With the command output being out of band from the input of the
|
||||
command, not as independent blocks, this becomes a bit trickier. To try and
|
||||
reproduce a similar ability to collapse regions of the buffer, we'll look to
|
||||
[Marks] in the terminal as a potential solution. The FinalTerm sequences allow a
|
||||
client to mark up the region of the buffer that's the prompt, the command line,
|
||||
and the output. Using those marks would provide an easy heuristic to allow users
|
||||
to collapse the output of commands. These sequences however do require manual
|
||||
configuration by the user, and are not expected to be able to work in all
|
||||
environments (and shells). While powerful, because of this limitation, we didn't
|
||||
want to architect the entire experience around something that wouldn't always
|
||||
work.
|
||||
|
||||
## Resources
|
||||
|
||||
[comment]: # Be sure to add links to references, resources, footnotes, etc.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
[This thread on the Terminal repo](https://github.com/microsoft/terminal/issues/14680), where the user included a long collection of commands to run
|
||||
|
||||
### Footnotes
|
||||
|
||||
<a name="footnote-1"><a>[1]:
|
||||
|
||||
[Jupyter notebooks]: https://jupyter.org/
|
||||
[a Jupyter example]: https://jupyter.org/try-jupyter/retro/notebooks/?path=notebooks/Intro.ipynb
|
||||
[this comment on HackerNews]: https://news.ycombinator.com/item?id=26617656
|
||||
[Marks]: https://github.com/microsoft/terminal/issues/11000
|
||||
226
doc/specs/NorthStar/Shell-Completion-UI.md
Normal file
@@ -0,0 +1,226 @@
|
||||
---
|
||||
author: Mike Griese
|
||||
created on: 2022-02-16
|
||||
last updated: 2023-07-07
|
||||
issue id: TODO!
|
||||
---
|
||||
|
||||
# Shell Completions Protocol
|
||||
|
||||
## Abstract
|
||||
|
||||
> Note:
|
||||
>
|
||||
> This is a draft document - mainly just notes from early iterations on the
|
||||
> [Suggestions UI]. The protocol laid out in this version of the doc is very
|
||||
> much not finalized.
|
||||
>
|
||||
> It is included with the remainder of my North Star docs, because it was always
|
||||
> a part of that story. As we iterate on this protocol, we'll revise this doc
|
||||
> with the final protocol.
|
||||
|
||||
## Background
|
||||
### Inspiration
|
||||
### User Stories
|
||||
### Elevator Pitch
|
||||
### Business Justification
|
||||
|
||||
## Solution Design
|
||||
|
||||
### Escape sequence
|
||||
```
|
||||
OSC 633 ; Completions ; Ri ; Rl ; Ci ; Js ST
|
||||
```
|
||||
where
|
||||
* `Ri`: the replacement index (TODO!?)
|
||||
* `Rl`: the replacement length (TODO!?)
|
||||
* `Rl`: the current cursor position in the command (TODO!?)
|
||||
* `Js`: A json-encoded blob describing the suggested completions. See [Completion Schema](#completion-schema) for a more thorough description
|
||||
|
||||
|
||||
|
||||
### Completion Schema
|
||||
|
||||
|
||||
#### Example JSON blobs
|
||||
|
||||
* Typed text: ```Get-M```
|
||||
|
||||
```jsonc
|
||||
[
|
||||
{
|
||||
"CompletionText": "Get-MarkdownOption",
|
||||
"ListItemText": "Get-MarkdownOption",
|
||||
"ResultType": 2,
|
||||
"ToolTip": "Get-MarkdownOption\r\n"
|
||||
},
|
||||
{
|
||||
"CompletionText": "Get-Member",
|
||||
"ListItemText": "Get-Member",
|
||||
"ResultType": 2,
|
||||
"ToolTip": "Get-Member\r\n"
|
||||
},
|
||||
{
|
||||
"CompletionText": "Get-Module",
|
||||
"ListItemText": "Get-Module",
|
||||
"ResultType": 2,
|
||||
"ToolTip": "\r\nGet-Module [[-Name] <string[]>] [-FullyQualifiedName <ModuleSpecification[]>] [-All] [<CommonParameters>]\r\n\r\nGet-Module [[-Name] ... (omitted for brevity)"
|
||||
},
|
||||
// ...
|
||||
]
|
||||
|
||||
```
|
||||
|
||||
* Typed text: ```Get-Module ```
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"CompletionText": "Microsoft.PowerShell.Management",
|
||||
"ListItemText": "Microsoft.PowerShell.Management",
|
||||
"ResultType": 8,
|
||||
"ToolTip": "Description: \r\nModuleType: Manifest\r\nPath: C:\\program files\\powershell\\7\\Modules\\Microsoft.PowerShell.Management\\Microsoft.PowerShell.Management.psd1"
|
||||
},
|
||||
{
|
||||
"CompletionText": "Microsoft.PowerShell.Utility",
|
||||
"ListItemText": "Microsoft.PowerShell.Utility",
|
||||
"ResultType": 8,
|
||||
"ToolTip": "Description: \r\nModuleType: Manifest\r\nPath: C:\\program files\\powershell\\7\\Modules\\Microsoft.PowerShell.Utility\\Microsoft.PowerShell.Utility.psd1"
|
||||
},
|
||||
{
|
||||
"CompletionText": "PSReadLine",
|
||||
"ListItemText": "PSReadLine",
|
||||
"ResultType": 8,
|
||||
"ToolTip": "Description: Great command line editing in the PowerShell console host\r\nModuleType: Script\r\nPath: C:\\program files\\powershell\\7\\Modules\\PSReadLine\\PSReadLine.psm1"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
### PowerShell function
|
||||
|
||||
```ps1
|
||||
function Send-Completions {
|
||||
$commandLine = ""
|
||||
$cursorIndex = 0
|
||||
|
||||
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$commandLine, [ref]$cursorIndex)
|
||||
$completionPrefix = $commandLine
|
||||
|
||||
# Get completions
|
||||
$result = "`e]633;Completions"
|
||||
if ($completionPrefix.Length -gt 0) {
|
||||
# Get and send completions
|
||||
$completions = TabExpansion2 -inputScript $completionPrefix -cursorColumn $cursorIndex
|
||||
if ($null -ne $completions.CompletionMatches) {
|
||||
$result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);"
|
||||
$result += $completions.CompletionMatches | ConvertTo-Json -Compress
|
||||
}
|
||||
}
|
||||
$result += "`a"
|
||||
|
||||
Write-Host -NoNewLine $result
|
||||
}
|
||||
```
|
||||
|
||||
## UX / UI Design
|
||||
|
||||

|
||||
|
||||
### Description tooltips
|
||||
|
||||
### Segoe Fluent Icons
|
||||
|
||||
See: https://github.com/PowerShell/PowerShellEditorServices/pull/1738
|
||||
|
||||
| Name | val | Icon ideas | description
|
||||
| ------------------- | --- | --------------------- | --------------
|
||||
| Text | 0 | | An unknown result type, kept as text only.
|
||||
| History | 1 |e81c History | A history result type like the items out of get-history.
|
||||
| Command | 2 |ecaa AppIconDefault | A command result type like the items out of get-command.
|
||||
| ProviderItem | 3 |e8e4 AlignLeft | A provider item.
|
||||
| ProviderContainer | 4 |e838 FolderOpen | A provider container.
|
||||
| Property | 5 |e7c1 Flag | A property result type like the property items out of get-member.
|
||||
| Method | 6 |ecaa AppIconDefault | A method result type like the method items out of get-member.
|
||||
| ParameterName | 7 |e7c1 Flag | A parameter name result type like the Parameters property out of get-command items.
|
||||
| ParameterValue | 8 |f000 KnowledgeArticle| A parameter value result type.
|
||||
| Variable | 9 | | A variable result type like the items out of get-childitem variable.
|
||||
| Namespace | 10 |e943 Code | A namespace.
|
||||
| Type | 11 | | A type name.
|
||||
| Keyword | 12 | | A keyword.
|
||||
| DynamicKeyword | 13 |e945 LightningBolt | A dynamic keyword.
|
||||
|
||||
#### Sample XAML
|
||||
|
||||
The following XAML produces a menu that looks like the following:
|
||||
|
||||

|
||||
|
||||
I included a scrollviewer, because I couldn't seem to find a way to get the tooltip to be wider. I'm sure there's better ways of styling it in real code (vs just in XAML studio).
|
||||
|
||||
```xml
|
||||
<muxc:TeachingTip x:Name="MyTooltip"
|
||||
IsOpen="True"
|
||||
MinWidth="900"
|
||||
Title="Get-Module">
|
||||
<ScrollViewer HorizontalScrollMode="Enabled" HorizontalScrollBarVisibility="Hidden" >
|
||||
<TextBlock>
|
||||
<Run>Get-Module [[-Name] <string[]>] [-FullyQualifiedName <ModuleSpecification[]>] [-All] [<CommonParameters>]
|
||||
</Run>
|
||||
<LineBreak/>
|
||||
<Run>Get-Module [[-Name] <string[]>] -ListAvailable [-FullyQualifiedName <ModuleSpecification[]>] [-All] [-PSEdition <string>] [-SkipEditionCheck] [-Refresh] [<CommonParameters>]
|
||||
</Run>
|
||||
<LineBreak/>
|
||||
<Run>Get-Module [[-Name] <string[]>] -PSSession <PSSession> [-FullyQualifiedName <ModuleSpecification[]>] [-ListAvailable] [-PSEdition <string>] [-SkipEditionCheck] [-Refresh] [<CommonParameters>]
|
||||
</Run>
|
||||
<LineBreak/>
|
||||
<Run>Get-Module [[-Name] <string[]>] -CimSession <CimSession> [-FullyQualifiedName <ModuleSpecification[]>] [-ListAvailable] [-SkipEditionCheck] [-Refresh] [-CimResourceUri <uri>] [-CimNamespace <string>] [<CommonParameters>]
|
||||
</Run>
|
||||
</TextBlock>
|
||||
</ScrollViewer>
|
||||
</muxc:TeachingTip>
|
||||
```
|
||||
|
||||
|
||||
## Tenents
|
||||
|
||||
<table>
|
||||
|
||||
<tr><td><strong>Compatibility</strong></td><td>
|
||||
|
||||
[TODO!]: TODO! -----------------------------------------------------------------
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Accessibility</strong></td><td>
|
||||
|
||||
The SXN UI was designed with the goal of making commandline shell suggestions _more_ accessible. As Carlos previously wrote:
|
||||
|
||||
> Screen readers struggle with this because the entire menu is redrawn every time, making it harder to understand what exactly is "selected" (as the concept of selection in this instance is a shell-side concept represented by visual manipulation).
|
||||
>
|
||||
> ...
|
||||
>
|
||||
> _\[Shell driven suggestions\]_ can then be leveraged by Windows Terminal to create UI elements. Doing so leverages WinUI's accessible design.
|
||||
|
||||
This will allow the Terminal to provide more context-relevant information to
|
||||
screen readers.
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Sustainability</strong></td><td>
|
||||
|
||||
No sustainability changes expected.
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Localization</strong></td><td>
|
||||
|
||||
[TODO!]: TODO! -----------------------------------------------------------------
|
||||
The localization needs of the Suggestions UI will be effectively the same as the
|
||||
needs of the Command Palette.
|
||||
|
||||
</td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
[Suggestions UI]: ./Suggestions-UI.md
|
||||
19
doc/specs/NorthStar/Shell-Integration-Marks.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
author: Mike Griese
|
||||
created on: 2022-03-28
|
||||
last updated: 2023-07-07
|
||||
issue id: 11000, 1527, 6232
|
||||
---
|
||||
|
||||
##### [Original issue: [#1527]] [experimental PR [#12948]] [remaining marks [#14341]]
|
||||
|
||||
# Windows Terminal - Shell Integration (Marks)
|
||||
|
||||
> Note:
|
||||
>
|
||||
> This document has been moved. It was originally authored as a part of the
|
||||
> North Star docs, but later submitted for its own review. You can find it in PR
|
||||
> at
|
||||
> [microsoft/terminal#14792](https://github.com/microsoft/terminal/pull/14792),
|
||||
> or the final home of this doc in
|
||||
> [Shell-Integration-Marks.md](../%2311000%20-%20Marks/Shell-Integration-Marks.md)
|
||||
670
doc/specs/NorthStar/Suggestions-UI.md
Normal file
@@ -0,0 +1,670 @@
|
||||
---
|
||||
author: Mike Griese
|
||||
created on: 2022-08-22
|
||||
last updated: 2023-02-16
|
||||
issue id: 1595
|
||||
---
|
||||
|
||||
# Windows Terminal - Suggestions UI
|
||||
|
||||
## Abstract
|
||||
|
||||
Multiple related scenarios have come up where it would be beneficial to display
|
||||
actionable UI to the user within the context of the active terminal itself. This
|
||||
UI would be akin to the Intellisense UI in Visual Studio. It appears right where
|
||||
the user is typing, and can help provide immediate content for the user, based
|
||||
on some context. The "Suggestions UI" is this new ephemeral UI within the
|
||||
Windows Terminal that can display different types of actions, from different
|
||||
sources.
|
||||
|
||||
## Background
|
||||
|
||||
The Suggestions UI is the singular UI by which the Terminal can display a
|
||||
variety of suggestions to the user. These include:
|
||||
|
||||
* Recent commands the user has executed in this terminal, powered by shell integration.
|
||||
* Recent directories, similarly powered by shell integration
|
||||
* Completions from the shell itself (like the shell completions in PowerShell)
|
||||
* Tasks, which are `sendInput` actions from the user's settings
|
||||
* Buffer Completions, which is a dumb type of autocomplete based on words in the buffer
|
||||
* and more (as provided via extensions)
|
||||
|
||||
All of these scenarios are places where it makes sense to present the user a
|
||||
menu at the point of text insertion in the terminal control itself.
|
||||
|
||||
### Inspiration
|
||||
|
||||
Primarily, the inspiration is any Intellisense-like experience, in any app.
|
||||
Visual Studio, VsCode, PowerShell, vim, Sublime any JetBrains IDE - there's more
|
||||
than enough examples in the wild.
|
||||
|
||||
Ultimately, the inspiration for the Suggestions UI came from a bunch of places
|
||||
all at once. In the course of a few months though, it became clear that we'd
|
||||
need a unified UI for displaying a variety of suggestion-like experiences in the
|
||||
Terminal. Our work with the PowerShell and VsCode teams helped refine these
|
||||
requests all into the unified design below.
|
||||
|
||||
### User Stories
|
||||
|
||||
Story | Size | Description
|
||||
--|-----------|--
|
||||
| 🐣 Crawl | The user can bring up the Suggestions UI with recent commands, powered by shell integration
|
||||
| 🐣 Crawl | [#12863] The user can bring up the Suggestions UI with recent directories, powered by shell integration
|
||||
| 🚶 Walk | The user can bring up the Suggestions UI with tasks from their settings
|
||||
| 🚶 Walk | CLI apps can invoke the Suggestions UI with a new VT sequence
|
||||
| 🚶 Walk | The Suggestions UI can be opened using the current typed commandline as a filter
|
||||
| 🚶 Walk | Recent commands and directories are stored in `state.json`, across sessions
|
||||
| 🏃♂️ Run | Suggestions can have descriptions presented in / alongside the UI
|
||||
| 🏃♂️ Run | The Suggestions UI can be opened without any nesting
|
||||
| 🏃♂️ Run | The Suggestions UI can be opened, nested by `source` of the suggestion
|
||||
| 🚀 Sprint | Extensions can provide suggestion sources for the Suggestions UI
|
||||
| 🚀 Sprint | The Suggestions UI can be opened in "inline" mode, only showing the text of the first suggestion
|
||||
|
||||
### Elevator Pitch
|
||||
|
||||
The Suggestions UI is a UI element displayed in the Terminal for providing
|
||||
different types of text suggestions to the user - anything from recently run
|
||||
commands, to saved commands, to tab-completion suggestions from the shell
|
||||
itself.
|
||||
|
||||
## Business Justification
|
||||
|
||||
It will delight developers.
|
||||
|
||||
Furthermore, our partners on the Visual Studio team have been requesting similar
|
||||
functionality for some time now. The way autocompletion menus in PowerShell
|
||||
currently interact with UIA clients leaves much to be desired. They'd like a way
|
||||
to provide richer context to screen readers. Something to enable the terminal to
|
||||
more specifically describe the context of what's being presented to the user.
|
||||
|
||||
## Scenario Details
|
||||
|
||||
### UI/UX Design
|
||||
|
||||
#### Prototypes
|
||||
|
||||
The following gif was a VsCode prototype of [shell-driven autocompletion]. This
|
||||
is the point of reference we're starting from when talking about what the
|
||||
suggestions UI might look like.
|
||||
|
||||

|
||||
|
||||
These suggestions are populated by logic within PowerShell itself, and
|
||||
communicated to the Terminal. The Terminal can then display them in the
|
||||
Suggestions UI.
|
||||
|
||||
The following gifs demonstrate a prototype of what that might look like for the
|
||||
Terminal. These are meant to be informative, not normative, representations of
|
||||
what the UI would look like.
|
||||
|
||||

|
||||
|
||||
An prototype of the recent commands UI, powered by shell integration:
|
||||

|
||||
|
||||
An prototype of the tasks UI, powered by the user's settings:
|
||||

|
||||
(admittedly, the `TeachingTip` needs better placement).
|
||||
|
||||
In general, the Suggestions UI will present a list of elements to select from,
|
||||
near the text cursor. This control might be contain a text box for filtering
|
||||
these items (a "**palette**"), or it might not (a "**menu**").
|
||||
|
||||

|
||||
|
||||
#### Palette vs Menu
|
||||
|
||||
Depending on how the suggestions UI is invoked, we may or may not want to
|
||||
display a text box for filtering these suggestions. Consider the Intellisense
|
||||
menu in Visual Studio. That's a UI that only allows for up/down for navigation
|
||||
(and enter/tab for selecting the suggestion).
|
||||
|
||||
For suggestions driven by the Terminal, we'll display a filtering text box in
|
||||
the Suggestions UI. This is similar to the command palette's search - a fuzzy
|
||||
search to filter the contents. This is the "**palette**" style of the
|
||||
suggestions dialog.
|
||||
|
||||
For completions driven by the shell, we should probably not display the
|
||||
filtering text box. This is the "**menu**" style of the suggestion dialog. The
|
||||
user is primarily interacting with the shell here, not the Terminal.
|
||||
|
||||
> **Warning**
|
||||
> TODO! For discussion, possibly with a real UX designer.
|
||||
|
||||
How should we handle completions here? Tab? Enter? Right-Arrow? Should we have
|
||||
an element selected when we open the menu, or should tab/enter only work once
|
||||
the user has used the arrows at least once? Sublime allows for <kbd>tab</kbd> to
|
||||
complete the suggestion immediately.
|
||||
|
||||
Consider also that these suggestions might be provided by the shell, as the user
|
||||
is typing at a commandline shell. For something like PowerShell, the user might
|
||||
want to start typing a command and have it tab-complete based off the shell's
|
||||
tab expansion rules. PowerShell's inline suggestions use right-arrow to
|
||||
differentiate "use this suggestion" vs tab for "tab expand what I'm typing at
|
||||
the prompt". We should probably preserve this behavior.
|
||||
|
||||
We probably don't want to provide different experiences for the **menu** version
|
||||
won't be pressing tab to tab-complete at the shell (the focus is out of the of
|
||||
the Suggestions UI vs. the **palette** version. In the palette version, the user
|
||||
terminal and into the Suggestions UI).
|
||||
|
||||
We will want to make sure that there's some semblance of consistency across our
|
||||
implementation for the Suggestions UI, our own Command Palette, VsCode's
|
||||
intellisense and their own implementation of shell-completions in the Terminal.
|
||||
|
||||
> **Note**
|
||||
> In my prototype, for the "Menu" mode, I accepted ALL of right-arrow, tab, and
|
||||
> enter as "accept completion", and any other key dismissed the UI. This _felt_
|
||||
> right for that mode. I'm not sure we could make the same call for "palette"
|
||||
> mode, where we'd need tab for navigating focus.
|
||||
|
||||
### Implementation Details
|
||||
|
||||
#### Fork the Command Palette
|
||||
|
||||
We're largely going to start with the Command Palette to build the Suggestions
|
||||
UI. The Command Palette is already a control we've built for displaying a
|
||||
transient list of commands and dispatching them to the rest of the app.
|
||||
|
||||
Currently, the Command Palette is a single static control, at the top-center of
|
||||
the Terminal window, and occupying a decent portion of the screen. For the
|
||||
Suggestions UI, we'll instead want to make sure that the control appears
|
||||
relative to the current cursor position.
|
||||
|
||||
We'll start by taking the command palette, and copying it over to a new control.
|
||||
This will allow us to remove large chunks of code dealing with diffent modes
|
||||
(i.e. the tab switcher), and code dealing with prefix characters to switch
|
||||
modes.
|
||||
|
||||
We'll need to make some small modifications to enable the Suggestions UI to
|
||||
* work as a text cursor-relative control
|
||||
* exist as a Flyout outside the bounds of the Terminal window
|
||||
* If the Suggestions UI is too close to the bottom of the screen, we'll need it to open
|
||||
"upwards", with the search box at the _bottom_ and the list extending above it
|
||||
* prevent it from switching to command-line mode
|
||||
* display tooltips / `TeachingTip`s / some secondary flyout with a description
|
||||
of the suggestion (if provided)
|
||||
|
||||
#### Completion sources
|
||||
|
||||
The Suggestions UI will support suggestions from a variety of different
|
||||
"sources". As an example, consider the following actions:
|
||||
|
||||
```json
|
||||
{ "command": { "action":"suggestions", "source": "commandHistory" } },
|
||||
{ "command": { "action":"suggestions", "source": "directoryHistory" } },
|
||||
|
||||
{ "command": { "action":"suggestions", "source": "tasks" } },
|
||||
{ "command": { "action":"suggestions", "source": "local" } },
|
||||
|
||||
{ "command": { "action":"suggestions", "source": ["local", "tasks", "commandHistory"] } },
|
||||
|
||||
{ "command": { "action":"suggestions", "source": "Microsoft.Terminal.Extensions.BufferComplete" } },
|
||||
```
|
||||
|
||||
Each of these `suggestions` actions would open the Suggestions UI with a
|
||||
different set of actions.
|
||||
|
||||
* `commandHistory`: Use commands from this session, as identified via shell
|
||||
integration. This won't be able to return any suggestions if the user has not
|
||||
configured their shell to support shell integration sequences yet.
|
||||
* `directoryHistory`: Populate the list with a series of `cd {path}` commands,
|
||||
where the paths are populated via shell integration. Paths are in MRU order.
|
||||
* `tasks`: Populate the list with all `sendInput` actions in the user's settings
|
||||
file. The command structure should remain unchanged. For example, if they have
|
||||
`sendInput` actions nested under a "git" command, then the "git" entry will
|
||||
remain in this tasks view with their `sendInput` actions nested inside it. For
|
||||
more details, see the [Tasks] spec.
|
||||
* `local`: Populate the list with tasks that are located in the CWD, in a file
|
||||
named `.wt.json`. For more details, see the [Tasks] spec.
|
||||
* `Microsoft.Terminal.Extensions.BufferComplete`: As an example, this
|
||||
demonstrates how an action might be authored to reference a suggestion source
|
||||
from an extension.
|
||||
|
||||
Each of these different sources will build a different set of `Command`s,
|
||||
primarily populated with `sendInput` actions. We'll load those `Command`s into
|
||||
the Suggestions UI control, and open it at the text cursor.
|
||||
|
||||
To drill in on a single example - the `commmandHistory` source. In that
|
||||
particular case, the TerminalPage will query the active TermControl for a list
|
||||
of it's recent commands. If it knows these (via shell integration), then the
|
||||
TerminalPage will use that list of commands to build a list of `sendInput`
|
||||
actions. Those will then get fed to the suggestions UI.
|
||||
|
||||
Not listed above is [shell-driven autocompletion]. These aren't something that
|
||||
the Terminal can invoke all on it's own - these are something the shell would
|
||||
need to invoke themselves.
|
||||
|
||||
#### Pre-populate the current commandline context
|
||||
|
||||
Consider the following scenario. A user has typed `git c` in their shell, and
|
||||
has [shell integration] enabled for their shell. They want to open the
|
||||
Suggestions UI filtered to their recent history, but starting with what they've
|
||||
already typed. To support this scenario, we'll add an addional property:
|
||||
|
||||
* `"useCommandline"`: `bool`
|
||||
* `true`: the current commandline the user has typed will pre-populate the
|
||||
filter of the Suggestions UI. This requires that the user has enabled shell
|
||||
integration in their shell's config.
|
||||
* `false`: the filter will start empty.
|
||||
|
||||
With that setting, the user can achieve their desired UX with the following action:
|
||||
|
||||
```json
|
||||
{ "command": { "action":"suggestions", "source": "commandHistory", "useCommandline": true } },
|
||||
```
|
||||
|
||||
Now, when they type `git c` and invoke the Suggestions UI, they can immediately
|
||||
start searching for recent commands that started with `git c`.
|
||||
|
||||
#### Default actions
|
||||
|
||||
I propose adding the following actions to the Terminal by default:
|
||||
```json
|
||||
{ "command": { "action":"suggestions", "source": "commandHistory", "useCommandline": true } },
|
||||
{ "command": { "action":"suggestions", "source": "directoryHistory" } },
|
||||
{ "command": { "action":"suggestions", "source": ["local", "tasks", "commandHistory"], "useCommandline": true, "nesting": "disabled" } },
|
||||
{ "command": { "action":"suggestions", "source": ["all"], "useCommandline": false, "nesting": "source" } },
|
||||
```
|
||||
|
||||
These actions are colloquially:
|
||||
* Give me suggestions from my recent commands, using what I've typed
|
||||
* Give me suggestions of directories I've recently been in
|
||||
* _(After [Tasks] are implemented)_ Give me suggestions from recent commands,
|
||||
commands I've saved, and commands for this project. Don't nest any, so they're
|
||||
all in the top-level menu. Use what I've typed already to start filtering.
|
||||
* Just open the Suggestions UI with all suggestions sources, and group them by
|
||||
the source of the suggestions.
|
||||
|
||||
This should cover most of the basic use cases for suggestions.
|
||||
|
||||
## Tenents
|
||||
|
||||
<table>
|
||||
|
||||
<tr><td><strong>Compatibility</strong></td><td>
|
||||
|
||||
This shouldn't break any existing flows. This is a general purpose UI element,
|
||||
to be extended in a variety of ways. Those customizations will all be opt-in by
|
||||
the user, so I'm not expecting any breaking compatibility changes here.
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Accessibility</strong></td><td>
|
||||
|
||||
The Suggestions UI was designed with the goal of making commandline shell
|
||||
suggestions _more_ accessible. As Carlos previously wrote:
|
||||
|
||||
> Screen readers struggle with this because the entire menu is redrawn every time, making it harder to understand what exactly is "selected" (as the concept of selection in this instance is a shell-side concept represented by visual manipulation).
|
||||
>
|
||||
> ...
|
||||
>
|
||||
> _\[Shell driven suggestions\]_ can then be leveraged by Windows Terminal to create UI elements. Doing so leverages WinUI's accessible design.
|
||||
|
||||
This will allow the Terminal to provide more context-relevant information to
|
||||
screen readers.
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Sustainability</strong></td><td>
|
||||
|
||||
No sustainability changes expected.
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Localization</strong></td><td>
|
||||
|
||||
The localization needs of the Suggestions UI will be effectively the same as the
|
||||
needs of the Command Palette.
|
||||
|
||||
</td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### 🐣 Crawl
|
||||
|
||||
* [ ] Fork the Command palette to a new UI element, the `SuggestionsControl`
|
||||
* [ ] Enable previewing `sendInput` actions in the Command Palette and `SuggestionsControl`
|
||||
* [ ] Enable the `SuggestionsControl` to open top-down (aligned to the bottom of the cursor row) or bottom-up (aligned to the top of the cursor row).
|
||||
* [ ] Disable sorting on the `SuggestionsControl` - elements should presumably be pre-sorted by the source.
|
||||
* [ ] Expose the recent commands as a accessor on `TermControl`
|
||||
* [ ] Add a `suggestions` action which accepts a single option `recentCommands`. These should be fed in MRU order to the `SuggestionsControl`.
|
||||
* [ ] Expose the recent directories as a accessor on `TermControl`, and add a `recentDirectories` source.
|
||||
|
||||
### 🚶 Walk
|
||||
|
||||
* [ ] Add a `tasks` source to `suggestions` which opens the Suggestions UI with
|
||||
a tree of all `sendInput` commands
|
||||
* [ ] Enable the `SuggestionsControl` to open with or without a search box
|
||||
* [ ] Plumb support for shell-driven completions through the core up to the app
|
||||
* [ ] Figure out how exactly we want to persist recent commands / directories. Globally? Per-profile? Layered? Per executable (does that even make sense)?
|
||||
* [ ] Persist recent commands / directories accordingly
|
||||
* [ ] Expose the _current_ commandline from the `TermControl`
|
||||
* [ ] Add a `useCommandline` property to `suggestions`, to pre-populate the search with the current commandline.
|
||||
|
||||
### 🏃♂️ Run
|
||||
|
||||
* [ ] Add a `description` field to `Command`
|
||||
* [ ] Add a `TeachingTip` (or similar) to the Suggestions UI to display
|
||||
descriptions (when available)
|
||||
* [ ] Use the `ToolTip` property of shell-driven suggestions as the description
|
||||
* [ ] Add a boolean `nesting` property which can be used to disable nesting on the `tasks` source.
|
||||
* [ ] Add the ability for `nesting` to accept `enabled`/`disabled` as `true`/`false` equivalents
|
||||
* [ ] Add the ability for `nesting` to accept `source`, which instead groups all
|
||||
commands to the Suggestions UI by the source of that suggestion.
|
||||
|
||||
### 🚀 Sprint
|
||||
|
||||
The two "sprint" tasks here are much more aspirational than the other listed
|
||||
scenarios, so breaking them down to atomic tasks sees less reasonable. We'd have
|
||||
to spend a considerable amount more time figuring out _how_ to do each of these
|
||||
first.
|
||||
|
||||
For example - extensions. We have yet to fully realize what extensions _are_.
|
||||
Determining how extensions will provide suggestions is left as something we'll
|
||||
need to do as a part of the Extensions spec.
|
||||
|
||||
## Conclusion
|
||||
|
||||
Here's a sample json schema for the settings discussed here.
|
||||
|
||||
```json
|
||||
"OpenSuggestionsAction": {
|
||||
"description": "Arguments corresponding to a Open Suggestions Action",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/$defs/ShortcutAction"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"const": "suggestions"
|
||||
},
|
||||
"source": {
|
||||
"$ref": "#/$defs/SuggestionSource",
|
||||
"description": "Which suggestion sources to filter."
|
||||
},
|
||||
"useCommandline": {
|
||||
"default": false,
|
||||
"description": "When set to `true`, the current commandline the user has typed will pre-populate the filter of the Suggestions UI. This requires that the user has enabled shell integration in their shell's config. When set to false, the filter will start empty."
|
||||
},
|
||||
"nesting": {
|
||||
"default": true,
|
||||
"description": "When set to `true`, suggestions will follow the provided nesting structure. For Tasks, these will follow the structure of the Command Palette. When set to `false`, no nesting will be used (and all suggestions will be in the top-level menu.",
|
||||
"$comment": "This setting is a possible follow-up setting, not required for v1. "
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"SuggestionSource": {
|
||||
"default": "all",
|
||||
"description": "Either a single suggestion source, or an array of sources to concatenate. Built-in sources include `commandHistory`, `directoryHistory`, `tasks`, and `local`. Extensions may provide additional values. The special value `all` indicates all suggestion sources should be included",
|
||||
"$comment": "`tasks` and `local` are sources that would be added by the Tasks feature, as a follow-up"
|
||||
"oneOf": [
|
||||
{
|
||||
"type": [ "string", "null" ]
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
]
|
||||
},
|
||||
```
|
||||
|
||||
### Future Considerations
|
||||
|
||||
* Another extension idea: `WithFig.FigCompletions`. Imagine an extension that
|
||||
could parse existing [Fig] completion specs, and provide those as suggestions
|
||||
in this way.
|
||||
* This might be a good example of an async suggestion source. The current
|
||||
commandline is used as the starting filter, and the suggestions would be
|
||||
populated by some `fig` process / thread / async operation that returns the
|
||||
suggestions.
|
||||
* If the user hasn't enabled shell completion, we could add text to the
|
||||
`commandHistory` or `directoryHistory` menus to inform the user how they could
|
||||
go enable shell integration.
|
||||
* Maybe there could be a per-profile setting for automatic suggestions after
|
||||
some timeout. Like, as you type, a menu version of the Suggestions UI appears.
|
||||
So you could just start typing `git c`, and it would automatically give you a
|
||||
menu with suggestions, implicitly using the typed command as the "filter".
|
||||
* Maybe we could do this as an `implicit` property on the `suggestions` action
|
||||
* It might make sense in the future to have the Suggestions UI exposed as an
|
||||
element of the `TermControl` itself, rather than an element of the
|
||||
`TerminalPage`. Especially when we consider [shell-driven autocompletion].
|
||||
That seems like a scenario that the `TermControl` should expose for all
|
||||
consumers of the control, without them manually needing to write their own UI
|
||||
element to manage it. This probably could be done without many changes
|
||||
* Instead of operating on `Command`s and actions from the terminal settings,
|
||||
the control could just know that all the entries in the menu are "send
|
||||
input" "actions".
|
||||
* The control could offer a method to manually invoke the Suggestions UI for a
|
||||
list of {suggestion, name, description} objects.
|
||||
* The app layer could easily translate between sendInput actions and these
|
||||
pseudo-actions.
|
||||
|
||||
#### Description Tooltips
|
||||
|
||||
> **Note**: _This is left as a future consideration for the initial draft of
|
||||
> this spec. I'd like to flesh out [shell-driven autocompletion] more before
|
||||
> committing any plans here.
|
||||
|
||||
It would be beneficial for the Suggestions UI to display additional context to
|
||||
the user. Consider a extension that provides some commands for the user, like a
|
||||
hypothetical "Docker" extension. The extension author might be able to give the
|
||||
commands simplified names, but also want to expoose a more detailed description
|
||||
of the commands to the user.
|
||||
|
||||
Or consider the Suggestions UI when invoked by [shell-driven autocompletion].
|
||||
The shell might want to provide help text to the user with each of the
|
||||
suggestions. This would allow a user to browse through the suggestions that they
|
||||
might not know about, and learn how they work before committing to one.
|
||||
|
||||
Only the help text for the currently hovered command should be presented to the
|
||||
user. To support this kind of UX, we'll add an optional flyout of some sort to
|
||||
display with the Suggestions UI. This flyout will only appear if there's more
|
||||
information provided to the Terminal.
|
||||
|
||||
This might be in the form of a `TeachingTip`, as in this example:
|
||||

|
||||
|
||||
Actions in the settings could also accept an optional `description` property, to
|
||||
specify the string that would be presented in that flyout.
|
||||
|
||||
#### Pre-filtering the UI & filter by source
|
||||
|
||||
> **Note**: _This is a brainstorm I considered while writing this spec. I would
|
||||
> not not include it in the v1 of this spec. Rather, I'd like to leave it for
|
||||
> where we might go with this UX in the future._
|
||||
|
||||
Do want to support different _types_ of nesting? So instead of just the default,
|
||||
there could be something like `nesting: "source"`, to create a mune structured
|
||||
like:
|
||||
|
||||
```
|
||||
Suggestions UI
|
||||
├─ Recent Commands...
|
||||
│ ├─ git checkout main
|
||||
│ ├─ git fetch
|
||||
│ └─ git pull
|
||||
├─ Recent Directories...
|
||||
│ ├─ d:\dev
|
||||
│ ├─ d:\dev\public
|
||||
│ └─ d:\dev\public\terminal
|
||||
├─ Saved tasks...
|
||||
│ ├─ Git...
|
||||
│ │ └─ git commit -m "
|
||||
│ │ └─ git log...
|
||||
│ └─ bx & runut
|
||||
└─ Docker
|
||||
├─ docker build --platform linux/amd64 <path>
|
||||
└─ docker logs -f --tail <lines_count> <container_name>
|
||||
```
|
||||
|
||||
> **Note**
|
||||
> I'm using `Docker` as an example fragment extension that provides
|
||||
> some `docker` commands. When grouping by `"source"`, we could pull those into
|
||||
> a seperate top-level entry. When not grouping by `"source"`, those would still
|
||||
> show up with the rest of `tasks`. )
|
||||
|
||||
#### Store recent commands across sessions
|
||||
|
||||
> **Note**
|
||||
> _I'm not sure we really want to put this in this spec or not, hence
|
||||
> why it's in the "Future considerations" section. I think it's worth
|
||||
> mentioning. This might be better served in the [shell integration] doc._
|
||||
|
||||
We'll probably want a way for recent commands to be saved across sessions. That way, your `cmd.exe` command history could persist across sessions. We'd need:
|
||||
|
||||
* A setting to enable this behavior
|
||||
* A setting to control the context of these saved commandlines.
|
||||
* Do we want them saved per-profile, or globally?
|
||||
* If they're saved per-profile, maybe a profile can opt-in to loading all the commands?
|
||||
* How does defterm play with this? Do we "layer: by concatenating per-profile commands with `profiles.defaults` ones?
|
||||
* A button in the Settings UI for clearing these commands
|
||||
* Should fragments be able to pre-populate "recent commands"?
|
||||
* I'm just gonna say _no_. That would be a better idea for Tasks (aka just a `sendInput` Action that we load from the fragment normally as a Task), or a specific suggestion source for the fragment extension.
|
||||
|
||||
#### Inline mode
|
||||
|
||||
> **Note**
|
||||
> _This is a half-baked idea with some potential. However, I don't
|
||||
> think it needs to be a part of the v1 of the Suggestions UI, so I'm leaving it
|
||||
> under future considerations for a future revision._
|
||||
|
||||
Do we want to have a suggestions UI "mode", that's just **one** inline
|
||||
suggestion, "no" UI? Some UX ala the `PsReadline` recent command suggestion
|
||||
feature. Imagine, we just display the IME ghost text thing for the first result,
|
||||
given the current prompt?
|
||||
|
||||
Take the following action as an example:
|
||||
|
||||
```json
|
||||
{ "command": { "action":"suggestions", "source": "commandHistory", "useCommandline": true, "inline": true } },
|
||||
```
|
||||
|
||||
Type the start of some command at the prompt, and press that key. Presto, we do
|
||||
the `pwsh` thing. Ghost text appears for the first match in the `commandHistory`
|
||||
for what the user has typed. If they press another key, ~they've typed into the
|
||||
"hidden" Suggestions UI, which filters the (hidden) list more, and updates the
|
||||
one inline suggestion.~
|
||||
|
||||
Or, instead, typed keys go to the shell, and then we re-query the commandline,
|
||||
and update the filter accordingly. That would allow tab-completion to still
|
||||
work. We'd use <kbd>right arrow</kbd> to accept the suggestion (and dismiss the
|
||||
ghost text preview).
|
||||
|
||||
This would seemingly SUPER conflict with PowerShell's own handler. Probably not
|
||||
something someone should enable for PowerShell 7 profiles if they're using that
|
||||
feature.
|
||||
|
||||
### Rejected ideas
|
||||
|
||||
These are musings from earlier verisons of the spec.
|
||||
* **Asynchronous prompting**: This was rejected because it was so fundamentally
|
||||
different from the rest of the UX of the Suggestions UI, it didn't make sense
|
||||
to try and also do that behavior.
|
||||
|
||||
Furthermore, async sources wouldn't work with sync
|
||||
ones, at all. E.g. if you did `source: ["tasks", "myAsyncSource"]`. It doesn't
|
||||
make sense to start with a list of `tasks`, then type, find no tasks, but then
|
||||
oh! the UI fills in some other suggestions too. That's weird.
|
||||
* ...
|
||||
|
||||
#### REJECTED: Asynchronous prompting
|
||||
|
||||
Certain suggestion sources might want to provide results asynchronously.
|
||||
Consider a source that might want to make a web request to populate what strings
|
||||
to suggest. That source might want to prompt the user for input first, then
|
||||
dispatch the request, then populate the UI. Or something like a `fig`-like
|
||||
suggestion source, which would need to parse some files from the disk to
|
||||
generate the list of suggestions.
|
||||
|
||||
The easiest way to do this would be to provide a secondary UI element for
|
||||
prompting the user for input, doing the request in the background, then opening
|
||||
the UI later. However, that feels a little disjointed. Could we instead provide
|
||||
a more continuous experience?
|
||||
|
||||
The following is a proposal for using the Suggestions UI itself as the control
|
||||
to prompt the user for input.
|
||||
|
||||
```c++
|
||||
TerminalPage::SetUpSuggestionsUI()
|
||||
{
|
||||
const auto& asyncSource{ AsyncSuggestions() };
|
||||
|
||||
suggestionsUI.OnInputChanged({ asyncSource, AsyncSuggestions::InputChangedHandler});
|
||||
// In this example, we don't want the UI to filter item based on the input
|
||||
// string - the source has already determined the list of relevant matches.
|
||||
suggestionsUI.FilterByInput(false);
|
||||
|
||||
asyncSource.SuggestionsChanged([](const auto& newCommands){
|
||||
suggestionsUI.Loading(false);
|
||||
suggestionsUI.Commands(newCommands);
|
||||
})
|
||||
}
|
||||
|
||||
void AsyncSuggestions::InputChangedHandler(FilterChangedArgs args)
|
||||
{
|
||||
// kick off a trailing ThrottledFunc to do a new query
|
||||
_loadNewResults->Run(args.NewInputText());
|
||||
// If we get another request, we might want to cancel the pending throttled
|
||||
// func entirely, and start the timeout fresh. Just so that we only make a
|
||||
// query for the final string they type.
|
||||
|
||||
args.RequestLoading(true); // pass a boolean back up in the args, so that
|
||||
// the Suggestions UI can clear out the current commands, and start displaying an
|
||||
// indeterminate progress wheel.
|
||||
}
|
||||
```
|
||||
|
||||
That would basically _have_ to be special cased for this source, at least for
|
||||
now. We could refactor that later to beetter deal with extensions.
|
||||
|
||||
Let's make sure this would work for something `fig`-like, where the "prompt" is
|
||||
literally the prompt, what the user has already typed at the commandline.
|
||||
|
||||
After some discussion:
|
||||
* How do we differentiate the prompting version of the Suggestions UI from the
|
||||
filtering version?
|
||||
* The prompting version _doesn't_ filter results
|
||||
* Async modes wouldn't work with sync ones
|
||||
|
||||
## Resources
|
||||
|
||||
[comment]: # Be sure to add links to references, resources, footnotes, etc.
|
||||
|
||||
Prominent North Star references:
|
||||
* [Tasks]
|
||||
* [shell integration]
|
||||
* [shell-driven autocompletion]
|
||||
|
||||
### Footnotes
|
||||
|
||||
<a name="footnote-1"><a>[1]:
|
||||
|
||||
|
||||
[Fig]: https://github.com/withfig/autocomplete
|
||||
[Warp]: https://www.warp.dev/
|
||||
[workflows]: https://docs.warp.dev/features/workflows
|
||||
[also working on workflows]: https://fig.io/user-manual/workflows
|
||||
[winget script]: https://github.com/microsoft/PowerToys/blob/main/.github/workflows/package-submissions.yml
|
||||
[#1595]: https://github.com/microsoft/terminal/issues/1595
|
||||
[#7039]: https://github.com/microsoft/terminal/issues/7039
|
||||
[#3121]: https://github.com/microsoft/terminal/issues/3121
|
||||
[#10436]: https://github.com/microsoft/terminal/issues/10436
|
||||
[#12927]: https://github.com/microsoft/terminal/issues/12927
|
||||
[#12863]: https://github.com/microsoft/terminal/issues/12863
|
||||
[#5790]: https://github.com/microsoft/terminal/issues/5790
|
||||
[Terminal North Star]: ./Terminal-North-Star.md
|
||||
[#keep]: https://github.com/zadjii/keep
|
||||
[VsCode Tasks]: https://github.com/microsoft/terminal/blob/main/.vscode/tasks.json
|
||||
[Tasks]: ./Tasks.md
|
||||
[shell integration]: ./Shell-Integration-Marks.md
|
||||
|
||||
<!-- TODO! -->
|
||||
[shell-driven autocompletion]: ./Terminal-North-Star.md#Shell_autocompletion
|
||||
511
doc/specs/NorthStar/Tasks.md
Normal file
@@ -0,0 +1,511 @@
|
||||
---
|
||||
author: Mike Griese
|
||||
created on: 2022-08-22
|
||||
last updated: 2022-12-14
|
||||
issue id: 1595
|
||||
---
|
||||
|
||||
# Windows Terminal - Tasks
|
||||
|
||||
> **Note**:
|
||||
>
|
||||
> This is a draft document. This doc largely predates the creation of the
|
||||
> [Suggestions UI]. Many of the elements of this doc need to be updated to
|
||||
> reflect newer revisions to the Suggestions UI.
|
||||
>
|
||||
> It is included with the remainder of my North Star docs, because it was always
|
||||
> a part of that story. A future revision will come through to polish this doc
|
||||
> into a final form.
|
||||
|
||||
## Abstract
|
||||
|
||||
The command line is a highly powerful tool. However, its power is dependent on
|
||||
the user's knowledge of the specific commands, flags and parameters needed to
|
||||
perform tasks from the command-line. For simple everyday commands, this might not
|
||||
be so hard. For longer commands, or ones used less frequently, there's quite a
|
||||
bit of mental overhead trying to recall the exact syntax. For teams, it might be
|
||||
helpful to share these tasks with everyone on the project. The Terminal can be a
|
||||
aveneue by which complicated tasks can be remembered, shared, discovered and
|
||||
recalled by the user simply thinking **"what do I want to do"**, rather than
|
||||
"how do I do it".
|
||||
|
||||
## Background
|
||||
|
||||
|
||||
> **Note**:
|
||||
>
|
||||
> This largely builds off of work in the [Suggestions UI], for displaying these
|
||||
> tasks to the user. Make sure to read that spec first.
|
||||
|
||||
### Inspiration
|
||||
|
||||
The primordial version of this idea was probably [#keep] - a command-line tool I
|
||||
wrote for stashing long command-lines and directories, and recalling them with
|
||||
just a number. We've had many variations on this idea over the years - [#1595]
|
||||
was probably the first such request on the Terminal repo. ITerm2 also had [a
|
||||
similar feature](https://iterm2.com/images/CommandHistory.png). Theirs was more
|
||||
directly tied to shell integration (that menu is populated from commands that
|
||||
they know were run in the shell). In the absence of shell integration though, it
|
||||
should be able to save these commands to a menu manually.
|
||||
|
||||
It is hard to say that the ultimate vision here isn't partially inspired by the
|
||||
"[workflows]" of [Warp], or by [Fig]. These are modern tools that seek to
|
||||
augment the command-line experience, by making the command-line more
|
||||
approachable. Warp quite clearly has the same concept in "workflows" - scripts
|
||||
which the user can build and Warp (a Terminal emulator) can insert quickly. Fig,
|
||||
on the other hand, is more focused on just simplifing the command-line
|
||||
experience. Fig is more about providing additional metadata to the user as
|
||||
they're typing. They are [also working on workflows], so there's clearly quite a
|
||||
bit of ecosystem-wide demand for more discoverable command-line tooling.
|
||||
|
||||
Consider also [VsCode Tasks]. These are files which can be placed in the root of
|
||||
a workspace, and share common tasks between users of that workspace. They've got
|
||||
support for starting processes, with a set of args. These args can also be
|
||||
picked at runtime, and custom sets of arguments can be specified for individual
|
||||
arguments.
|
||||
|
||||
We've had verbatim feedback that developers already attempt to record useful
|
||||
commandlines in various different ways - in OneNotes, in shell scripts, in
|
||||
aliases. Sharing these Providing a unified way to easily store, browse, and use
|
||||
these command lines should be valuable to developers already doing this.
|
||||
Furthermore, developers often share these commands with the rest of their teams.
|
||||
A static file in their project containing commands for the whole team seems like
|
||||
a simple solution to this problem.
|
||||
|
||||
### User Stories
|
||||
|
||||
Story | Size | Description
|
||||
--|-----------|--
|
||||
A | 🐣 Crawl | Users can bring up a menu of command line tasks and quickly execute them
|
||||
B | 🐣 Crawl | Fragment apps can provide tasks to a users settings
|
||||
D | 🚶 Walk | The user can save commands straight to their settings with a `wt` command
|
||||
E | 🚶 Walk | Users can have different tasks enabled for different profiles(/shells?)
|
||||
F | 🏃♂️ Run | The terminal can automatically look for command fragments in the tree of the CWD
|
||||
H | 🏃♂️ Run | Tasks are filterable by tool (`git`, `docker`, etc.)
|
||||
I | 🏃♂️ Run | ? Tasks can both be atomic _tasks_ and longer scripts. Tasks can be sent straightaway to the Terminal, while the longer scripts are more for reference (ex: [winget script]).
|
||||
J | 🏃♂️ Run | Tasks can be filtered by text the user has already typed
|
||||
K | 🚀 Sprint | Tasks can have promptable sections of input
|
||||
L | 🚀 Sprint | Community tasks are hosted in a public GH repo
|
||||
M | 🚀 Sprint | A simple UX (either web or in Terminal) is exposed for interacting with public GH repo of tasks
|
||||
|
||||
### Elevator Pitch
|
||||
|
||||
The Terminal can remember long command-lines and display them with user-friendly
|
||||
descriptions of _what they actually do_. These tasks can be searched by intent,
|
||||
rather than the particular combination of flags. They can be shared with members
|
||||
of your team, so everyone has easy access to common tasks for a project.
|
||||
|
||||
### Why not just aliases / native script files?
|
||||
|
||||
Why not just take these tasks and put them into a shell alias? For longer tasks,
|
||||
why not just stick them in a `.ps1`/`.bat`/`.sh`/etc file? This is an option
|
||||
that's existed since the time immemorial. However, this still requires the user
|
||||
to remember that they've created these aliases/scripts, remember where they're
|
||||
stored, and remember how they work.
|
||||
|
||||
By providing a dedicated UI for these command-lines, they can always be at your
|
||||
fingertips. No need to remember what the alias for a particular command-line is -
|
||||
just look up what you want to do. Aliases and scripts are no longer scattered
|
||||
across `.bashrc`, `.bash_profile`, `.profile`, etc, they can all be stashed in
|
||||
the Terminal config, or in the project they're relevant to. By stashing them
|
||||
alongside the code, then anyone else coming to work on the code can have
|
||||
immediate access to useful sets of tasks.
|
||||
|
||||
Aliases have a tendency towards more experienced shell users. This proposal
|
||||
instead brings the power of these aliases and scripts right to the foreground,
|
||||
with a cross-shell mechanism of exposing them to even beginners. With fragment
|
||||
extensions, tools can bundle common workflows together with their application so
|
||||
the Terminal can automatically load them for the user.
|
||||
|
||||
### Community Tasks
|
||||
|
||||
_The big stretch version of this feature._
|
||||
|
||||
A community currated list of Tasks, for various tools. Stored publicly on a
|
||||
GitHub repo (a la the winget-pkgs repo). Users can submit tasks with
|
||||
descriptions of what the task does. The Terminal can plug into that repo
|
||||
automatically and fetch the latest community commands, immediately giving the
|
||||
user access to a wide bearth of common tasks.
|
||||
|
||||
## Business Justification
|
||||
|
||||
It will delight developers.
|
||||
|
||||
## Scenario Details
|
||||
|
||||
### UI/UX Design
|
||||
|
||||
For the most part, we'll be using the [Suggestions UI] to display tasks to the
|
||||
user. This is a text cursor-relative UI surface that can quickly display actions
|
||||
to the user, in the context of what they're working on.
|
||||
|
||||
The following are some examples from VsCode, Warp. These are meant to be
|
||||
illustrative of what these menus already look like in the wild:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
The following gif was a prototype of [shell-driven autocompletion]. This was
|
||||
more for suggestions from the shell, to the Terminal, but is helpful for
|
||||
visualizing what this might look like in the Windows Terminal.
|
||||
|
||||

|
||||
|
||||
A prototype of the recent commands UI, powered by shell integration:
|
||||
|
||||

|
||||
|
||||
A prototype of the tasks UI, powered by the user's settings:
|
||||
|
||||

|
||||
|
||||
A prototype of saving a command directly to the user's settings, then invoking it via the tasks UI
|
||||
|
||||

|
||||
|
||||
A prototype of reading tasks from the CWD
|
||||
|
||||

|
||||
|
||||
<hr> <!-- end of onepager -->
|
||||
|
||||
### Implementation Details
|
||||
|
||||
[TODO!]: # TODO! ---------------------------------------------------------------
|
||||
What info do we all want for these tasks?
|
||||
|
||||
* The text to send to the terminal
|
||||
- This might be multiple lines of text, with newlines in it
|
||||
* A friendly description of the command (different from the name?)
|
||||
* Sections of the input that are promptable, s.t. the user can save the command
|
||||
as a "template", and fill it in at runtime
|
||||
- ex: `nuget push -apikey az -source TerminalDependencies ${path-to-nuget-package}`
|
||||
- how do we specify these as promptable sections without stomping on all sorts
|
||||
of other shells syntaxes?
|
||||
* ~Maybe metadata about the command that it is used for? e.g. `git`, `docker`?~
|
||||
- This can probably be figured out from the first word of the command
|
||||
* What shell it should be used for?
|
||||
- CMD, pwsh seem like clear choices.
|
||||
- linux shells are trickier - not sure Terminal can always figure out what
|
||||
shell is actually running once it boots up WSL. Is it `bash`? `zsh`? `fish`?
|
||||
- Running `ssh me@some-linux.box` from a CMD shell would instantly blow up
|
||||
shell-specific commands
|
||||
- a profile with a command-line of `cmd /k doTheThing & ssh you-get-it`, again,
|
||||
would blow up the heuristic matching
|
||||
- So maybe this is a **bad idea**. Maybe we should just leave tasks as "this
|
||||
is just a string of text for the commandline, you gotta know which shell to
|
||||
use it with"
|
||||
|
||||
|
||||
#### Layering actions
|
||||
|
||||
* Fragments shouldn't be able to unbind actions from keys, _right_? TODO!
|
||||
* How do we differentiate multiple actions with the same name, but different descriptions? I think everything is keyed off on Name at this point. Maybe it should be off some hash.
|
||||
|
||||
#### Settings comparison
|
||||
|
||||
##### Simple task
|
||||
|
||||
```pwsh
|
||||
nuget push -apikey az -source TerminalDependencies ${path-to-nuget-package}
|
||||
```
|
||||
|
||||
The JSON is pretty strightforward:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"actions":
|
||||
[
|
||||
{
|
||||
"command":
|
||||
{
|
||||
"action": "sendInput",
|
||||
"input": "nuget push -apikey az -source TerminalDependencies ${path-to-nuget-package}"
|
||||
},
|
||||
"name": "Push to nuget feed",
|
||||
"description": "Used to upload a new dependency nuget to our internal nuget feed.",
|
||||
},
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The trick here is the `${path-to-nuget-package}`. PowerShell accepts the
|
||||
`${foo}` syntax to mean "a variable named `foo`". So us using that in our
|
||||
settings syntax would require users to escape our parsing, if they wanted to use
|
||||
that syntax in powershell.
|
||||
|
||||
##### Multiline script
|
||||
|
||||
For the [following script](https://gist.github.com/zadjii-msft/b598eebd6c5601328498e3e7acc581a7):
|
||||
|
||||
```pwsh
|
||||
$s=Invoke-GitHubGraphQlApi "query{organization(login:`"Microsoft`"){projectV2(number: 159) { id } } }"
|
||||
|
||||
$tasks = get-githubissue -Labels "Issue-Task" -state open
|
||||
$bugs = get-githubissue -Labels "Issue-Bug" -state open
|
||||
$issues = $tasks + $bugs
|
||||
|
||||
$issues | ? {$_.labels.Name -notcontains "Needs-Triage" } | ? { $_.milestone.title -Ne "Icebox ❄" } | ? type -Ne "PullRequest" | select -expand node_id | % {
|
||||
$resp = add-githubbetaprojectitem -projectnodeid $s.organization.projectV2.id -ContentNodeId $_ ;
|
||||
}
|
||||
```
|
||||
|
||||
The JSON is basically entirely unusable. Since JSON doesn't support multiline
|
||||
strings, then every line has to be joined to a single line, seperated by `\r\n`.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"actions":
|
||||
[
|
||||
{
|
||||
"command":
|
||||
{
|
||||
"action": "sendInput",
|
||||
"input": "$s=Invoke-GitHubGraphQlApi \"query{organization(login:`\"Microsoft`\"){projectV2(number: 159) { id } } }\"\r\n$tasks = get-githubissue -Labels \"Issue-Task\" -state open\r\n$bugs = get-githubissue -Labels \"Issue-Bug\" -state open\r\n$issues = $tasks + $bugs\r\n$issues | ? {$_.labels.Name -notcontains \"Needs-Triage\" } | ? { $_.milestone.title -Ne \"Icebox ❄\" } | ? type -Ne \"PullRequest\" | select -expand node_id | % {\r\n $resp = add-githubbetaprojectitem -projectnodeid $s.organization.projectV2.id -ContentNodeId $_ ;\r\n}"
|
||||
},
|
||||
"name": "Upload to project board",
|
||||
"description": "Sync all our issues and bugs that have been triaged and are actually on the backlog to the big-ol project",
|
||||
"shell": "pwsh",
|
||||
},
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
This version instead adds a `commands` parameter to `sendInput`, with the
|
||||
implication that each of these should be sent with <kbd>enter</kbd> between
|
||||
them.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"actions":
|
||||
[
|
||||
{
|
||||
"command":
|
||||
{
|
||||
"action": "sendInput",
|
||||
"commands":
|
||||
[
|
||||
"$s=Invoke-GitHubGraphQlApi \"query{organization(login:`\"Microsoft`\"){projectV2(number: 159) { id } } }\"",
|
||||
"$tasks = get-githubissue -Labels \"Issue-Task\" -state open",
|
||||
"$bugs = get-githubissue -Labels \"Issue-Bug\" -state open",
|
||||
"$issues = $tasks + $bugs",
|
||||
"$issues | ? {$_.labels.Name -notcontains \"Needs-Triage\" } | ? { $_.milestone.title -Ne \"Icebox ❄\" } | ? type -Ne \"PullRequest\" | select -expand node_id | % {",
|
||||
" $resp = add-githubbetaprojectitem -projectnodeid $s.organization.projectV2.id -ContentNodeId $_ ;",
|
||||
"}",
|
||||
""
|
||||
]
|
||||
},
|
||||
"name": "Upload to project board",
|
||||
"description": "Sync all our issues and bugs that have been triaged and are actually on the backlog to the big-ol project",
|
||||
"shell": "pwsh",
|
||||
},
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Still gross, but at least maintainable.
|
||||
|
||||
YAML or something else might make more sense here.
|
||||
|
||||
#### Per-project tasks(`.wt.json`?)
|
||||
|
||||
In addition to tasks stored in the user's `settings.json`, we also want to provide users with a way to store commands relative to their projects. These can be checked in to source control repositories alongside code. When the
|
||||
|
||||
[TODO!]: # TODO! ---------------------------------------------------------------
|
||||
How do we want to represent this?
|
||||
* snippets of JSON with `sendInput` actions is easy for the Terminal to understand.
|
||||
* They are probably not that user friendly outside of Windows Terminal.
|
||||
Consider, users are gonna stick these JSON blobs in the root of their repo.
|
||||
Theoretically other tools should use them too. Is our json actions syntax what
|
||||
we'd really want to saddle people with?
|
||||
* JSON is not super friendly to command-lines - since everything's gotta be
|
||||
encapsulated as a string, then you've got to escape characters (esp quotes
|
||||
`"`) for JSON strings
|
||||
- on the other hand, embedding tabs `\t`, newlines `\r`, escape characters, is fairly
|
||||
straightforward.
|
||||
* Anything that's not JSON blobs will require a lot of spec'ing to come up with
|
||||
a standard, and more expensive implementation Terminal-side
|
||||
* For what it is worth, [Warp] uses .yaml files for their "workflows"[[1](#footnote-1)]. As an
|
||||
example, see
|
||||
[`clone_all_repos_in_org.yaml`](https://github.com/warpdotdev/workflows/blob/main/specs/git/clone_all_repos_in_org.yaml)
|
||||
* Yaml does have the neat benefit of not needing too much command-line escaping
|
||||
* How do we want this to play with longer workflows? E.g. our familiar [winget script]
|
||||
* Markdown [Notebooks] seems relevant here, but probably not best for annotating
|
||||
specific commands that we want the Terminal to pick up on. A
|
||||
`.terminal-tasks.md` seems simple enough to look for, but embedding metadata
|
||||
about which shell, what text should be prompted for, descriptions, that does
|
||||
seem harder.
|
||||
##### File name
|
||||
|
||||
In my original prototype, I used `.wt.json` as the filename for a
|
||||
filesystem-relative commands. This seems to me like a bit of a silly file name.
|
||||
Node proejcts can store various aliases for commands in their `package.json`
|
||||
file. Perhaps the `.` prefix isn't necessary. Would `wt.json` be too silly?
|
||||
|
||||
[TODO!]: # TODO! ---------------------------------------------------------------
|
||||
|
||||
##### Save to project on the commandline
|
||||
|
||||
As an example implementation, see [these
|
||||
commits](https://github.com/microsoft/terminal/compare/6f5b9fb...1cde67ac466e19394eea1eb3a41405513d160a6f).
|
||||
|
||||
`wt save --local commandline...`?
|
||||
`wt save --settings commandline...`?
|
||||
`wt save --file [path to file] commandline...`?
|
||||
|
||||
##### Shell escaping commandlines
|
||||
|
||||
Something like `wt save ping 8.8.8.8 > foo.txt` isn't going to work the way
|
||||
users want. The shell is gonna get the first crack at parsing that commandline,
|
||||
and is going to try and redirect the _output of `wt`_ to `foo.txt`.
|
||||
|
||||
<!-- This is something I encountered in #keep constantly -->
|
||||
|
||||
[TODO!]: # TODO! ---------------------------------------------------------------
|
||||
|
||||
Is there a better way to escape, like `wt save "ping 8.8.8.8 > foo.txt"` or something?
|
||||
|
||||
#### Community tasks from extensions
|
||||
|
||||
[TODO!]: # TODO! ---------------------------------------------------------------
|
||||
|
||||
Fragment extensions. Case in point: https://github.com/abduvik/just-enough-series/tree/master/courses/docker+docker-compose
|
||||
|
||||
|
||||
## Tenents
|
||||
|
||||
<table>
|
||||
|
||||
<tr><td><strong>Compatibility</strong></td><td>
|
||||
|
||||
[comment]: # Will the proposed change break existing code/behaviors? If so, how, and is the breaking change "worth it"?
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Accessibility</strong></td><td>
|
||||
|
||||
[comment]: # TODO!
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Sustainability</strong></td><td>
|
||||
|
||||
[comment]: # TODO!
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Localization</strong></td><td>
|
||||
|
||||
[comment]: # TODO!
|
||||
|
||||
Mildly worried here about the potential for community-driven tasks to have
|
||||
non-localized descriptions. We may need to accept a `description:{ en-us:"",
|
||||
pt-br:"", ...}`-style map of language->string descriptions.
|
||||
|
||||
</td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
[comment]: # If there are any other potential issues, make sure to include them here.
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### 🐣 Crawl
|
||||
* [ ] The command palette needs to be able to display both the command name and a comment?
|
||||
- This will need to be reconciled with [#7039], which tracks displaying non-localized names in the command palette
|
||||
* [ ] The command palette is refactored to allow it to interact as the Tasks panel
|
||||
* [ ] [#1595] An action for opening the tasks panel, filled with all `sendInput` commands
|
||||
* [ ] Fragments can add **actions** to a user's settings
|
||||
* [ ] [#10436] Users can manage all their fragments extensions directly in the Settings UI
|
||||
|
||||
### 🚶 Walk
|
||||
* [ ] The terminal can look for a settings file of tasks in a profile's `startingDirectory`
|
||||
* [ ] [#5790] - profile specific actions
|
||||
* [ ] [#12927]
|
||||
* [ ] [#12857] Ability to save selected text as a `sendInput` action
|
||||
|
||||
### 🏃♂️ Run
|
||||
* [ ] When the user `cd`s to a directory (with shell integration enabled), the terminal can load the tasks from that directory tree
|
||||
- Kinda dependent on [#5790] and fragment **actions**, so we understand how they should be layered.
|
||||
* [ ] Fork of [#12927] - promptable sections can accept a command to dynamically populate options
|
||||
|
||||
### 🚀 Sprint
|
||||
* [ ]
|
||||
* [ ]
|
||||
|
||||
|
||||
## Conclusion
|
||||
|
||||
[comment]: # Of the above proposals, which should we decide on, and why?
|
||||
|
||||
|
||||
### Future Considerations
|
||||
|
||||
[comment]: # Are there other future features planned that might affect the current design of this setting? The team can help with this section during the review.
|
||||
|
||||
This "tasks panel" is a part of a much bigger picture. We fully intend to reuse
|
||||
this for the shell-driven autocompletions that xterm.js (read:VsCode) and
|
||||
PowerShell are working on (vaguely tracked by [#3121]).
|
||||
|
||||
Longer workflows might be best exposed as [Notebooks].
|
||||
|
||||
## Resources
|
||||
|
||||
[comment]: # Be sure to add links to references, resources, footnotes, etc.
|
||||
|
||||
|
||||
### Footnotes
|
||||
|
||||
<a name="footnote-1"><a>[1]: We may want to straight up just seemlessly support that syntax. The commands are all licensed under Apache 2.0. Converting them to WT-compatible json is fairly trivial:
|
||||
|
||||
```python
|
||||
import yaml
|
||||
import json
|
||||
|
||||
def parse_yaml_files(directory):
|
||||
json_data = {}
|
||||
json_data["name"] = f"{directory} tasks..."
|
||||
json_data["commands"] = []
|
||||
|
||||
for filename in os.listdir(directory):
|
||||
if filename.endswith(".yaml") or filename.endswith(".yml"):
|
||||
file_path = os.path.join(directory, filename)
|
||||
with open(file_path, 'r') as file:
|
||||
try:
|
||||
yaml_data = yaml.safe_load(file)
|
||||
new_obj = {}
|
||||
command = {}
|
||||
command["input"] = yaml_data["command"]
|
||||
command["action"] ="sendInput"
|
||||
|
||||
new_obj["command"]=command
|
||||
new_obj["name"] = yaml_data["name"]
|
||||
new_obj["description"] = yaml_data["description"]
|
||||
json_data["commands"].append(new_obj)
|
||||
except yaml.YAMLError as e:
|
||||
print(f"Error parsing {filename}: {e}")
|
||||
json.dump(data, file, indent=4)
|
||||
```
|
||||
|
||||
|
||||
[Fig]: https://github.com/withfig/autocomplete
|
||||
[Warp]: https://www.warp.dev/
|
||||
[workflows]: https://docs.warp.dev/features/workflows
|
||||
[also working on workflows]: https://fig.io/user-manual/workflows
|
||||
[winget script]: https://github.com/microsoft/PowerToys/blob/main/.github/workflows/package-submissions.yml
|
||||
[#1595]: https://github.com/microsoft/terminal/issues/1595
|
||||
[#7039]: https://github.com/microsoft/terminal/issues/7039
|
||||
[#3121]: https://github.com/microsoft/terminal/issues/3121
|
||||
[#10436]: https://github.com/microsoft/terminal/issues/10436
|
||||
[#12927]: https://github.com/microsoft/terminal/issues/12927
|
||||
[#12857]: https://github.com/microsoft/terminal/issues/12857
|
||||
[#5790]: https://github.com/microsoft/terminal/issues/5790
|
||||
[Notebooks]: ./Markdown%20Notebooks.md
|
||||
[Terminal North Star]: ./Terminal-North-Star.md
|
||||
[#keep]: https://github.com/zadjii/keep
|
||||
[VsCode Tasks]: https://github.com/microsoft/terminal/blob/main/.vscode/tasks.json
|
||||
|
||||
<!-- TODO! -->
|
||||
[shell-driven autocompletion]: ./Terminal-North-Star.md#Shell_autocompletion
|
||||
|
||||
499
doc/specs/NorthStar/Terminal-North-Star.md
Normal file
@@ -0,0 +1,499 @@
|
||||
---
|
||||
author: Mike Griese
|
||||
created on: 2022-07-01
|
||||
last updated: 2023-03-27
|
||||
issue id: n/a
|
||||
---
|
||||
|
||||
# Windows Terminal - Command Line North Star
|
||||
|
||||
## Abstract
|
||||
|
||||
The terminal is a critical component of Windows. It is the primary interface for
|
||||
developers, system administrators, and power users. In recent years, there's
|
||||
been renewed enthusiasm for the command-line environment, and new competitors on
|
||||
the scene are pushing the limits of what terminals can be on other platfoms. As
|
||||
a result, Microsoft recognizes the need to invest in pushing the boundaries of
|
||||
terminals to enhance the user experience and remain competitive. This document
|
||||
outlines the long-term strategic enhancements planned for the Windows Terminal,
|
||||
with the goal of creating a more powerful and feature-rich terminal experience
|
||||
that meets the evolving needs of our users.
|
||||
|
||||
These efforts should be considered in addition to other table-stakes
|
||||
functionality. Things like improving UTF-8 support, tearing tabs out of the
|
||||
window, continued expansion of VT sequence support, continued performance
|
||||
improvements, and partner team asks are still important priorities. They are not
|
||||
to be considered "instead of" this work, but as a fundamental baseline to this
|
||||
effort. These scenarios listed below are "in addition to" the Terminal
|
||||
fundamentals. Without continued investment in the fundamentals, then the north
|
||||
star features here will serve only to polish a turd. Focus on fundamentals and
|
||||
existing known priorities remains important to avoid mistrust generated by
|
||||
questions like _"Why would they add this feature instead of working on
|
||||
{fundamental issue that's existed for years}"_.
|
||||
|
||||
## Background
|
||||
|
||||
This document is a broad architectural overview of proposed features for the
|
||||
Terminal. None of the scenarios listed here are described in particular detail.
|
||||
Rather, the intent is to show a broad overview of how these elements work with
|
||||
one another. For more detailed individual specs, refer to the following docs:
|
||||
|
||||
* [Notebooks]
|
||||
* [Tasks]
|
||||
* [Suggestions UI]
|
||||
* [Copilot]
|
||||
* [Shell Integration]
|
||||
|
||||
### Context
|
||||
|
||||
This document was originally authored in 2022, in the midst of the ongoing
|
||||
global COVID-19 pandemic. At the time, one of the key focuses of the tech
|
||||
industry was ways to empower remote collaboration. The reader will find a number
|
||||
of scenarios that are heavily influenced by this. While the pandemic has begun
|
||||
to recede, and companies are returning to the office in greater numbers, it
|
||||
remains an important mission to support collaboration in whatever form it might
|
||||
take.
|
||||
|
||||
Subsequently, recent advances in large language models have made "AI"
|
||||
experiences more reliable and convincing. This has created the opportunity to
|
||||
build new experiences powered by these "AI" models. Further additions were made
|
||||
to this doc to reflect these advancements. While these language models can
|
||||
provide powerful new experiences, it remains important that we continue to
|
||||
prioritize ["human intelligence", enhanced by
|
||||
AI](#addenda-human-intelligence-and-artificial-intelligence).
|
||||
|
||||
## Pillars
|
||||
|
||||
This document focuses on a few key scenarios which are more revolutionary
|
||||
feature adds rather than "table stakes" features the Terminal has been focused
|
||||
on for the last few years. These are grouped into the following pillars:
|
||||
* Command-line tooling is easier to discover and use
|
||||
* The Terminal advances the command-line shell UX
|
||||
* The Terminal enables new CLI experiences
|
||||
* The Terminal enables powerful collaboration
|
||||
* The Terminal provides a first-class accesibility experience
|
||||
|
||||
### Command-line tooling is easier to discover and use
|
||||
|
||||
(_The Terminal makes my existing command-line workflow better_)
|
||||
|
||||
* AI enables users to describe what they want to do with the commandline, rather
|
||||
than relying on user's knowledge of specific commands and arguments. <!-- D -->
|
||||
* AI can quickly provide explanations of what's happening - error messages and
|
||||
command lines can be explained without needing to leave the context of the
|
||||
Terminal. <!-- D -->
|
||||
* Markdown integration for quickly running blocks of commands from existing
|
||||
markdown documentation <!-- E -->
|
||||
* Recording the contents of the Terminal output to a file is simple and
|
||||
optimized for sharing on GitHub <!-- F -->
|
||||
* Searching for errors is as simple as right clicking on some selected text
|
||||
<!-- * Customizations to command-line tools is easy to discover and install ~The
|
||||
Terminal exposes a curated list of ways to customize your command-line
|
||||
tooling, and easily install~ -->
|
||||
<!-- * Working across multiple machines is made easy
|
||||
* Automatic detection of saved ssh sessions and Hyper-V VMs makes connecting simple
|
||||
* Broadcasting input to multiple tabs and panes makes exectuting the same
|
||||
commands in multiple environments easy -->
|
||||
|
||||
### The Terminal advances the command-line shell UX
|
||||
|
||||
(_Things the Terminal can do for the user, to provide a modern experience_)
|
||||
|
||||
* Prompts, command-lines, output are marked semantically <!-- A -->
|
||||
* Icons in the gutter to indicate if a command succeeded, had an error, or was canceled <!-- A -->
|
||||
* Icons in the gutter can be used to quickly: <!-- A -->
|
||||
* re-run the command
|
||||
* copy the output to the clipboard
|
||||
* Save the command line as an action for later.
|
||||
* Horizontal markers can be used to subtly indicate the separation between different commands <!-- A -->
|
||||
* The terminal remembers command-lines ("Tasks") <!-- B -->
|
||||
* Users can share complicated command-lines with one another for easy access
|
||||
* Errors and warnings in output can be automatically identified and jumped to <!-- A -->
|
||||
|
||||
### The Terminal enables new CLI experiences
|
||||
|
||||
(_New experiences that CLI applications can deliver for users_)
|
||||
|
||||
* CLI apps can drive rich auto-complete suggestions presented by the Terminal <!-- C -->
|
||||
* CLI applications can send Windows notifications via the Terminal
|
||||
* CLI apps can display images in the Terminal (sixel)
|
||||
* CLI apps can provide clickable suggestions <!-- ala https://github.com/microsoft/terminal/issues/5001#issuecomment-1246562464 -->
|
||||
|
||||
### The Terminal enables powerful collaboration
|
||||
|
||||
* LiveShare - share a terminal window with a member of your team for realtime collaboration
|
||||
* Useful commands and notes can be shared automatically across members of your team
|
||||
|
||||
### The Terminal provides a first-class accesibility experience
|
||||
* Terminals can describe their contents prcatically to assistive technologies, through a new "terminal" UIA pattern <!-- (word delims, alt/main buffer) -->
|
||||
* CLI apps can help direct the behavior of screen readers, via new VT sequences
|
||||
* High Contrast Mode within the Terminal itself adjusts text colors to make sure all CLI apps are visible.
|
||||
* CLI apps can provide auto-completions which the Terminal can use to present rich details to screen readers <!-- C -->
|
||||
|
||||
## Business Justification
|
||||
|
||||
**"The command line works best on Windows"**. Your shells, your tools, don't
|
||||
just work, but work _best_ on Windows, enabled by enhancements provided by the
|
||||
Windows Terminal.
|
||||
|
||||
The Terminal remains the primary dev environment for developers of all sorts of
|
||||
toolchains. It remains the most familiar experience for users who are
|
||||
considering Windows over MacOS or linux.
|
||||
|
||||
The terminal is a deeply personal app. Users spend a lot of time adjusting their
|
||||
terminal of choice to fit their needs. Once users find one they like, they're
|
||||
unlikely to change. Developers are highly opinionated. One-size-fits-all
|
||||
solutions are typically not good enough. Every developer has their own opinions
|
||||
on how they'd like their keybindings, what colors they'd like to use, what shell
|
||||
or editor is best. By providing the most customizable terminal possible, we
|
||||
address the largest possible cohort of developers. Giving developers knobs for
|
||||
every possible setting removes any incentive for developers to seek out an
|
||||
alternative.
|
||||
|
||||
There's plenty of interest in reinvigorating the command line experience.
|
||||
Applications like [Fig] and [Warp] demonstrate the desire for not just incremental
|
||||
improvements to the user experience of the command-line, but wholesale
|
||||
reimagining. To date, the Windows Terminal has managed to meet current
|
||||
expectations of terminals on other platforms (and remains short of competitiors,
|
||||
like ITerm2, in many regards).
|
||||
|
||||
For some market comparison - Warp raised $26M of funding, and Fig raised $2.4M.
|
||||
That's 28 million combined dollars of investment into the command-line
|
||||
experience, which at this point was only produced tooling for MacOS.
|
||||
|
||||
These "Hero scenarios" create a compelling differentiating experience on
|
||||
Windows. They position Windows as the premier command line development
|
||||
experience. By providing the best-in-class developer experience, we seek to
|
||||
provide an ecosystem where developers would be reluctant to choose another
|
||||
platform. Scenarios here help create an ecosystem of features surrounding the
|
||||
Terminal, features which aren't immediately reproducible on other platforms.
|
||||
|
||||
## Scenario Details
|
||||
|
||||
Above is listed a high-level description of some user stories. This section
|
||||
provides a deeper drill into some of the above areas.
|
||||
|
||||
### Scenario A: More powerful commanding powered by advanced shell integration
|
||||
|
||||
The Terminal provides a way for command line shells to semantically mark parts
|
||||
of the command-line output. By marking up parts of the output, the Terminal can
|
||||
richer experiences. The Terminal will know where each command starts and stops,
|
||||
what the actual command was and what the output of that command is. This allows
|
||||
the terminal to expose quick actions for:
|
||||
* Quickly navigating the history by scrolling between commands
|
||||
* Re-running a previous command in the history
|
||||
* Copying all the output of a single command-line
|
||||
* A visual indicator to separate out one command-line from the next, for quicker
|
||||
mental parsing of the output of the command-line.
|
||||
* Collapsing the output of a command, as to reduce noise
|
||||
* Visual indicators that highlight commands that succeeded or failed.
|
||||
* Jumping to previously used directories
|
||||
|
||||
Enabling these features requires that the shell co-operates with the terminal,
|
||||
to tell the Terminal about these parts of the output. Typically, this would
|
||||
require complicated customizations that the user would have to install manually
|
||||
into their shell's configuration. We will provide sample snippets that will
|
||||
enable this functionality for a variety of shells. However, VsCode has
|
||||
experimented with functionality to automatically insert this functionality into
|
||||
shells it's familiar with. This has been reasonably successful to date, so it
|
||||
provides a valuable guide for a way the Terminal could do the same. This would
|
||||
enable the Terminal to have a simple setting that would automatically enable
|
||||
powerful features for the user's shell, without them needing to configure their
|
||||
shell at all.
|
||||
|
||||
### Scenario B: The Terminal knows and remembers complicated command lines, so I don't have to
|
||||
|
||||
The command line experience is often filled with running a number of commands
|
||||
with some frequency, but also a small number of commands infrequently.
|
||||
Command-line options and parameters are not easily discoverable, forcing
|
||||
developers to constantly refer back to documentation. Team members often need to
|
||||
use the same command-lines within the scope of their project, but need to share
|
||||
them amongst the team manually.
|
||||
|
||||
Users might run a series of commands like `git commit -m "..."`, `git push`
|
||||
multiple times an hour. For these kinds of scenarios, it might be helpful if the
|
||||
commands were easily accessible with a single keystroke, rather than typing them
|
||||
out every single time.
|
||||
|
||||
Other commands the user might run once a month, or even less frequently. Some
|
||||
projects might have a very complicated command-line for pushing an updated
|
||||
package to nuget, which the developer only needs to run once every few months.
|
||||
That kind of infrecuency leads to the developer needing to look up the command
|
||||
from their notes every time, if the notes even exist. Consider a single
|
||||
developer working on the OS repo, who might work in a variety of projects within
|
||||
that repo. They might need to bounce around between projects every couple
|
||||
months. Each project might have its own build scripts, test deployment scripts,
|
||||
and output files that are interesting. Without good notes, it would be easy for
|
||||
the developer to simply forget the commands for a single project in the months
|
||||
between working on it.
|
||||
|
||||
Similarly, there are scenarios where one member of a team might author a
|
||||
complicated command-line for doing something in their project. ~As an example -
|
||||
sometimes a local clone of the Terminal repo can get into a broken state where a
|
||||
user needs to delete a couple `.xbf` files, but just blindly deleting them all
|
||||
would force a full rebuild. I've got a handy script that just deletes the bad
|
||||
ones, but any time someone on the team needs this they need to go where? Our
|
||||
wiki? Our OneNote? Somewhere deep in the Teams chat history?~ Now, that
|
||||
developer needs to share it manually with the rest of the team. The team would
|
||||
need to have a well documented way of sharing command-lines between members - a
|
||||
practice that surely not every team has mastered.
|
||||
|
||||
Furthermore, there is often a discommect between what the user wants to do, and
|
||||
what the user needs to type at a command-line. Consider "I need to compress this
|
||||
directory to a `tar.gz` archive". The user knows what they want to do, but they
|
||||
now need to go pull up a man page or Stack Overflow to figure out how to do what
|
||||
they want.
|
||||
|
||||
Enter **[Tasks]**. These are sets of command-lines that can quickly
|
||||
be saved, shared, with descriptive names and longer descriptions. They can be
|
||||
grouped - by application, by team, by whatever the user chooses. Descriptive
|
||||
names allow users to quickly navigate the menu looking for the thing they want
|
||||
to do. When shared to your team{repo/project/?}, they automatically show up for
|
||||
other team members.
|
||||
|
||||
After running a command in your shell that you'd like to save for later, all it
|
||||
takes is a simple <kbd>↑</kbd>, <kbd>Home</kbd>, `wt save `, and the terminal will stash that
|
||||
command-line for later use.
|
||||
|
||||
Tasks are powered by the [Suggestions UI].
|
||||
|
||||
### Scenario C: The Terminal enables powerful autocompletion suggestions, driven by the shell
|
||||
|
||||
Shells are already powerful tools in their own right. Anyone who's used a shell
|
||||
more than a few times is probably familiar with shells' ability to tab-complete
|
||||
paths at the prompt. Most modern shells provide elaborate mechanisms for command
|
||||
line apps to extend their tab completion, so that subcommands, arguments, and
|
||||
parameter values can also be tab-completed. However, these options are not
|
||||
usually highly discoverable - the completions the shell might provide still
|
||||
assume the user hast started typing the correct value.
|
||||
|
||||
PowerShell has started to attempt to mitigate this with its MenuComplete, which
|
||||
outputs possible suggestions beneath the prompt inline with other commandline
|
||||
output. Other shells (like `fish`, `zsh`) have similar extensions as well.
|
||||
However, everyone needs to implement support for these menus themselves.
|
||||
|
||||
One major downside of this is that these menus are very hard for screen readers
|
||||
to interact with. The mechanism used to redraw parts of the "menu" to indicate
|
||||
the selection changed usually means that a screen reader will re-read the entire
|
||||
menu of suggestions. Furthermore, there's no way for a screen reader to indicate
|
||||
the purpose of this text.
|
||||
|
||||
To remedy this, we'll implement a new VT escape sequence. This sequence can be
|
||||
used by a CLI application to tell the terminal to render a menu of suggestions.
|
||||
This will enable the Terminal to present all the options the shell knows about
|
||||
to the user in a quickly filterable menu. By being a dedicated control within
|
||||
the Terminal, the Terminal can provide unique UIA patterns for this menu to make
|
||||
it clear to screen readers what is happening.
|
||||
|
||||
By authoring this as a open VT standard, we enable not just Terminal and
|
||||
PowerShell to use this to communicate with one another, but any combination of
|
||||
terminal and CLI application. The ecosystem works best when we all work
|
||||
together. Prototypes for this protocol and menu were started by the VsCode
|
||||
terminal's team. Both VsCode and Terminal can reuse the same plumbing, as well
|
||||
as `xterm`, `alacritty`, `gnome-terminal` or anything else out there.
|
||||
|
||||
Shell autocompletion is powered by the [Suggestions UI].
|
||||
|
||||
### Scenario D: AI powered commandline experience
|
||||
|
||||
Recent advancements in large language models have created a rapidy evolving
|
||||
ecosystem of AI-enhanced experiences. These models are highly effective at
|
||||
synthesizing responses to natural language questions. The command line is no
|
||||
different, and is an environment ripe for innovation.
|
||||
|
||||
The commandline is an environment filled with verbose, often esoteric output.
|
||||
This is a place where AI might be valuable for translating those error messages
|
||||
to simple language explaining what went wrong.
|
||||
|
||||
In the reverse, translating natural language descriptions of what the user wants
|
||||
to do into actual commands is a well-trodden path for innovation. In only the
|
||||
few months since the broad rollout of gpt-3 and Github Copilot, already there
|
||||
are many examples of "natural language to commandline". There's already [Codex
|
||||
CLI], [Copilot CLI], and [Warp AI] all working on natural language experiences
|
||||
in the terminal.
|
||||
|
||||
These are just two key scenarios we're targeting. This is a space where the
|
||||
current pace of innovation is very rapid. The landscape of what models are
|
||||
available and what they are capable is evolving weekly. Staying on top of these
|
||||
innovations and finding ways to integrate these experiences into the Terminal
|
||||
will be an important part of our strategy moving forward.
|
||||
|
||||
Crucially, we'll want to create a pluggable infrastructure for these AI
|
||||
features. This will enable developers to pick and choose whatever model they
|
||||
prefer. The Terminal will ask simple, abstract queries from these plugins, and
|
||||
leave the prompting implementation to the actual plugin author themselves. This
|
||||
will allow the greatest flexibility for experimentation on both the part of the
|
||||
Terminal and the model backend itself. The Terminal won't need to concern itself
|
||||
with the raw prompt construction. The plugin authors will be able to experiment
|
||||
and fine-tune their prompts to get the best results.
|
||||
|
||||
This scenario is discussed in greater detail in [Copilot] and the specs in that
|
||||
directory.
|
||||
|
||||
### Scenario E: Markdown notebooks
|
||||
|
||||
Notebooks have risen to popularity in recent years as a way of combining both
|
||||
code and documentation in a single experience. They enable users to seamlessly
|
||||
write code, and execute it to see the output, write documentation on the code,
|
||||
and share that with others. However, there's not really anything like notebooks
|
||||
for generic commandline experiences.
|
||||
|
||||
There are, however, markdown files. Markdown has become a bit of a lingua franca
|
||||
of the developer experience. It's used prominently on GitHub - the "homepage" of
|
||||
any repo on GitHub is now typically a markdown file. This file will have all
|
||||
sorts of documentation, and notably these READMEs are often filled with commands
|
||||
that one can execute for this project. Downloading, installing its dependencies,
|
||||
building and running the project, etc, all commands that are already listed
|
||||
today in READMEs across the world.
|
||||
|
||||
It would be a major convenience for users to be able to just load a pre-rendered
|
||||
markdown file directly into their terminal windows. These files already include
|
||||
marked blocks of code which identify sets of commands for the command line. It
|
||||
should be as simple as clicking a button to run these commands in the Terminal,
|
||||
or even to run a whole file worth of commands automatically.
|
||||
|
||||
This scenario is discussed in greater detail in [Notebooks] and the specs in that
|
||||
directory.
|
||||
|
||||
<!--
|
||||
|
||||
Omitted from North Star - these are valuable features, but not pushing the
|
||||
boundary of what's possible by terminal emulators today
|
||||
|
||||
### Scenario W: Enhancements to remote connections
|
||||
|
||||
* Dynamic profiles from `.sshconfig`
|
||||
* [#12773] Dynamic profiles from Hyper-V VMs
|
||||
* Broadcast Input Mode
|
||||
* -->
|
||||
|
||||
### Scenario F: Quick Terminal recording
|
||||
|
||||
Case in point: [Textualize]. This is a website that's loaded with recordings of
|
||||
the terminal doing something cool. And they're all using **macOS**. That
|
||||
reinforces the precedent that cool command line experiences are being developed
|
||||
for _not Windows_.
|
||||
|
||||
Gifs that could easily be shared in READMEs on GitHub, where developers
|
||||
already frequently use recordings of their terminal to demonstrate how their
|
||||
tools work. By including not just the body of the Terminal, but the frame
|
||||
itself, it's immediately apparent to someone watching that _this is the Windows
|
||||
Terminal_. The observer knows that this gif was recoded on Windows, and that the
|
||||
maintainer built this tool on Windows (and ideally, for Windows). By making the
|
||||
experience as quick and painless as possible, developers could quickly create
|
||||
engaging documentation for their users.
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
Below are some screenshots of similar features from other apps. Featured here prominently are iTerm2, Warp, and VsCode's own xterm.js.
|
||||
|
||||
### Prior art
|
||||
#### Workflows, suggestions
|
||||
|
||||

|
||||

|
||||
|
||||
#### Shell autocompletion
|
||||
|
||||

|
||||

|
||||
|
||||
#### Notebooks
|
||||
|
||||

|
||||
|
||||
## Conclusion
|
||||
|
||||
Investing engineering resources into pushing the boundaries of the Terminal is a
|
||||
critical strategy that will benefit Windows and Microsoft as a whole. By
|
||||
providing new user experiences and capabilities, we can boost the entire Windows
|
||||
ecosystem. A more powerful terminal will attract developers to build new and
|
||||
innovative applications for Windows, making the platform more vibrant and
|
||||
exciting. By leveraging our connected services via Visual Studio, GitHub, and AI
|
||||
we can create a more compelling and attractive platform to better serve the
|
||||
needs of our users. This robust developer experience will help Windows stand out
|
||||
as the best platform for developers and system administrators.
|
||||
|
||||
<!-- ### Future Considerations
|
||||
|
||||
[comment]: # Are there other future features planned that might affect the current design of this setting? The team can help with this section during the review. -->
|
||||
|
||||
## Resources
|
||||
|
||||
This architecture docs is intentionally a 10000ft overview. For more detailed docs on these scenarios, see the following docs:
|
||||
|
||||
* [Notebooks]
|
||||
* [Tasks]
|
||||
* [Suggestions UI]
|
||||
* [Copilot]
|
||||
* [Shell Integration]
|
||||
|
||||
## Addenda: Human Intelligence and Artificial Intelligence
|
||||
|
||||
An ongoing theme within the tech industry is how AI can empower user with new
|
||||
experiences. I think it is important to remember that Human Intelligence should
|
||||
always be relied upon first and foremost. AI can be a useful backstop for human
|
||||
intelligence, but it is no replacement. Whenever possible, we should rely on the
|
||||
user's own knowledge and expertise, before using AI for suggestions.
|
||||
|
||||
As an example: Tasks and AI Command Suggestions. Tasks are usually a better
|
||||
answer for the user - they represent the user has already found the answer of
|
||||
how to do something. They've already evaluated that task as the correct solution
|
||||
to the problem. Tasks that are shared with the rest of your team are similar - a
|
||||
team mate has already found the right solution for a problem within your
|
||||
project. Their solution is going to be more reliable than asking a language
|
||||
model to synthesize a result.
|
||||
|
||||
AI can be used to enhance human intelligence, when at the limits of the user's
|
||||
knowledge. Large language models can be used to produce results that are
|
||||
sometimes correct and often incorrect. They're best at synthesizing results the
|
||||
user could have otherwise found in a web search or in documentation. Providing
|
||||
immediate access to those answers helps the user stay in the flow. For more
|
||||
challenging queries that the model may not have exact, correct responses for,
|
||||
even wrong responses can be valuable. They can help to inspire human creativity.
|
||||
A wrong response might help point the user in the direction of the correct
|
||||
solution.
|
||||
|
||||
## Addenda: Command-line North Star
|
||||
|
||||
This document is solely Terminal-oriented. Everything in here is features that
|
||||
the Terminal can provide to improve the developer experience on Windows. What's
|
||||
not covered at all are ways we can improve the commandline tooling itself on
|
||||
Windows. Things like adding more built-in commandline utilities. Updating
|
||||
existing ones (`tar`, `curl`). There's no discussion of improvements to our
|
||||
shell offerings (`cmd` or PowerShell). This is another valuable discussion we
|
||||
should have, but I feel it warrants its own doc.
|
||||
|
||||
## Addenda: Shell Integration metrics from VsCode
|
||||
|
||||
In the first month that Shell Integration was enabled by default for all VsCode users:
|
||||
|
||||
* ~57% machines fired shell integration-related events (_I think this covers all
|
||||
who used the terminal_). Of those:
|
||||
* 40% succeeded activation at least once
|
||||
* 83% failed activation silently/gracefully at least once (_This improved in subsequent releases_)
|
||||
* 0.2% Failed due to process exit (_This was likely mostly https://github.com/microsoft/vscode/issues/157611_)
|
||||
* ~0.4% changed the setting manually to true or false
|
||||
|
||||
That last number, 0.4%, would suggest that the number of people who opted out is
|
||||
_very_ low and that the feature would be largely inoffensive.
|
||||
|
||||
### Footnotes
|
||||
|
||||
<a name="footnote-1"><a>[1]:
|
||||
|
||||
|
||||
[Fig]: https://github.com/withfig/autocomplete
|
||||
[Warp]: https://www.warp.dev/
|
||||
[#13445]: https://github.com/microsoft/terminal/issues/13445
|
||||
[Textualize]: https://www.textualize.io/
|
||||
[#12773]: https://github.com/microsoft/terminal/issues/12773
|
||||
[Notebooks]: ./Markdown%20Notebooks.md
|
||||
[Tasks]: ./Tasks.md
|
||||
[Suggestions UI]: ./Suggestions-UI.md
|
||||
[Shell Integration]: ./Shell-Integration-Marks.md
|
||||
[Copilot]: ./Copilot/Overview.md
|
||||
|
||||
[Codex CLI]: https://github.com/microsoft/Codex-CLI
|
||||
[Copilot CLI]: https://githubnext.com/projects/copilot-cli/
|
||||
[Warp AI]: https://docs.warp.dev/features/warp-ai
|
||||
8
doc/specs/NorthStar/generate.bat
Normal file
@@ -0,0 +1,8 @@
|
||||
@echo off
|
||||
pushd .
|
||||
cd Copilot
|
||||
pandoc -s Overview.md -o ..\generated\Copilot\Overview.docx
|
||||
pandoc -s Prompting.md -o ..\generated\Copilot\Prompting.docx
|
||||
pandoc -s Implicit-Suggestions.md -o ..\generated\Copilot\Implicit-Suggestions.docx
|
||||
pandoc -s Explain-that.md -o ..\generated\Copilot\Explain-that.docx
|
||||
popd
|
||||
BIN
doc/specs/NorthStar/img/3121-sxn-menu-2023-000.gif
Normal file
|
After Width: | Height: | Size: 585 KiB |
BIN
doc/specs/NorthStar/img/Copilot-in-cmdpal.png
Normal file
|
After Width: | Height: | Size: 100 KiB |
BIN
doc/specs/NorthStar/img/GitHub-open-with.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
doc/specs/NorthStar/img/command-history-suggestions.gif
Normal file
|
After Width: | Height: | Size: 965 KiB |
BIN
doc/specs/NorthStar/img/developers-already-do-this-000.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
doc/specs/NorthStar/img/inline-blocks-000.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
doc/specs/NorthStar/img/iterm2-CommandHistory.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
doc/specs/NorthStar/img/jupyter-notebooks-example.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
doc/specs/NorthStar/img/mockup-000.png
Normal file
|
After Width: | Height: | Size: 868 KiB |
BIN
doc/specs/NorthStar/img/save-command.gif
Normal file
|
After Width: | Height: | Size: 858 KiB |
BIN
doc/specs/NorthStar/img/shell-autocomplete-jul-2022-000.gif
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
doc/specs/NorthStar/img/shell-completion-menu-2023-02-21.gif
Normal file
|
After Width: | Height: | Size: 1008 KiB |
BIN
doc/specs/NorthStar/img/shell-completion-tooltip-000.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
doc/specs/NorthStar/img/tasks-from-cwd.gif
Normal file
|
After Width: | Height: | Size: 2.8 MiB |
BIN
doc/specs/NorthStar/img/tasks-suggestions.gif
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
doc/specs/NorthStar/img/vscode-shell-autocomplete-000.gif
Normal file
|
After Width: | Height: | Size: 431 KiB |
BIN
doc/specs/NorthStar/img/vscode-shell-integration-gutter-mark.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
doc/specs/NorthStar/img/vscode-shell-suggestions.gif
Normal file
|
After Width: | Height: | Size: 431 KiB |
BIN
doc/specs/NorthStar/img/vscode-tasks-000.gif
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
doc/specs/NorthStar/img/warp-workflows-000.gif
Normal file
|
After Width: | Height: | Size: 143 KiB |
BIN
doc/specs/NorthStar/img/warp-workflows-001.gif
Normal file
|
After Width: | Height: | Size: 450 KiB |