The "copy the remaining attributes" loop assumes that it has full
ownership over the rows that it copies. For that to be true,
we have to of course make sure that the current write-cursor
is at a fresh, new row in the first place.
## Validation Steps Performed
* In a new pwsh tab with 120 colums:
``Write-Host -NoNewline "`e[36m$('a'*120)`e[m"; sleep 10``
* Resize the window wider
* Color doesn't get lost
Regressed in #15500, incorrectly fixed in #17332, exposed by #17583.
My ineptitude on full display. If this isn't the last cursor
invalidation bug I'm going to cry.
Closes#17615
## Validation Steps Performed
* cmd.exe
* a directory with 6 files
* 80x24 viewport
* run `cls`
* run `dir` twice
This PR adds the ability to load snippets from the CWD into the
suggestions UI.
If shell integration is disabled, then we only ever think the CWD for a
pane is it's `startingDirectory`. So, in the default case, users can
still stick snippets into the root of their git repos, and have the
Terminal load them automatically (for profiles starting in the root of
their repo).
If it's enabled though, we'll always try to load snippets from the CWD
of the shell.
* We cache the actions into a separate map of CWD -> actions. This lets
us read the file only the first time we see a dir.
* We clear that cache on settings reload
* We only load `sendInput` actions from the `.wt.json`
As spec'd in #17329
* Add a revision to `ImageSlice` so that the renderers
can use it to cache them as bitmaps across frames.
* Hooked up the revision tracking to AtlasEngine to cache the
slices into `Buffer`s so we can own them into the `Present`.
* Hooked up those snapshots to BackendD3D with a straightforward
hashmap -> atlas-rect logic. Just like rendering text.
* Hooked up BackendD2D with a bad, but simple & direct drawing logic.
* Bonus: Modify `ImageSlice` to be returned as a raw pointers
as this helps performance slightly. (Trivial type == good.)
* Bonus: Fixed the `_debugShowDirty` code (disabled by default).
## Validation Steps Performed
* `mpv --really-quiet --vo=sixel foo.mp4` looks good ✅
* Scroll up down & observe dirty rects ✅
`nuget restore` actually runs through MSBuild! However, #15855 added a
dependency from our project on a system-installed _or locally detected_
`vcpkg.targets` (or `.props`).
Our build runs `nuget restore` before finding or installing vcpkg, so
the rules in our project file would try to import vcpkg before it had
been found (or installed).
On build agents with vcpkg installed via the VS workload, this was fine:
we would import the one that came with VS and go on our merry way. On
build agents where it needs to be installed locally, it could not be
imported.
The fix in this PR is to install/bootstrap vcpkg before running nuget.
I tried to isolate the vcpkg rules to only run _in the absence of
nuget_, but that didn't work.
Removes the GitHub action that provides the functionality for the
similar issues bot prototype. We can onboard to the more official
prototype instead to conserve functionality.
This regressed in #15707. By having the `viewportOffset` on the
`Settings` object we accidentally invalidate the entire viewport
every time it scrolls. That doesn't break anything of course,
but it's better to prevent this.
This PR additionally contains a fix for clamping the y coordinates
coming from `Renderer`: Since `viewportCellCount.y` is a count and
thus exclusive, but clamp's max is inclusive, we must subtract 1.
This pull request removes the following vendored open source, in favor
of getting it from vcpkg:
- CLI11 2.4
- jsoncpp 1.9
- fmt 7.1.3
- gsl 3.1 (not vendored, but submoduled--arguably worse!)
Now that Visual Studio 2022 includes a built-in workload for vcpkg, the
onboarding process is much smoother. Terminal should only require the
vcpkg workload.
I've added some build rules that detect vcpkg via VS and via the user's
environment before falling back to a location in the source tree. The CI
pipeline will fall back to installing and bootstrapping vcpkg in
dep/vcpkg if necessary.
Some OSS has not been (and will not be) migrated:
- wyhash: ours is included directly in til/hash
- pcg_random: we have a stripped down copy compared to vcpkg
- stb_rect: vcpkg only ships *all of STB*; ours is a stripped down copy
- chromium numerics: vcpkg does not ship Chromium, especially not this
tiny fraction of Chromium
- dynamic_bitset and libpopcnt: removing in #17510
- interval_tree: no vcpkg equivalent
To support the needs of the inbox Windows build, I've split up our vcpkg
manifest into dependencies for all projects and dependencies just for
Terminal. To support this, we now offer a `terminal` feature. The vcpkg
rules in `common.build.pre.props` are set up to turn it on, whereas the
build rules we eventually write for the OS will not be.
Most of the work is concentrated in `common.build.pre.props`.
Split off from #17510:
* `Viewport::Clamp` used `std::clamp` to calculate the intersection
between two rectangles. That works for exclusive rectangles,
because `.left == .right` indicates an empty rectangle.
But `Viewport` is an inclusive one, and so `.left == .right` is
non-empty. For instance, if the to-be-clamped rect is fully
outside the bounding rect, the result is a 1x1 viewport.
In effect this meant that `Viewport::Clamp` never clamped so far.
* The `targetArea < targetBuffer.size()` check is the wrong way around.
It should be `targetArea > targetBuffer.size()`.
* The `sourceSize` and `targetSize` checks are incorrect, because the
rectangles may be non-empty but outside the valid bounding rect.
* If these sizes were empty, we'd return the requested rectangle which
is a regression since conhost v1 and violates the API contract.
* The `sourceRect` emptiness check is incorrect, because the clamping
logic before it doesn't actually clamp to the bounding rect.
* The entire clamping and iteration logic is just overall too complex.
Adds a keybinding to open the quick fix menu, if one is available. When
the action is used, we also open up the button (if it was collapsed)
because that looks nice.
The `showSuggestions` action is bound to `ctrl+shift+period` by default
to align with VS' "quick actions" feature and VS Code's "quick fix"
feature. This was chosen over binding to `quickFix` because it's more
helpful. The quick fix button is a route for users that prefer to use
the mouse. If users want to add a keybinding to activate the `quickFix`
button, they can do that now.
This PR also performs a bit of miscellaneous polish from the bug bash.
This includes:
- the suggestions UI now presents quick fixes first
- scrolling may result in the button being drawn in the wrong place
- The bug was tracked down this line:
`TermControl::CursorPositionInDips()` --> `_core.CursorPosition()` -->
`Terminal::GetViewportRelativeCursorPosition()`. The mutable viewport
there does _not_ update when the user scrolls. Thus, the button would be
drawn on the same position _on the screen_ even though we scrolled. To
fix this, I include the `_scrollOffset` in the calculation. The only
other place this function is used is with the suggestions UI, which does
_not_ update the UIs position as we scroll (but if we're interested in
doing that, we can now).
Closes#17377
Without a renderer in #17510 we cannot skip "frames" anymore.
As such, using overlapped IO becomes crucial to avoid a regression
in performance. ITerminalHandoff3 fixes this by allowing the terminal
to pick the pipes it wants, which mirrors CreatePseudoConsole
where the caller can also pick its own pipes.
## Validation Steps Performed
* Do a handoff with the dev build
* Input/Output works ✅
This implements a 3s timeout for cursor inheritance which prevents
ConPTY from being deadlocked at startup, if the terminal misbehaves.
It serves another purpose, however, in that it prepares the code for
the introduction of overlapped IO in #17510.
Closes#11213
After the ConPTY rewrite in #17510 we'll not modify any VT sequences
anymore. This means that the `--vtmode` flag uses its only function.
Its only known user is `telnet.exe` which needs to be updated
to sanitize the output on its own. See MSFT:52532514
Split off from #17510:
* `HandleWantsOverlappedIo` can be used to check if a handle requires
overlapped IO. This is important, as `ReadFile` and `WriteFile` are
documented to not work correctly if an overlapped handle is used
without overlapped IO and vice versa.
In my tests with pipes, this appears to be true.
* `CreatePipe` creates a synchronous, unidirectional pipe.
* `CreateOverlappedPipe` does what it says on the tin, while allowing
you to specify the direction of the pipe (in, out, duplex).
* `GetOverlappedResultSameThread` is largely the same as
`GetOverlappedResult`, but adds back a neat optimization from
the time before Windows 7. I thought it was neat.
This abstraction will help #17510 inject its ConPTY-specific behavior
into all 6 relevant console API functions simultaneously. This avoids
having to repeat the same prologue and epilogue 4 times.
Ideally, we'd use composition here, but I found it to be a bad fit.
These events are kinda just boilerplate that now keeps getting
copy-pasta'd every time I make new pane types.
This instead moves them all to a singular base class, so the definitions
stay in sync.
* Wide glyphs that don't fit into the last column got treated
as narrow glyphs which broke line layout.
* Wide glyphs that don't fit into the last column got manually
padded with whitespace which broke Ctrl+A + Ctrl+C in conhost.
* Sudden increases/decreases in the pager height would leave
parts of the viewport with leftover text and not clear it away.
* Deleting an entire word at the start of a line would only delete
its first two characters.
Closes#17554
STL iterators have a significant overhead. This improves performance
of `GetLastNonSpaceColumn` by >100x (it's too large to measure),
and reflow by ~15x in debug builds. This makes text reflow in debug
builds today ~10x faster than it used to be in release builds before
the large rewrites in #15701 and #13626.
Turns out, when the branding disables the feature, we try to get
`QuickFixMenu` when it's not loaded, causing a crash in TerminalPage.
Since we end up loading the quick fix menu when we scroll or apply UI
settings, we're actually loading the quick fix menu pretty early on. So
might as well remove the `x:Load="False"`. If we feel strongly about
keeping the lazy loading functionality, we can do that later (and
probably apply the same heuristic to the other XAML we're registering in
TerminalApp).
This also adds a feature flag check when registering the menu in
TerminalApp.
Closes#17548
By rewriting `COOKED_READ_DATA` to use VT for its output we make it
possible to pass this VT output 1:1 straight to the hosting terminal
if we're running under ConPTY. This is also possible with the current
console APIs it uses, but it's somewhat janky. In particular the
usage of `ReadConsoleOutput` to backup/restore the popup contents
could be considered bad faith "rules for thee, not for me",
given that we're telling people to move away from those APIs.
The new implementation contains a bare bones "pager" to fit even
very long prompt contents into the VT viewport.
I fully expect this initial PR to not be entirely bug free, because
writing a proper pager with line wrapping is a little bit complex.
This PR takes some significant shortcuts by leveraging the fact
that the prompt line is always left-to-right and always a series
of fully filled lines followed by one potentially semi-full line.
This allows us to skip using a front/back-buffer for diffing the
contents between two redisplay calls.
Part of #14000
## Validation Steps Performed
* ASCII input
* Chinese input (中文維基百科) ✅
* Surrogate pair input (🙂) ✅
* In cmd.exe
* Create 2 files: "a😊b.txt" and "a😟b.txt"
* Press tab: Autocomplete to "a😊b.txt" ✅
* Navigate the cursor right past the "a"
* Press tab twice: Autocomplete to "a😟b.txt" ✅
* Execute `printf(" "); gets(buffer);` in C (or equivalent)
* Press Tab, A, Ctrl+V, Tab, A ✅
* The prompt is " A^V A" ✅
* Cursor navigation works ✅
* Backspacing/Deleting random parts of it works ✅
* It never deletes the initial 4 spaces ✅
* Backspace deletes preceding glyphs ✅
* Ctrl+Backspace deletes preceding words ✅
* Escape clears input ✅
* Home navigates to start ✅
* Ctrl+Home deletes text between cursor and start ✅
* End navigates to end ✅
* Ctrl+End deletes text between cursor and end ✅
* Left navigates over previous code points ✅
* Ctrl+Left navigates to previous word-starts ✅
* Right and F1 navigate over next code points ✅
* Pressing right at the end of input copies characters
from the previous command ✅
* Ctrl+Right navigates to next word-ends ✅
* Insert toggles overwrite mode ✅
* Delete deletes next code point ✅
* Up and F5 cycle through history ✅
* Doesn't crash with no history ✅
* Stops at first entry ✅
* Down cycles through history ✅
* Doesn't crash with no history ✅
* Stops at last entry ✅
* PageUp retrieves the oldest command ✅
* PageDown retrieves the newest command ✅
* F2 starts "copy to char" prompt ✅
* Escape dismisses prompt ✅
* Typing a character copies text from the previous command up
until that character into the current buffer (acts identical
to F3, but with automatic character search) ✅
* F3 copies the previous command into the current buffer,
starting at the current cursor position,
for as many characters as possible ✅
* Doesn't erase trailing text if the current buffer
is longer than the previous command ✅
* Puts the cursor at the end of the copied text ✅
* F4 starts "copy from char" prompt ✅
* Escape dismisses prompt ✅
* Erases text between the current cursor position and the
first instance of a given char (but not including it) ✅
* F6 inserts Ctrl+Z ✅
* F7 without modifiers starts "command list" prompt ✅
* Escape dismisses prompt ✅
* Entries wider than the window width are truncated ✅
* Height expands up to 20 rows with longer histories ✅
* F9 starts "command number" prompt ✅
* Left/Right replace the buffer with the given command ✅
* And put cursor at the end of the buffer ✅
* Up/Down navigate selection through history ✅
* Stops at start/end with <10 entries ✅
* Stops at start/end with >20 entries ✅
* Scrolls through the entries if there are too many ✅
* Shift+Up/Down moves history items around ✅
* Home navigates to first entry ✅
* End navigates to last entry ✅
* PageUp navigates by $height items at a time or to first ✅
* PageDown navigates by $height items at a time or to last ✅
* Alt+F7 clears command history ✅
* F8 cycles through commands that start with the same text as
the current buffer up until the current cursor position ✅
* Doesn't crash with no history ✅
* F9 starts "command number" prompt ✅
* Escape dismisses prompt ✅
* Ignores non-ASCII-decimal characters ✅
* Allows entering between 1 and 5 digits ✅
* Pressing Enter fetches the given command from the history ✅
* Alt+F10 clears doskey aliases ✅
* In cmd.exe, with an empty prompt in an empty directory:
Pressing tab produces an audible bing and prints no text ✅
* When Narrator is enabled, in cmd.exe:
* Typing individual characters announces only
exactly each character that is being typed ✅
* Backspacing at the end of a prompt announces
only exactly each deleted character ✅
In the spec review, we agreed these didn't really need to be saved to
the user's own settings file. This removes parsing and saving for the
`experimental.saveSnippet` action, but we still have the action
_internally_. This is powered by a new x-macro for "INTERNAL_" actions.
Follow-up from #16513.
The strided `memcpy` between buffers failed to account for situations
where the destination stride is smaller than the source stride.
The solution is to only copy as many bytes as are in each row.
## Validation Steps Performed
Even with AppVerifier the issue could not be reproduced.
Adding an `assert(srcStride <= mapped.RowPitch)`, however, did trap
the bug when WARP is used while BackendD3D is force-enabled.
This became much more obvious with the sendInput previewing. We would
only dismiss previews if the following action was also previewable.
related: #15845
As discussed in the bug bash. It should be closable with a button.
This also changes the tab color to match the Settings tabs.
This also fixes a crash where dragging just a snippets pane out to it's
own window would crash.
This fixes some more issues not properly covered by #17526:
* Fixed `_locComment_text` comments being effectively ignored.
* Fixed line splitting of comments (CRLF vs LF).
* Fixed BOM suppression.
* Fixed support for having multiple `{Locked=...}` comments.
* Modified `Generate-PseudoLocalizations.ps1` to find the .xml files.
(As opposed to .resw for the other translations.)
* Added support for the new format by adding new XPath expressions,
and stripping comments/attributes as needed.
* Fixed `PreserveWhitespace` during XML loading.
* Fixed compliance with PowerShell's strict mode.
## Validation Steps Performed
Ran it locally and compared the results. ✅
We have to run in an older OneBranch Windows container image due to
compiler bugs.
This change prevents us from having to wait for the container image to
download for build legs that _aren't_ using the compiler.
This adds a snippets pane, which can be a static pane with all your
snippets (`sendInput` actions) in it. (See #17329)
This pane has a treeview with these actions in it, that we can filter
with a textbox at the top.
Play buttons next to entries make it quick to run the command you found.
Bound in the default actions with
```json
{ "command": { "action": "splitPane", "type": "snippets" }, "id": "Terminal.OpenSnippetsPane", "name": { "key": "SnippetsPaneCommandName" } },
```
re: #1595
----
TODO, from 06-04 bug bash
* [x] Snippets pane doesn't display some "no snippets found" text if
there aren't any yet
* [x] open snippets pane; find a "send input"; click the play button on
it; input is sent to active pane; begin typing
* [x] I can open an infinite amount of suggestions panes
* ~I'm closing this as by-design for now at least. Nothing stopping
anyone from opening infinite of any kind of pane.~
* ~This would require kind of a lot of refactoring in this PR to mark a
kind of pane as being a singleton or singleton-per-tab~
* Okay everyone hates infinite suggestions panes, so I got rid of that
* [x] Ctrl+Shift+W should still work in the snippets pane even if focus
isn't in textbox
* [ ] open snippets pane; click on text box; press TAB key;
* [ ] If you press TAB again, I have no idea where focus went
* [x] some previews don't work. Like `^c` (`"input": "\u0003"`)
* [x] nested items just give you a bit of extra space for no reason and
it looks a little awkward
* [x] UI Suggestion: add padding on the right side
* [ ] [Accessibility] Narrator says "Clear buffer; Suggestions found
132" when you open the snippets pane
- Note: this is probably Narrator reading out the command palette (since
that's where I opened it from)
- We should probably expect something like "Snippets", then (assuming
focus is thrown into text box) "Type to filter snippets" or something
like that
- Remove the `deprecated` flag for the `keybindings` array now that we
have re-added that
- Update `userDefaults` to use the correct ID for the `Copy` command
This allows us to remove the dependency on the `Terminal.Internal`
repository.
I have also added some parameters to the build pipeline to ease testing.