Compare commits

..

218 Commits

Author SHA1 Message Date
Leonard Hecker
6126532e71 wip 2024-01-15 21:48:31 +01:00
Dustin L. Howett
a4445ed4cc Merge remote-tracking branch 'origin/inbox' 2024-01-12 12:13:12 -06:00
Dustin Howett
f1ca1566a1 Merged PR 10097391: [Git2Git] !10088843: Disable Legacy Console checkbox & display a label when FoD is missing
This change adds a different label to the property sheet which will be
displayed when conhostv1 is missing. It explains why the legacy console
checkbox is not enabled.

Related work items: MSFT-46195288
Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_we_adept_e4d2 41871b6f4c0bba64852bfbaa9255f7677246d6fe
2024-01-11 22:41:23 +00:00
Carlos Zamora
057183b651 Update SUI Color Scheme colors' AutoProp.Name and ToolTip (#16544)
In the Settings UI's Color Scheme page (where you edit the color scheme itself), update the color chip buttons to include the RGB value in the tooltip and screen reader announcements.

Closes #15985
Closes #15983

## Validation Steps Performed
Tooltip and screen reader announcement is updated on launch and when a new value is selected.
2024-01-10 10:06:14 -08:00
Leonard Hecker
fb8b120215 Remove leftover telemetry code (#16468)
This cleans up some leftover unused telemetry skeleton code.

## Validation Steps Performed
* A TraceLogging viewing application shows events 
2024-01-09 21:00:32 +00:00
James Holderness
d115500cff Enable alternate scroll mode by default (#16535)
This PR enables alternate scroll mode by default, and also fixes the
precedence so if there is any other mouse tracking mode enabled, that
will take priority.

## Validation Steps Performed

I've manually tested by viewing a file with `less`, and confirmed that
it can now scroll using the mouse wheel by default. Also tested mouse
mouse in vim and confirmed that still works.

## PR Checklist
Closes #13187
2024-01-09 14:44:27 -06:00
Dustin L. Howett
c4c06dadad Remove EDP auditing completely (#16460)
This pull request started out very differently. I was going to move all
the EDP code from the internal `conint` project into the public, because
EDP is [fully documented]!

Well, it doesn't have any headers in the SDK.

Or import libraries.

And it's got a deprecation notice:

> [!NOTE]
> Starting in July 2022, Microsoft is deprecating Windows Information
> Protection (WIP) and the APIs that support WIP. Microsoft will
continue
> to support WIP on supported versions of Windows. New versions of
Windows
> won't include new capabilities for WIP, and it won't be supported in
> future versions of Windows.

So I'm blasting it out the airlock instead.

[fully documented]:
https://learn.microsoft.com/en-us/windows/win32/devnotes/windows-information-protection-api
2024-01-09 14:11:14 -06:00
Craig Loewen
375d00d0cd Fix similarIssues.yml to not fail when no similar issues found (#16542)
Added an if statement to similarIssues.yml so that the logic can be
updated to not show as 'failure' when no similar issue is found.

Related: https://github.com/craigloewen-msft/GitGudSimilarIssues/issues/33
2024-01-08 14:30:41 -06:00
Craig Loewen
b02316b37c Update similarIssues.yml to have a lower tolerance (#16530)
The tolerance value for a similar repo was changed from 0.8 to 0.75.

This is because I changed the backend service for this to use pinecone
instead of Azure AI search (see here
f72fa59e23
) and the metric changed as a result of that. They are slightly lower
than they were before, so this should offset that.
2024-01-08 10:20:37 -06:00
Dustin L. Howett
8b7bb99160 Migrate OSS up to acb06304c (1.19-pre, GDI curly underlines!) 2023-12-15 17:57:11 -06:00
Leonard Hecker
acb06304c2 Put the final touches on GDI's underlines (#16475)
While #16444 left wavy lines in an amazing state already, there were
a few more things that could be done to make GDI look more consistent
with other well known Windows applications.

But before that, a couple unrelated, but helpful changes were made:
* `GdiEngine::UpdateFont` was heavily modified to do all calculations
  in floats. All modern CPUs have fast FPUs and even the fairly slow
  `lroundf` function is so fast (relatively) nowadays that in a cold
  path like this, we can liberally call it to convert back to `int`s.
  This makes intermediate calculation more accurate and consistent.
* `GdiEngine::PaintBufferGridLines` was exception-unsafe due to its
  use of a `std::vector` with catch clause and this PR fixes that.
  Additionally, the vector was swapped out with a `til::small_vector`
  to reduce heap allocations. (Arena allocators!)
* RenderingTests was updated to cover styled underlines

With that in place, these improvements were done:
* Word's double-underline algorithm was ported over from `AtlasEngine`.
  It uses a half underline-width (aka `thinLineWidth`) which will now
  also be used for wavy lines to make them look a bit more filigrane.
* The Bézier curve for wavy/curly underlines was modified to use
  control points at (0.5,0.5) and (0.5,-0.5) respectively. This results
  in a maxima at y=0.1414 which is much closer to a sine curve with a
  maxima at 1/(2pi) = 0.1592. Previously, the maxima was a lot higher
  (roughly 4x) depending on the aspect ratio of the glyphs.
* Wavy underlines don't depend on the aspect ratio of glyphs anymore.
  This previously led to several problems depending on the exact font.
  The old renderer would draw exactly 3 periods of the wave into
  each cell which would also ensure continuity between cells.
  Unfortunately, this meant that waves could look inconsistent.
  The new approach always uses the aforementioned sine-like waves.
* The wavy underline offset was clamped so that it's never outside of
  bounds of a line. This avoids clipping.

* Compile RenderingTests and run it
* Using Consolas, MS Gothic and Cascadia Code while Ctrl+Scrolling
  up and down works as expected without clipping 

(cherry picked from commit 99193c9a3f)
Service-Card-Id: 91356394
Service-Version: 1.19
2023-12-15 17:55:22 -06:00
Tushar Singh
a62fb06b32 Fix curlyline rendering in AtlasEngine and GDIRenderer (#16444)
Fixes Curlyline being drawn as single underline in some cases

**Detailed Description**

- Curlyline is drawn at all font sizes.
- We might render a curlyline that is clipped in cases where we don't
have enough space to draw a full curlyline. This is to give users a
consistent view of Curlylines. Previously in those cases, it was drawn
as a single underline.
- Removed minimum threshold `minCurlyLinePeakHeight` for Curlyline
drawing.
- GDIRender changes:
- Underline offset now points to the (vertical) mid position of the
underline. Removes redundant `underlineMidY` calculation inside the draw
call.

Closes #16288

(cherry picked from commit f5b45c25c9)
Service-Card-Id: 91349182
Service-Version: 1.19
2023-12-15 17:54:22 -06:00
Tushar Singh
322fdd027c Support rendering of underline style and color (#16097)
Add support for underline style and color in the renderer

> [!IMPORTANT]
> The PR adds underline style and color feature to AtlasEngine (WT) and
GDIRenderer (Conhost) only.

After the underline style and color feature addition to Conpty, this PR
takes it further and add support for rendering them to the screen!

Out of five underline styles, we already supported rendering for 3 of
those types (Singly, Doubly, Dotted) in some form in our (Atlas)
renderer. The PR adds the remaining types, namely, Dashed and Curly
underlines support to the renderer.

- All renderer engines now receive both gridline and underline color,
and the latter is used for drawing the underlines. **When no underline
color is set, we use the foreground color.**
- Curly underline is rendered using `sin()` within the pixel shader.
- To draw underlines for DECDWL and DECDHL, we send the line rendition
scale within `QuadInstance`'s texcoord attribute.
- In GDI renderer, dashed and dotted underline is drawn using `HPEN`
with a desired style. Curly line is a cubic Bezier that draws one wave
per cell.

## PR Checklist
-  Set the underline color to underlines only, without affecting the
gridline color.
-  Port to DX renderer. (Not planned as DX renderer soon to be replaced
by **AtlasEngine**)
-  Port underline coloring and style to GDI renderer (Conhost).
-  Wide/Tall `CurlyUnderline` variant for `DECDWL`/`DECDHL`.

Closes #7228

(cherry picked from commit e268c1c952)
Service-Card-Id: 91349180
Service-Version: 1.19
2023-12-15 17:54:21 -06:00
Dustin L. Howett
c150919bd0 Migrate OSS up to 2546c02ad (1.19-pre, bug fixes) 2023-12-15 17:53:34 -06:00
Leonard Hecker
2546c02adb Fix parsing of chunked win32-input-mode sequences (#16466)
Even with the previous fixes we still randomly encounter win32-
input-mode sequences that are broken up in exactly such a way that
e.g. lone escape keys are encounters. Those for instance clear the
current prompt. The remaining parts of the sequence are then visible.

This changeset fixes the issue by skipping the entire force-to-ground
code whenever we saw at least 1 win32-input-mode sequence.

Related to #16343

## Validation Steps Performed
* Host a ConPTY inside ConPTY (= double the trouble) with cmd.exe
* Paste random amounts of text
* In the old code spurious `[..._` strings are seen
* In the new code they're consistently gone 

(cherry picked from commit bc18348967)
Service-Card-Id: 91337332
Service-Version: 1.19
2023-12-15 17:52:46 -06:00
js324
63c3573a13 Wrap word-wise selection when the word is actually wrapped (#16441)
Added wrapping to highlighted selection when selecting a word, added
tests for it

## Detailed Description of the Pull Request / Additional comments
- Modified GetWordStart and GetWordEnd and their helpers to no longer be
bounded by the right and left viewport ranges
- Kept same functionality (does not wrap) when selecting wrapped
whitespace
- Added tests to TextBufferTests.cpp to include cases of wrapping text

## Validation Steps Performed
- Ran locally and verified selection works properly
- Tests passed locally

Closes #4009
2023-12-15 15:50:45 -08:00
Leonard Hecker
bc18348967 Fix parsing of chunked win32-input-mode sequences (#16466)
Even with the previous fixes we still randomly encounter win32-
input-mode sequences that are broken up in exactly such a way that
e.g. lone escape keys are encounters. Those for instance clear the
current prompt. The remaining parts of the sequence are then visible.

This changeset fixes the issue by skipping the entire force-to-ground
code whenever we saw at least 1 win32-input-mode sequence.

Related to #16343

## Validation Steps Performed
* Host a ConPTY inside ConPTY (= double the trouble) with cmd.exe
* Paste random amounts of text
* In the old code spurious `[..._` strings are seen
* In the new code they're consistently gone 
2023-12-15 23:50:06 +00:00
Leonard Hecker
91e97c169e Increase VtInputThread buffer size (#16470)
This makes 3 improvements:
* 16x larger input buffer size improves behavior when pasting
  clipboard contents while the win32-input-mode is enabled,
  as each input character is roughly 15-20x longer after encoding.
* Translate UTF8 to UTF16 outside of the console lock.
* Preserve the UTF16 buffer between reads for less mallocs.

(cherry picked from commit 171a21ad48)
Service-Card-Id: 91347494
Service-Version: 1.19
2023-12-15 17:38:19 -06:00
Leonard Hecker
5d85eb3e24 COOKED_READ: A minor cleanup (#16463)
This is just a minor, unimportant cleanup to remove code duplication
in `_flushBuffer`, which called `SetCursorPosition` twice each time
the cursor position changed.
2023-12-15 23:31:48 +00:00
Leonard Hecker
a65d5f321f Add missing TraceLoggingRegister calls (#16467)
17cc109 and e9de646 both made the same mistake: When cleaning up our
telemetry code they also removed the calls to `TraceLoggingRegister`
which also broke regular tracing. Windows Defender in particular uses
the "CookedRead" event to monitor for malicious shell commands.

This doesn't fix it the "right way", because destructors of statics
aren't executed when DLLs are unloaded. But I felt like that this is
fine because we have way more statics than that in conhost land,
all of which have the same kind of issue.
2023-12-15 23:29:09 +00:00
Leonard Hecker
99193c9a3f Put the final touches on GDI's underlines (#16475)
While #16444 left wavy lines in an amazing state already, there were
a few more things that could be done to make GDI look more consistent
with other well known Windows applications.

But before that, a couple unrelated, but helpful changes were made:
* `GdiEngine::UpdateFont` was heavily modified to do all calculations
  in floats. All modern CPUs have fast FPUs and even the fairly slow
  `lroundf` function is so fast (relatively) nowadays that in a cold
  path like this, we can liberally call it to convert back to `int`s.
  This makes intermediate calculation more accurate and consistent.
* `GdiEngine::PaintBufferGridLines` was exception-unsafe due to its
  use of a `std::vector` with catch clause and this PR fixes that.
  Additionally, the vector was swapped out with a `til::small_vector`
  to reduce heap allocations. (Arena allocators!)
* RenderingTests was updated to cover styled underlines

With that in place, these improvements were done:
* Word's double-underline algorithm was ported over from `AtlasEngine`.
  It uses a half underline-width (aka `thinLineWidth`) which will now
  also be used for wavy lines to make them look a bit more filigrane.
* The Bézier curve for wavy/curly underlines was modified to use
  control points at (0.5,0.5) and (0.5,-0.5) respectively. This results
  in a maxima at y=0.1414 which is much closer to a sine curve with a
  maxima at 1/(2pi) = 0.1592. Previously, the maxima was a lot higher
  (roughly 4x) depending on the aspect ratio of the glyphs.
* Wavy underlines don't depend on the aspect ratio of glyphs anymore.
  This previously led to several problems depending on the exact font.
  The old renderer would draw exactly 3 periods of the wave into
  each cell which would also ensure continuity between cells.
  Unfortunately, this meant that waves could look inconsistent.
  The new approach always uses the aforementioned sine-like waves.
* The wavy underline offset was clamped so that it's never outside of
  bounds of a line. This avoids clipping.

## Validation Steps Performed
* Compile RenderingTests and run it
* Using Consolas, MS Gothic and Cascadia Code while Ctrl+Scrolling
  up and down works as expected without clipping 
2023-12-15 15:02:24 -08:00
e82eric
28acc102a5 Highlight all search results while the search box is open (#16227)
**FIRST TIME CONTRIBUTOR**

Follows the existing selection code as much as possible.
Updated logic that finds selection rectangles to also identify search
rectangles.

Right now, this feature only works in the new Atlas engine -- it uses
the background and foreground color bitmaps to quickly and efficiently
set the colors of a whole region of text.

Closes #7561

Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
2023-12-15 21:13:49 +00:00
Leonard Hecker
171a21ad48 Increase VtInputThread buffer size (#16470)
This makes 3 improvements:
* 16x larger input buffer size improves behavior when pasting
  clipboard contents while the win32-input-mode is enabled,
  as each input character is roughly 15-20x longer after encoding.
* Translate UTF8 to UTF16 outside of the console lock.
* Preserve the UTF16 buffer between reads for less mallocs.
2023-12-15 11:17:42 -08:00
Tushar Singh
306cb404dc Use MSWord compatible RTF sequence for background text color (#16035)
The `GenRTF(...)` was using `\highlight` control word for sending
background text color in the RTF format during a copy command. This
doesn't work correctly, since many applications (E.g. MSWord) don't
support full RGB with `\highlight`, and instead uses an approximation of
what is received. For example, `rgb(197, 15, 31)` becomes `rgb(255, 0,
255)`. Also, the standard way of using background colors is `\cbN`
control word, which isn't supported as per the [RTF Spec 1.9.1]
in Word.

But it briefly mentioned a workaround at Pg. 23, which seems to work on
all the RTF editors I tested.

The PR makes the changes to use `\chshdng0\chcbpatN` for the background
coloring.

Also did some refactoring to make the implementation concise.

## Validation Steps Performed

Verified that the background is correctly copied on below editors:
- MSWord
- WordPad
- LibreOffice
- Outlook

[RTF Spec 1.9.1]: https://msopenspecs.azureedge.net/files/Archive_References/[MSFT-RTF].pdf

(cherry picked from commit 310814bb30)
Service-Card-Id: 91349195
Service-Version: 1.19
2023-12-15 12:40:08 -06:00
Tushar Singh
f5b45c25c9 Fix curlyline rendering in AtlasEngine and GDIRenderer (#16444)
Fixes Curlyline being drawn as single underline in some cases

**Detailed Description**

- Curlyline is drawn at all font sizes.
- We might render a curlyline that is clipped in cases where we don't
have enough space to draw a full curlyline. This is to give users a
consistent view of Curlylines. Previously in those cases, it was drawn
as a single underline.
- Removed minimum threshold `minCurlyLinePeakHeight` for Curlyline
drawing.
- GDIRender changes:
- Underline offset now points to the (vertical) mid position of the
underline. Removes redundant `underlineMidY` calculation inside the draw
call.

Closes #16288
2023-12-14 11:47:14 -08:00
Dustin L. Howett
a93d99d0c1 Migrate OSS up to bcc01d96b (1.19-pre) 2023-12-08 15:22:20 -06:00
Dustin L. Howett
bcc01d96bf conpty: request DSR-CPR before Win32 input mode (#16445)
This prevents an issue in conhost where older versions of Windows
Terminal (including the ones currently inbox in Windows, as well as
stable and preview) will *still* cause WSL interop to hang on startup.

Since VT input is erroneously re-encoded as Win32 input events on those
versions, we need to make sure we request the cursor position *before*
enabling Win32 input mode. That way, the CPR we get back is properly
encoded.

(cherry picked from commit 17867af534)
Service-Card-Id: 91301135
Service-Version: 1.19
2023-12-08 15:21:47 -06:00
Dustin L. Howett
17867af534 conpty: request DSR-CPR before Win32 input mode (#16445)
This prevents an issue in conhost where older versions of Windows
Terminal (including the ones currently inbox in Windows, as well as
stable and preview) will *still* cause WSL interop to hang on startup.

Since VT input is erroneously re-encoded as Win32 input events on those
versions, we need to make sure we request the cursor position *before*
enabling Win32 input mode. That way, the CPR we get back is properly
encoded.
2023-12-08 21:01:55 +00:00
Ryan Luu
20dad62471 Fix markdown alerts syntax in README (#16434)
Changes any references of `> **Note**\` with `> [!NOTE]` to match the
new syntax for markdown files in GitHub.

Fixes the 14 November 2023 update to the alerts syntax in markdown
files:
> ## Update - 14 November 2023
> * The initial syntax using e.g. **Note** isn't supported any longer.
> 
> https://github.com/orgs/community/discussions/16925
2023-12-07 00:31:30 +01:00
Dustin L. Howett
32f19ef437 Migrate OSS up to f63e25b87 (1.19-pre) 2023-12-06 17:16:58 -06:00
Leonard Hecker
f63e25b87c Fix chunked soft fonts not working (#16349)
This changeset fixes an issue caused by #15991 where "chunked" escape
sequences would get corrupted. The fix is to simply not flush eagerly
anymore. I tried my best to keep the input lag reduction from #15991,
but unfortunately this isn't possible for console APIs.

Closes #16079

## Validation Steps Performed
* `type ascii.com` produces soft font ASCII characters 

(cherry picked from commit bdf2f6f274)
Service-Card-Id: 91283205
Service-Version: 1.19
2023-12-06 17:16:41 -06:00
Dustin L. Howett
8b5c833b2b Migrate OSS up to efbfb1214 (1.19-pre) 2023-12-06 16:55:26 -06:00
Leonard Hecker
efbfb12145 Fix ConPTY inputs incorrectly being treated as plain text (#16352)
This is my proposal to avoid aborting ConPTY input parsing because a
read accidentally got split up into more than one chunk. This happens a
lot with WSL for me, as I often get (for instance) a
`\x1b[67;46;99;0;32;` input followed immediately by a `1_` input. The
current logic would cause both of these to be flushed out to the client
application.

This PR fixes the issue by only flushing either a standalone escape
character or a escape+character combination. It basically limits the
previous code to just `VTStates::Ground` and `VTStates::Escape`.

I'm not using the `_state` member, because `VTStates::OscParam` makes no
distinction between `\x1b]` and `\x1b]1234` and I only want to flush the
former. I felt like checking the contents of `run` directly is easier to
understand.

Related to #16343

## Validation Steps Performed
* win32-input-mode sequences are now properly buffered 
* Standalone alt-key combinations are still being flushed 

(cherry picked from commit 5f5ef10571)
Service-Card-Id: 91270261
Service-Version: 1.19
2023-12-06 16:54:22 -06:00
Dustin L. Howett
306f31acf4 ci: remove the check-spelling-0.0.21 shim (#16424)
As noted by @jsoref in #16127, we could eventually remove this and also
check-spelling would make suggestions on what patterns to use.
2023-12-06 05:20:15 -06:00
Josh Soref
dc986e4489 Check spelling 0.0.22 (#16127)
Upgrades check-spelling to [v0.0.22](https://github.com/check-spelling/check-spelling/releases/tag/v0.0.22)

* refreshes workflow
* enables dependabot PRs to trigger CI (so that in the future you'll be
able to see breaking changes to the dictionary paths)
* refreshes metadata
* built-in handling of `\n`/`\r`/`\t` is removed -- This means that the
`patterns/0_*.txt` files can be removed.
* this specific PR includes some shim content, in
`allow/check-spelling-0.0.21.txt` -- once it this PR merges, it can be
removed on a branch and the next CI will clean out items from
`expect.txt` relating to the `\r` stuff and suggest replacement content.
* talking to the bot is enabled for forks (but not the master
repository)
* SARIF reporting is enabled for PRs w/in a single repository (not
across forks)
* In job reports, there's a summary table (space permitting) linking to
instances (this is a poor man's SARIF report)
* When a pattern splits a thing that results in check-spelling finding
an unrecognized token, that's reported with a distinct category
* When there are items in expect that not longer match anything but more
specific items do (e.g. `microsoft` vs. `Microsoft`), there's now a
specific category with help/advice
* Fancier excludes suggestions (excluding directories, file types, ...)
* Refreshed dictionaries
* The comment now links to the job summary (which includes SARIF link if
available, the details view, and a generated commit that people can use
if they're ok w/ the expect changes and don't want to run perl)

Validation
----------

1. the branch was developed in
https://github.com/check-spelling-sandbox/terminal/actions?query=branch%3Acheck-spelling-0.0.22
2. ensuring compatibility with 0.0.21 was done in
https://github.com/check-spelling-sandbox/terminal/pull/3
3. this version has been in development for a year and has quite a few
improvements, we've been actively dogfooding it throughout this period 😄

Additional Fixes
----------------
spelling: the
spelling: shouldn't
spelling: no
spelling: macos
spelling: github
spelling: fine-grained
spelling: coarse-grained

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-12-05 15:40:23 -08:00
Jvr
65d2d3dcec Update actions/add-to-project to version 0.5.0 (#16084)
Update actions/add-to-project to version 0.5.0
2023-12-05 16:31:52 -06:00
Jvr
9967851bf8 Update xamlstyler to 3.2311.2 (#16422)
Update xalmstyler to 3.2311.2
2023-12-05 16:30:21 -06:00
debghs
f9652983f1 Minor grammar fixes for the vintage AddASetting.md doc (#16188)
## Summary of the Pull Request
Added some Punctuation Marks as Required.
## References and Relevant Issues
None.
## Detailed Description of the Pull Request / Additional comments
There were some missing Punctuation Marks(Ex: Colon(:) and Full
Stop(.)), so I have added them.
## Validation Steps Performed
2023-12-05 15:39:00 -06:00
Leonard Hecker
5f5ef10571 Fix ConPTY inputs incorrectly being treated as plain text (#16352)
This is my proposal to avoid aborting ConPTY input parsing because a
read accidentally got split up into more than one chunk. This happens a
lot with WSL for me, as I often get (for instance) a
`\x1b[67;46;99;0;32;` input followed immediately by a `1_` input. The
current logic would cause both of these to be flushed out to the client
application.

This PR fixes the issue by only flushing either a standalone escape
character or a escape+character combination. It basically limits the
previous code to just `VTStates::Ground` and `VTStates::Escape`.

I'm not using the `_state` member, because `VTStates::OscParam` makes no
distinction between `\x1b]` and `\x1b]1234` and I only want to flush the
former. I felt like checking the contents of `run` directly is easier to
understand.

Related to #16343

## Validation Steps Performed
* win32-input-mode sequences are now properly buffered 
* Standalone alt-key combinations are still being flushed 
2023-12-05 13:37:58 -06:00
Leonard Hecker
71a6f26e6e Improve conhost's scrolling performance (#16333)
`EnableScrollbar()` and especially `SetScrollInfo()` are prohibitively
expensive functions nowadays. This improves throughput of good old
`type` in cmd.exe by ~10x, by briefly releasing the console lock.

## Validation Steps Performed
* `type`ing a file in `cmd` is as fast while the window is scrolling
  as it is while it isn't scrolling 
* Scrollbar pops in and out when scroll-forward is disabled 
2023-12-04 18:02:46 -08:00
Leonard Hecker
8a9af94095 Disable win32 input mode on exit (#16408)
When ConPTY exits it should attempt to restore the state as it was
before it started. This is particularly important for the win32
input mode sequences, as Linux shells don't know what to do with it.

Related to #16343

## Validation Steps Performed
* Replace conhost with this
* Launch a Win32 application inside WSL
* Exit that application
* Shell prompt doesn't get filled with win32 input mode sequences 

(cherry picked from commit 70e51ae28d)
Service-Card-Id: 91246943
Service-Version: 1.19
2023-12-04 19:54:08 -06:00
Leonard Hecker
70e51ae28d Disable win32 input mode on exit (#16408)
When ConPTY exits it should attempt to restore the state as it was
before it started. This is particularly important for the win32
input mode sequences, as Linux shells don't know what to do with it.

Related to #16343

## Validation Steps Performed
* Replace conhost with this
* Launch a Win32 application inside WSL
* Exit that application
* Shell prompt doesn't get filled with win32 input mode sequences 
2023-12-04 17:53:55 -08:00
Leonard Hecker
ef32e3e487 Fix scroll-forward-disable setting (#16411)
The final parameter, `updateBottom`, controls not just whether the
`_virtualBottom` is updated, but also whether the position is clamped
to be within the existing `_virtualBottom`. Setting this to `false`
thus broke scroll-forward as the `_virtualBottom` was now a constant.

## Validation Steps Performed
* Disable scroll-foward
* Press and hold Ctrl+C
* It scrolls past the viewport bottom 

(cherry picked from commit ab7a2f10c5)
Service-Card-Id: 91258882
Service-Version: 1.19
2023-12-04 17:09:35 -06:00
Leonard Hecker
9882154043 Avoid encoding VT via win32 input mode (#16407)
This changeset avoids re-encoding output from `AdaptDispatch`
via the win32-input-mode mechanism when VT input is enabled.
That is, an `AdaptDispatch` output like `\x1b[C` would otherwise
result in dozens of characters of input.

Related to #16343

## Validation Steps Performed
* Replace conhost with this
* Launch a Win32 application inside WSL
* ASCII keyboard inputs are represented as single `INPUT_RECORD`s 

(cherry picked from commit 0da37a134a)
Service-Card-Id: 91246942
Service-Version: 1.19
2023-12-04 17:09:34 -06:00
Leonard Hecker
486f7ef644 Fix a coroutine AV crash (#16412)
tl;dr: A coroutine lambda does not hold onto captured variables.
This causes an AV crash when closing tabs. I randomly noticed this
in a Debug build as the memory contents got replaced with 0xCD.
In a Release build this bug is probably fairly subtle and not common.

(cherry picked from commit 91fd7d0101)
Service-Card-Id: 91258717
Service-Version: 1.19
2023-12-04 17:09:32 -06:00
Leonard Hecker
85eee09854 Enable AtlasEngine by default (#16277)
This enables AtlasEngine by default in the 1.19 release branch.
A future change will remove the alternative DxEngine entirely.

(cherry picked from commit 204ebf3b19)
Service-Card-Id: 91158876
Service-Version: 1.19
2023-12-04 17:09:31 -06:00
Leonard Hecker
ab7a2f10c5 Fix scroll-forward-disable setting (#16411)
The final parameter, `updateBottom`, controls not just whether the
`_virtualBottom` is updated, but also whether the position is clamped
to be within the existing `_virtualBottom`. Setting this to `false`
thus broke scroll-forward as the `_virtualBottom` was now a constant.

## Validation Steps Performed
* Disable scroll-foward
* Press and hold Ctrl+C
* It scrolls past the viewport bottom 
2023-12-05 00:07:19 +01:00
Leonard Hecker
0da37a134a Avoid encoding VT via win32 input mode (#16407)
This changeset avoids re-encoding output from `AdaptDispatch`
via the win32-input-mode mechanism when VT input is enabled.
That is, an `AdaptDispatch` output like `\x1b[C` would otherwise
result in dozens of characters of input.

Related to #16343

## Validation Steps Performed
* Replace conhost with this
* Launch a Win32 application inside WSL
* ASCII keyboard inputs are represented as single `INPUT_RECORD`s 
2023-12-04 15:05:25 -08:00
Leonard Hecker
91fd7d0101 Fix a coroutine AV crash (#16412)
tl;dr: A coroutine lambda does not hold onto captured variables.
This causes an AV crash when closing tabs. I randomly noticed this
in a Debug build as the memory contents got replaced with 0xCD.
In a Release build this bug is probably fairly subtle and not common.
2023-12-04 14:58:57 -08:00
Leonard Hecker
204ebf3b19 Enable AtlasEngine by default (#16277)
This enables AtlasEngine by default in the 1.19 release branch.
A future change will remove the alternative DxEngine entirely.
2023-12-04 14:29:34 -06:00
Leonard Hecker
e33de75402 Fix backspacing over control visualizers (#16400)
During `!measureOnly` the old code would increment `distance` twice.
Now it doesn't. :)

Closes #16356

## Validation Steps Performed
See updated test instructions in `doc/COOKED_READ_DATA.md`

(cherry picked from commit 654b755161)
Service-Card-Id: 91232745
Service-Version: 1.19
2023-12-04 14:25:13 -06:00
Leonard Hecker
17d24bf055 Fix dwControlKeyState always including ENHANCED_KEY (#16335)
Since all VT parameters are treated to be at least 1 (and 1 if they're
absent or 0), `modifierParam > 0` was always true. This meant that
`ENHANCED_KEY` was always being set. It's unclear why `ENHANCED_KEY`
was used there, but it's likely not needed in general.

Closes #16266

## Validation Steps Performed
* Can't test this unless we fix the win32 input mode issue #16343 

(cherry picked from commit be9fc200c7)
Service-Card-Id: 91159301
Service-Version: 1.19
2023-12-04 14:25:12 -06:00
Adam Reynolds
dd83ba62cf Fixed crash when cloud shell provider timed out or was closed waiting for login (#16364)
## Summary of the Pull Request
Cloud shell connection calls out to Azure to do a device code login.
When the polling interval is exceeded or the tab is closed, the method
doing the connection polling returns `nullptr`, and `AzureConnection`
immediately tries to `GetNamedString` from it, causing a crash. This
doesn't repro on Terminal Stable or Preview, suggesting it's pretty
recent related to the update of this azureconnection.

This is just a proposed fix, not sure if you want to do more extensive
changes to the affected class or not, so marking this as a draft.

## References and Relevant Issues
* N/A - encountered this while using the terminal myself

## PR Checklist/Validation
Tested out a local dev build:

- [x] Terminal doesn't crash when cloudshell polling interval exceeded
- [x] Terminal doesn't crash when cloudshell tab closed while polling
for Azure login

(cherry picked from commit 0c4751ba30)
Service-Card-Id: 91232784
Service-Version: 1.19
2023-12-04 14:25:10 -06:00
Leonard Hecker
d4292d16cc Fix scrolling with SetConsoleWindowInfo (#16334)
81b7e54 caused a regression in `SetConsoleWindowInfo` and any other
function that used the `WriteToScreen` helper. This is because it
assumes that it can place the viewport anywhere randomly and it was
written at a time where `TriggerScroll` didn't exist yet (there was
no need for that (also not today, but that's being worked on)).

Caching the viewport meant that `WriteToScreen`'s call to
`TriggerRedraw` would pick up the viewport from the last rendered
frame, which would cause the intersection of both to be potentially
empty and nothing to be drawn on the screen.

This commit reverts 81b7e54 as I found that it has no or negligible
impact on performance at this point, likely due to the overall
vastly better performance of conhost nowadays.

Closes #15932

## Validation Steps Performed
* Scroll the viewport by entire pages worth of content using
  `SetConsoleWindowInfo` - see #15932
* The screen and scrollbars update immediately 

(cherry picked from commit 7a1b6f9d2a)
Service-Card-Id: 91152167
Service-Version: 1.19
2023-12-04 14:25:09 -06:00
Lonny Wong
a4ec8ec591 Fix Control+Space not sent to program running in terminal (#16298)
Converts null byte to specific input event, so that it's properly
delivered to the program running in the terminal.

Closes #15939

(cherry picked from commit 8747a39a07)
Service-Card-Id: 91201444
Service-Version: 1.19
2023-12-04 14:25:08 -06:00
Leonard Hecker
3538a9f72b Fix input buffering for A APIs (#16313)
This fixes an issue where character-wise reading of an input like "abc"
would return "a" to the caller, store "b" as a partial translation
(= wrong) and return "c" for the caller to store it for the next call.

Closes #16223
Closes #16299

## Validation Steps Performed
* `ReadFile` with a buffer size of 1 returns inputs character by
  character without dropping any inputs 

---------

Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
(cherry picked from commit 63b3820a18)
Service-Card-Id: 91122022
Service-Version: 1.19
2023-12-04 14:24:20 -06:00
Leonard Hecker
5ed7dc2f63 ConPTY: Fix a shutdown deadlock with WSL (#16340)
Under normal circumstances this bug should be rare as far as I can
observe it on my system. However, it does occur randomly.

In short, WSL doesn't pass us anonymous pipes, but rather WSA sockets
and those signal their graceful shutdown first before being closed
later by returning a `lpNumberOfBytesRead` of 0 in the meantime.

Additionally, `VtIo` synchronously pumps the input pipe to get the
initial cursor position, but fails to check `_exitRequested`.
And so even with the pipe handling fixed, `VtIo` will also deadlock,
because it will never realize that `VtInputThread` is done reading.

## Validation Steps Performed
* Build commit 376737e with this change and replace conhost with it
  Coincidentally it contains a bug (of as of yet unknown origin)
  due to which the initial cursor position loop in `VtIo` never
  completes. Thanks to this, we can easily provoke this issue.
* Launch WSL in conhost and run an .exe inside it
* Close the conhost window
* Task manager shows that all conhost instances exit immediately

(cherry picked from commit adb04729bc)
Service-Card-Id: 91152102
Service-Version: 1.19
2023-12-04 14:24:18 -06:00
Leonard Hecker
0d353d8be5 Fix nearby fonts for DxEngine again (#16323)
The nearby font loading has to be outside of the try/catch of the
`_FindFontFace` call, because it'll throw for broken font files.
But in my previous PR I had overlooked that the font variant loop
modifies the only copy of the face name that we got and was in the
same try/catch. That's bad, because once we get to the nearby search
code, the face name will be invalid. This commit fixes the issue by
wrapping each individual `_FindFontFace` call in a try/catch block.

Closes #16322

## Validation Steps Performed
* Remove every single copy of Windows Terminal from your system
* Manually clean up Cascadia .ttf files because they aren't gone
* Destroy your registry by manually removing appx references (fun!)
* Put the 4 Cascadia .ttf files into the Dev app AppX directory
* Launch
* No warning 

(cherry picked from commit b780b44528)
Service-Card-Id: 91114951
Service-Version: 1.19
2023-12-04 14:24:17 -06:00
Dustin L. Howett
abab8705fe Add a magic incantation to tell the Store we support Server (#16306)
I find it somewhat silly that (1) this isn't documented anywhere and (2)
installing the "desktop experience" packages for Server doesn't
automatically add support for the `Windows.Desktop` platform...

Oh well.

I'm going to roll this one out via Preview first, because if the store
blows up on it I would rather it not be during Stable roll-out.

(cherry picked from commit 86fb9b4478)
Service-Card-Id: 91098597
Service-Version: 1.19
2023-12-04 14:24:14 -06:00
Leonard Hecker
654b755161 Fix backspacing over control visualizers (#16400)
During `!measureOnly` the old code would increment `distance` twice.
Now it doesn't. :)

Closes #16356

## Validation Steps Performed
See updated test instructions in `doc/COOKED_READ_DATA.md`
2023-12-04 14:14:26 -06:00
Leonard Hecker
be9fc200c7 Fix dwControlKeyState always including ENHANCED_KEY (#16335)
Since all VT parameters are treated to be at least 1 (and 1 if they're
absent or 0), `modifierParam > 0` was always true. This meant that
`ENHANCED_KEY` was always being set. It's unclear why `ENHANCED_KEY`
was used there, but it's likely not needed in general.

Closes #16266

## Validation Steps Performed
* Can't test this unless we fix the win32 input mode issue #16343 
2023-11-30 15:55:06 +01:00
Leonard Hecker
130c9fbd76 Remove unused Utf8ToWideCharParser (#16392)
I randomly came across this class, that I didn't even remember we had.
We don't use this class at the moment and won't need it any time soon.
Its current implementation is also fairly questionable. While
`til::u16state` isn't "perfect", it's vastly better than this.
2023-11-30 15:52:39 +01:00
Adam Reynolds
0c4751ba30 Fixed crash when cloud shell provider timed out or was closed waiting for login (#16364)
## Summary of the Pull Request
Cloud shell connection calls out to Azure to do a device code login.
When the polling interval is exceeded or the tab is closed, the method
doing the connection polling returns `nullptr`, and `AzureConnection`
immediately tries to `GetNamedString` from it, causing a crash. This
doesn't repro on Terminal Stable or Preview, suggesting it's pretty
recent related to the update of this azureconnection.

This is just a proposed fix, not sure if you want to do more extensive
changes to the affected class or not, so marking this as a draft.

## References and Relevant Issues
* N/A - encountered this while using the terminal myself

## PR Checklist/Validation
Tested out a local dev build:

- [x] Terminal doesn't crash when cloudshell polling interval exceeded
- [x] Terminal doesn't crash when cloudshell tab closed while polling
for Azure login
2023-11-30 03:58:41 -06:00
Marcel Wagner
3b5e5cf5f1 Update paths to use linking within repo instead of github URL (#16358)
Update paths to use relative linking instead of static GitHub link. Also
fixes some dead links

Closes #16338
2023-11-27 15:41:17 -08:00
Leonard Hecker
7a1b6f9d2a Fix scrolling with SetConsoleWindowInfo (#16334)
81b7e54 caused a regression in `SetConsoleWindowInfo` and any other
function that used the `WriteToScreen` helper. This is because it
assumes that it can place the viewport anywhere randomly and it was
written at a time where `TriggerScroll` didn't exist yet (there was
no need for that (also not today, but that's being worked on)). 

Caching the viewport meant that `WriteToScreen`'s call to
`TriggerRedraw` would pick up the viewport from the last rendered
frame, which would cause the intersection of both to be potentially
empty and nothing to be drawn on the screen.

This commit reverts 81b7e54 as I found that it has no or negligible
impact on performance at this point, likely due to the overall
vastly better performance of conhost nowadays.

Closes #15932

## Validation Steps Performed
* Scroll the viewport by entire pages worth of content using
  `SetConsoleWindowInfo` - see #15932
* The screen and scrollbars update immediately 
2023-11-27 15:34:13 -06:00
Lonny Wong
8747a39a07 Fix Control+Space not sent to program running in terminal (#16298)
Converts null byte to specific input event, so that it's properly
delivered to the program running in the terminal.

Closes #15939
2023-11-27 15:31:06 -06:00
Leonard Hecker
35240f263e Fix font preview for conhost (#16324)
After exiting the main loop in this function the invariant
`nFont <= NumberOfFonts` still holds true. Additionally,
preceding this removed code is this (paraphrased):
```cpp
if (nFont < NumberOfFonts) {
    RtlMoveMemory(...);
}
```
It ensures that the given slot `nFont` is always unoccupied by moving
it and all following items upwards if needed. As such, the call to
`DeleteObject` is always incorrect, as the slot is always "empty",
but may contain a copy of the previous occupant due to the `memmove`.

This regressed in 154ac2b.

Closes #16297

## Validation Steps Performed
* All fonts have a unique look in the preview panel 
2023-11-27 12:44:50 -08:00
Radu Cernatescu
0a4fc9b6e4 Fix scrollbar resetting position on save (#16261)
This PR fixes Issue #11875 by introducing a ScrollViewer and some logic
for the scrollbar.

The ScrollViewer prevents the scrollbar from scrolling to the top
whenever "Save" is clicked in the Settings. In addition, the scrollbar
is scrolled to the top of the page whenever navigating to another page
within Settings. The scrollbar will not reset if attempting to navigate
to the same page that is already navigated to.

## Validation Steps Performed
Manual testing of the Settings by building the Terminal app.

Closes #11875
2023-11-27 11:40:47 -08:00
Leonard Hecker
63b3820a18 Fix input buffering for A APIs (#16313)
This fixes an issue where character-wise reading of an input like "abc"
would return "a" to the caller, store "b" as a partial translation
(= wrong) and return "c" for the caller to store it for the next call.

Closes #16223
Closes #16299

## Validation Steps Performed
* `ReadFile` with a buffer size of 1 returns inputs character by
  character without dropping any inputs 

---------

Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
2023-11-21 20:57:56 +00:00
Marcel Wagner
264ef4ebda [colortool] Add new campbell scheme, switch to CRLF endings for themes (#16339)
Adds "Campbell Absolute" which has absolute black/white instead of
slightly greyish variants as discussed per #35. Also updates line
endings to adhere to the default Windows line endings (i.e. CRLF)

Closes #35
2023-11-21 20:55:15 +00:00
Leonard Hecker
bdf2f6f274 Fix chunked soft fonts not working (#16349)
This changeset fixes an issue caused by #15991 where "chunked" escape
sequences would get corrupted. The fix is to simply not flush eagerly
anymore. I tried my best to keep the input lag reduction from #15991,
but unfortunately this isn't possible for console APIs.

Closes #16079

## Validation Steps Performed
* `type ascii.com` produces soft font ASCII characters 
2023-11-21 20:50:59 +00:00
Leonard Hecker
adb04729bc ConPTY: Fix a shutdown deadlock with WSL (#16340)
Under normal circumstances this bug should be rare as far as I can
observe it on my system. However, it does occur randomly.

In short, WSL doesn't pass us anonymous pipes, but rather WSA sockets
and those signal their graceful shutdown first before being closed
later by returning a `lpNumberOfBytesRead` of 0 in the meantime.

Additionally, `VtIo` synchronously pumps the input pipe to get the
initial cursor position, but fails to check `_exitRequested`.
And so even with the pipe handling fixed, `VtIo` will also deadlock,
because it will never realize that `VtInputThread` is done reading.

## Validation Steps Performed
* Build commit 376737e with this change and replace conhost with it
  Coincidentally it contains a bug (of as of yet unknown origin)
  due to which the initial cursor position loop in `VtIo` never
  completes. Thanks to this, we can easily provoke this issue.
* Launch WSL in conhost and run an .exe inside it
* Close the conhost window
* Task manager shows that all conhost instances exit immediately
2023-11-21 20:50:46 +00:00
Mike Griese
12318d97d0 test: Add an LLM-powered bot to detect dupes (#16304)
Just like in https://github.com/microsoft/WSL/pull/10745

We're working with the WSL team to figure out if we can use a LLM to
help us triage. This _should_ just comment on issues, if it finds
something similar on the backlog.
2023-11-21 10:05:07 -08:00
Leonard Hecker
376737e54a Hotfix recent AuditMode failures on CI (#16325)
Our CI seems to have had an update recently to around VS 17.7.
That version contains a faulty implementation for C26478 and C26494.
The issue has been fixed in VS 17.8 and later.
2023-11-16 15:28:37 -06:00
Leonard Hecker
b780b44528 Fix nearby fonts for DxEngine again (#16323)
The nearby font loading has to be outside of the try/catch of the
`_FindFontFace` call, because it'll throw for broken font files.
But in my previous PR I had overlooked that the font variant loop
modifies the only copy of the face name that we got and was in the
same try/catch. That's bad, because once we get to the nearby search
code, the face name will be invalid. This commit fixes the issue by
wrapping each individual `_FindFontFace` call in a try/catch block.

Closes #16322

## Validation Steps Performed
* Remove every single copy of Windows Terminal from your system
* Manually clean up Cascadia .ttf files because they aren't gone
* Destroy your registry by manually removing appx references (fun!)
* Put the 4 Cascadia .ttf files into the Dev app AppX directory
* Launch
* No warning 
2023-11-16 15:27:33 -06:00
Dustin L. Howett
86fb9b4478 Add a magic incantation to tell the Store we support Server (#16306)
I find it somewhat silly that (1) this isn't documented anywhere and (2)
installing the "desktop experience" packages for Server doesn't
automatically add support for the `Windows.Desktop` platform...

Oh well.

I'm going to roll this one out via Preview first, because if the store
blows up on it I would rather it not be during Stable roll-out.
2023-11-15 17:13:03 -08:00
Dustin Howett
65e19ddaf0 Merged PR 9880704: [Git2Git] conhost: remove all EOL velocity keys
I've also removed all of the supporting code.

Related work items: MSFT-47555635

Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_we_adept_e4d2 f8ad0110fd81d1b848224158c8f95724f34b1db2
2023-11-15 21:32:10 +00:00
Dustin L. Howett
37100034bf canary: include the correct handoff CLSIDs (#16317)
Canary still advertised the Dev CLSIDs, so it didn't work as DefTerm.

Closes #16316
2023-11-15 12:48:54 -08:00
Mike Griese
55a9874d5c Fix leak in buffering text for UIA when unfocused (#16251)
Notes in #16217 have the investigation.

TL;DR: we'd always buffer text. Even if we're disabled (unfocused). When
we're
disabled, we'd _never_ clear the buffered text. Oops.

Closes #16217

(cherry picked from commit d14524cd4c)
Service-Card-Id: 91033138
Service-Version: 1.19
2023-11-13 16:59:53 -06:00
PankajBhojwani
a7409ea4d3 Update Azure Cloud Shell for their new URI format (#16247)
The Azure cloud shell team made some API changes that required us to
format our requests a little differently. This PR makes those changes
(more info in the comments in the code)

Closes #16098

(cherry picked from commit 5a9f3529d7)
Service-Card-Id: 90985893
Service-Version: 1.19
2023-11-13 16:59:53 -06:00
Dustin L. Howett
28a1ecbdaa releng: add --first-parent to the scripts that use git log (#16279)
It makes the output less cluttered and more correct (for example:
ServicingPipeline no longer tries to service two copies of each commit
if there's a merge in the history...)

(cherry picked from commit 18b0ecbb2a)
Service-Card-Id: 91042450
Service-Version: 1.19
2023-11-13 16:59:53 -06:00
Leonard Hecker
4bbfa0570a Fix deadlocks due to holding locks across WriteFile calls (#16224)
This fixes a number of bugs introduced in 4370da9, all of which are of
the same kind: Holding the terminal lock across `WriteFile` calls into
the ConPTY pipe. This is problematic, because the pipe has a tiny buffer
size of just 4KiB and ConPTY may respond on its output pipe, before the
entire buffer given to `WriteFile` has been emptied. When the ConPTY
output thread then tries to acquire the terminal lock to begin parsing
the VT output, we get ourselves a proper deadlock (cross process too!).

The solution is to tease `Terminal` further apart into code that is
thread-safe and code that isn't. Functions like `SendKeyEvent` so far
have mixed them into one, because when they get called by `ControlCore`
they both, processed the data (not thread-safe as it accesses VT state)
and also sent that data back into `ControlCore` through a callback
which then indirectly called into the `ConptyConnection` which calls
`WriteFile`. Instead, we now return the data that needs to be sent from
these functions, and `ControlCore` is free to release the lock and
then call into the connection, which may then block indefinitely.

## Validation Steps Performed
* Start nvim in WSL
* Press `i` to enter the regular Insert mode
* Paste 1MB of text
* Doesn't deadlock 

(cherry picked from commit 71a1a97a9a)
Service-Card-Id: 91043521
Service-Version: 1.19
2023-11-13 16:59:53 -06:00
Mike Griese
2ac5e8670a Defer package updates while the Terminal is running (#16250)
Adds
```xml
<uap17:UpdateWhileInUse>defer</uap17:UpdateWhileInUse>
```
to our `Package.Properties` for all our packages.
This was added in the September 2023 OS release of Windows 11.

Apparently, this just works now? I did update VS,
but I don't _think_ that updated the SDK.
I have no idea how it updated the manifest definitions.

Closes #3915
Closes #6726

(cherry picked from commit 077d63e6a3)
Service-Card-Id: 91033136
Service-Version: 1.19
2023-11-13 16:59:53 -06:00
Mike Griese
d14524cd4c Fix leak in buffering text for UIA when unfocused (#16251)
Notes in #16217 have the investigation.

TL;DR: we'd always buffer text. Even if we're disabled (unfocused). When
we're
disabled, we'd _never_ clear the buffered text. Oops.

Closes #16217
2023-11-10 02:10:35 +01:00
Tushar Singh
e268c1c952 Support rendering of underline style and color (#16097)
Add support for underline style and color in the renderer

> [!IMPORTANT]  
> The PR adds underline style and color feature to AtlasEngine (WT) and
GDIRenderer (Conhost) only.

After the underline style and color feature addition to Conpty, this PR
takes it further and add support for rendering them to the screen!

Out of five underline styles, we already supported rendering for 3 of
those types (Singly, Doubly, Dotted) in some form in our (Atlas)
renderer. The PR adds the remaining types, namely, Dashed and Curly
underlines support to the renderer.

- All renderer engines now receive both gridline and underline color,
and the latter is used for drawing the underlines. **When no underline
color is set, we use the foreground color.**
- Curly underline is rendered using `sin()` within the pixel shader. 
- To draw underlines for DECDWL and DECDHL, we send the line rendition
scale within `QuadInstance`'s texcoord attribute.
- In GDI renderer, dashed and dotted underline is drawn using `HPEN`
with a desired style. Curly line is a cubic Bezier that draws one wave
per cell.

## PR Checklist
-  Set the underline color to underlines only, without affecting the
gridline color.
-  Port to DX renderer. (Not planned as DX renderer soon to be replaced
by **AtlasEngine**)
-  Port underline coloring and style to GDI renderer (Conhost).
-  Wide/Tall `CurlyUnderline` variant for `DECDWL`/`DECDHL`.

Closes #7228
2023-11-09 16:47:07 -08:00
chausner
eb16eeb29e Change DisclaimerStyle to be non-italic (#16272)
This changes the appearance of the disclaimer text that is used on some
of the settings pages. The italic text style is replaced with a neutral
style that fits better with the rest of the UI.

## Detailed Description of the Pull Request / Additional comments
I also tried out these alternative styles but overall preferred the
default TextBlock style (BodyTextBlockStyle).

Closes #16264.
2023-11-09 16:32:58 -08:00
PankajBhojwani
5a9f3529d7 Update Azure Cloud Shell for their new URI format (#16247)
The Azure cloud shell team made some API changes that required us to
format our requests a little differently. This PR makes those changes
(more info in the comments in the code)

Closes #16098
2023-11-08 09:12:13 -08:00
Dustin L. Howett
18b0ecbb2a releng: add --first-parent to the scripts that use git log (#16279)
It makes the output less cluttered and more correct (for example:
ServicingPipeline no longer tries to service two copies of each commit
if there's a merge in the history...)
2023-11-08 10:29:01 -06:00
Leonard Hecker
71a1a97a9a Fix deadlocks due to holding locks across WriteFile calls (#16224)
This fixes a number of bugs introduced in 4370da9, all of which are of
the same kind: Holding the terminal lock across `WriteFile` calls into
the ConPTY pipe. This is problematic, because the pipe has a tiny buffer
size of just 4KiB and ConPTY may respond on its output pipe, before the
entire buffer given to `WriteFile` has been emptied. When the ConPTY
output thread then tries to acquire the terminal lock to begin parsing
the VT output, we get ourselves a proper deadlock (cross process too!).

The solution is to tease `Terminal` further apart into code that is
thread-safe and code that isn't. Functions like `SendKeyEvent` so far
have mixed them into one, because when they get called by `ControlCore`
they both, processed the data (not thread-safe as it accesses VT state)
and also sent that data back into `ControlCore` through a callback
which then indirectly called into the `ConptyConnection` which calls
`WriteFile`. Instead, we now return the data that needs to be sent from
these functions, and `ControlCore` is free to release the lock and
then call into the connection, which may then block indefinitely.

## Validation Steps Performed
* Start nvim in WSL
* Press `i` to enter the regular Insert mode
* Paste 1MB of text
* Doesn't deadlock 
2023-11-08 10:28:07 -06:00
Mike Griese
077d63e6a3 Defer package updates while the Terminal is running (#16250)
Adds
```xml
<uap17:UpdateWhileInUse>defer</uap17:UpdateWhileInUse>
```
to our `Package.Properties` for all our packages.
This was added in the September 2023 OS release of Windows 11.

Apparently, this just works now? I did update VS,
but I don't _think_ that updated the SDK.
I have no idea how it updated the manifest definitions.

Closes #3915
Closes #6726
2023-11-07 21:35:16 +01:00
Dustin Howett
7cbe3190e1 Merged PR 9838597: Migrate OSS up to db27348e2
- AtlasEngine: Minor bug fixes (GH-16219)
- Fix the fix for the fix of nearby font loading (GH-16196)
- Added selectionBackground to light color schemes (GH-16243)
- Another theoretical fix for a crash (GH-16267)
- Fix tabs being printed in cmd.exe prompts (GH-16273)

Related work items: MSFT-47266988
2023-11-07 17:59:28 +00:00
Leonard Hecker
db27348e27 Fix tabs being printed in cmd.exe prompts (#16273)
A late change in #16105 wrapped `_buffer` into a class to better track
its dirty state, but I failed to notice that in this one instance we
intentionally manipulated `_buffer` without marking it as dirty.
This fixes the issue by adding a call to `MarkAsClean()`.

This changeset also adds the test instructions from #15783 as a
document to this repository. I've extended the list with two
bugs we've found in the implementation since then.

## Validation Steps Performed
* In cmd.exe, with an empty prompt in an empty directory:
  Pressing tab produces an audible bing and prints no text 

(cherry picked from commit 7a8dd90294)
Service-Card-Id: 91033502
Service-Version: 1.19
2023-11-07 11:56:00 -06:00
Mike Griese
83a2bc181a Another theoretical fix for a crash (#16267)
For history:

> This is MSFT:46763065 internally. Dumps show this repros on 1.19 too.
>
> This was previously #16061 which had a theoretical fix in #16065.
Looks like you're on Terminal Stable v1.18.2822.0, and
https://github.com/microsoft/terminal/releases/tag/v1.18.2822.0 is
supposed to have had that fix in it. Dang.

> well this is embarrassing ... I never actually checked if we _still
had a `_window`_. We're alive, yay! But we're still in the middle of
refrigerating. So, there's no HWND anymore

Attempt to fix this by actually ensuring there's a `_window` in
`AppHost::_WindowInitializedHandler`

Closes #16235

(cherry picked from commit 59dcbbe0e9)
Service-Card-Id: 91041359
Service-Version: 1.19
2023-11-07 11:55:59 -06:00
Taha Haksal
95e4d0bbe0 Added selectionBackground to light color schemes (#16243)
Add a selectionBackground property which is set to the scheme's
brightBlack too all 3 of the light color schemes.

Related to #8716
It does not close the bug because as mentioned in the issue, when you
input numbers, they seem to be invisible in the light color schemes and
selecting them with the cursor doesn't reveal them.

(cherry picked from commit a5c269b280)
Service-Card-Id: 91033167
Service-Version: 1.19
2023-11-07 11:55:59 -06:00
Leonard Hecker
a608a91571 Fix the fix for the fix of nearby font loading (#16196)
I still don't know how to reproduce it properly, but I'm slowly
wrapping my head around how and why it happens. The issue isn't that
`FindFamilyName` fails with `exists=FALSE`, but rather that any of the
followup calls like `GetDesignGlyphMetrics` fails, which results in an
exception and subsequently in an orderly fallback to Consolas.
I've always thought that the issue is that even with the nearby font
collection we get an `exists=FALSE`... I'm not sure why I thought that.

This changeset also drops the fallback iteration for Lucida Console and
Courier New, because I felt like the code looks neater that way and I
think it's a reasonable expectation that Consolas is always installed.

Closes #16058

(cherry picked from commit 9e86c9811f)
Service-Card-Id: 90885607
Service-Version: 1.19
2023-11-07 11:55:58 -06:00
Leonard Hecker
646edc7f8f AtlasEngine: Minor bug fixes (#16219)
This commit fixes 4 minor bugs:
* Forgot to set the maximum swap chain latency. Without it, it defaults
  to up to 3 frames of latency. We don't need this, because our renderer
  is simple and fast and is expected to draw frames within <1ms.
* ClearType treats the alpha channel as ignored, whereas custom shaders
  can manipulate the alpha channel freely. This meant that using both
  simultaneously would produce weird effects, like text having black
  background. We now force grayscale AA instead.
* The builtin retro shader should not be effected by the previous point.
* When the cbuffer is entirely unused in a custom shader, it has so far
  resulted in constant redraws. This happened because the D3D reflection
  `GetDesc` call will then return `E_FAIL` in this situation.
  The new code on the other hand will now assume that a failure
  to get the description is equal to the variable being unused.

Closes #15960

## Validation Steps Performed
* A custom passthrough shader works with grayscale and ClearType AA
  while also changing the opacity with Ctrl+Shift+Scroll 
* Same for the builtin retro shader, but ClearType works 
* The passthrough shader doesn't result in constant redrawing 

(cherry picked from commit 0289cb043c)
Service-Card-Id: 90915277
Service-Version: 1.19
2023-11-07 11:55:57 -06:00
Leonard Hecker
7a8dd90294 Fix tabs being printed in cmd.exe prompts (#16273)
A late change in #16105 wrapped `_buffer` into a class to better track
its dirty state, but I failed to notice that in this one instance we
intentionally manipulated `_buffer` without marking it as dirty.
This fixes the issue by adding a call to `MarkAsClean()`.

This changeset also adds the test instructions from #15783 as a
document to this repository. I've extended the list with two
bugs we've found in the implementation since then.

## Validation Steps Performed
* In cmd.exe, with an empty prompt in an empty directory:
  Pressing tab produces an audible bing and prints no text 
2023-11-07 11:51:13 -06:00
Mike Griese
59dcbbe0e9 Another theoretical fix for a crash (#16267)
For history: 

> This is MSFT:46763065 internally. Dumps show this repros on 1.19 too. 
> 
> This was previously #16061 which had a theoretical fix in #16065.
Looks like you're on Terminal Stable v1.18.2822.0, and
https://github.com/microsoft/terminal/releases/tag/v1.18.2822.0 is
supposed to have had that fix in it. Dang.

> well this is embarrassing ... I never actually checked if we _still
had a `_window`_. We're alive, yay! But we're still in the middle of
refrigerating. So, there's no HWND anymore

Attempt to fix this by actually ensuring there's a `_window` in
`AppHost::_WindowInitializedHandler`

Closes #16235
2023-11-06 22:45:24 +00:00
Taha Haksal
a5c269b280 Added selectionBackground to light color schemes (#16243)
Add a selectionBackground property which is set to the scheme's
brightBlack too all 3 of the light color schemes.

Related to #8716
It does not close the bug because as mentioned in the issue, when you
input numbers, they seem to be invisible in the light color schemes and
selecting them with the cursor doesn't reveal them.
2023-11-06 14:42:56 -08:00
Leonard Hecker
17cc109081 Remove conhost telemetry (#16253)
The `Telemetry` class was implemented as a singleton which stood in
my long-term goal to remove all global variables from the project.
Most telemetry captured by it hasn't been looked at for a long time
and just as much is now pointless (e.g.,`_fCtrlPgUpPgDnUsed`).
This removes the code.

## Validation Steps Performed
* Still compiles 
2023-11-06 22:00:40 +00:00
Leonard Hecker
9e86c9811f Fix the fix for the fix of nearby font loading (#16196)
I still don't know how to reproduce it properly, but I'm slowly
wrapping my head around how and why it happens. The issue isn't that
`FindFamilyName` fails with `exists=FALSE`, but rather that any of the
followup calls like `GetDesignGlyphMetrics` fails, which results in an
exception and subsequently in an orderly fallback to Consolas.
I've always thought that the issue is that even with the nearby font
collection we get an `exists=FALSE`... I'm not sure why I thought that.

This changeset also drops the fallback iteration for Lucida Console and
Courier New, because I felt like the code looks neater that way and I
think it's a reasonable expectation that Consolas is always installed.

Closes #16058
2023-11-06 15:30:03 -06:00
Leonard Hecker
0289cb043c AtlasEngine: Minor bug fixes (#16219)
This commit fixes 4 minor bugs:
* Forgot to set the maximum swap chain latency. Without it, it defaults
  to up to 3 frames of latency. We don't need this, because our renderer
  is simple and fast and is expected to draw frames within <1ms.
* ClearType treats the alpha channel as ignored, whereas custom shaders
  can manipulate the alpha channel freely. This meant that using both
  simultaneously would produce weird effects, like text having black
  background. We now force grayscale AA instead.
* The builtin retro shader should not be effected by the previous point.
* When the cbuffer is entirely unused in a custom shader, it has so far
  resulted in constant redraws. This happened because the D3D reflection
  `GetDesc` call will then return `E_FAIL` in this situation.
  The new code on the other hand will now assume that a failure
  to get the description is equal to the variable being unused.

Closes #15960

## Validation Steps Performed
* A custom passthrough shader works with grayscale and ClearType AA
  while also changing the opacity with Ctrl+Shift+Scroll 
* Same for the builtin retro shader, but ClearType works 
* The passthrough shader doesn't result in constant redrawing 
2023-10-31 14:25:41 +01:00
Dustin L. Howett
19efcfee9d Fix spelling after inbox merge 2023-10-27 17:23:57 -05:00
Dustin L. Howett
49c177f219 Merge inbox back into main after the 1.19 ingestion 2023-10-27 17:22:09 -05:00
Dustin Howett
68b5e58754 Merged PR 9792152: [Git2Git] Build fixes on top of 188a2ae4c
Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_we_adept_e4d2 3fc4bb99c75451d0ecadd7e4c8fe06ad67217574

Related work items: MSFT-47266988
2023-10-27 22:20:07 +00:00
Dustin Howett
16bac45714 Migrate OSS up to 188a2ae4c (v1.19-pre) 2023-10-26 14:25:39 -05:00
Mike Griese
188a2ae4c8 Clear the system menu when we refrigerate a window (#16225)
As in the title. Also fixes a crash for refrigeration with the rainbow
border.

Closes #16211

Tested by manually forcing us into Windows 10 mode (to refrigerate the
window). That immediately repros the bug, which was simple enough to
fix.

(cherry picked from commit d8c7719bfb)
Service-Card-Id: 90928408
Service-Version: 1.19
2023-10-26 14:24:29 -05:00
Leonard Hecker
c2fde69ff5 Fix UIA and marks regressions due to cooked read (#16105)
The initial cooked read (= conhost readline) rewrite had two flaws:
* Using viewport scrolls under ConPTY to avoid emitting newlines
resulted in various bugs around marks, coloring, etc. It's still
somewhat unclear why this happened, but the next issue is related and
much worse.
* Rewriting the input line every time causes problems with accessibility
tools, as they'll re-announce unchanged parts again and again.

The solution to these is to simply stop writing the unchanged parts of
the prompt. To do this, code was added to measure the size of text
without actually inserting them into the buffer. Since this meant that
the "interactive" mode of `WriteCharsLegacy` would need to be duplicated
for the new code, I instead moved those parts into `COOKED_READ_DATA`.
That way we can now have the interactive transform of the prompt (=
Ctrl+C -> ^C) and the two text functions (measure text & actually write
text) are now agnostic to this transformation.

Closes #16034
Closes #16044

## Validation Steps Performed
* A vision impaired user checked it out and it seemed fine 

(cherry picked from commit e1c69a99ce)
Service-Card-Id: 90891693
Service-Version: 1.19
2023-10-26 14:24:28 -05:00
Leonard Hecker
798ab586f1 Fix rectangular clipboard copying initiated from the app menu (#16197)
cd6b083 had 2 issues:
* Improper testing with Ctrl+M instead of Edit > Mark.
* Wrong SelectionState function being used. When the selection is
  initiated without keyboard or mouse, `IsKeyboardMarkSelection`
  returns false. The proper function to use is `IsLineSelection`.

Closes #15153

## Validation Steps Performed
* Run Far
* Start selection via Edit>Mark
* Hold Alt while dragging to make a rectangular selection
* Right click
* Clipboard contains a rectangular copy 

(cherry picked from commit d496a5fb80)
Service-Card-Id: 90886368
Service-Version: 1.19
2023-10-26 14:24:26 -05:00
Leonard Hecker
9892ade4e0 COOKED_READ: Fix reference counting woes (#16187)
This restores the original code from before 821ae3a where
the `.GetMainBuffer()` call was accidentally removed.

Closes #16158

## Validation Steps Performed
* Run this Python script:
  ```py
  import sys
  while True:
    sys.stdout.write("\033[?1049h")
    sys.stdout.flush()
    sys.stdin.readline()
    sys.stdout.write("\033[?1049l")
  ```
* Press enter repeatedly
* Doesn't crash 

(cherry picked from commit 08f30330d1)
Service-Card-Id: 90861143
Service-Version: 1.19
2023-10-26 14:24:25 -05:00
Leonard Hecker
7fd476d9ed env: properly handle nulls in REG_SZ strings (#16190)
eb871bf fails to properly handle REG_SZ strings, which are documented as
being null-terminated _and_ length restricted.
`wcsnlen` is the perfect fit for handling this situation as it returns
the position of the first \0, or the given length parameter.

As a drive by improvement, this also drops some redundant code:
* `to_environment_strings_w` which is the same as `to_string`
* Retrieving `USERNAME`/`USERDOMAIN` via `LookupAccountSidW` and
  `COMPUTERNAME` via `GetComputerNameW` is not necessary as the
  variables are "volatile" and I believe there's generally no
  expectation that they change unless you log in again.

Closes #16051

## Validation Steps Performed
* Run this in PowerShell to insert a env value with \0:
  ```pwsh
  $hklm = [Microsoft.Win32.RegistryKey]::OpenBaseKey(
    [Microsoft.Win32.RegistryHive]::LocalMachine,
    0
  )
  $key = $hklm.OpenSubKey(
    'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',
    $true
  )
  $key.SetValue('test', "foo`0bar")
  ```
* All `EnvTests` still pass 
* (Don't forget to remove the above value again!)

(cherry picked from commit 64b5b2884a)
Service-Card-Id: 90879164
Service-Version: 1.19
2023-10-26 14:24:24 -05:00
Mike Griese
c0275018ea Fix the color of marks (#16106)
Guess what _doesn't_ have the same layout as a bitmap? A `til::color`.

Noticed in 1.19.

Regressed in #16006

(cherry picked from commit 1745857407)
Service-Card-Id: 90758500
Service-Version: 1.19
2023-10-26 14:24:22 -05:00
Jaswir
229ba89c83 Allow Opacity to be set differently in both focused and unfocused terminals (#15974)
## Summary of the Pull Request
Closes #11092

Allowing `opacity `to be set differently in both focused and unfocused
terminals

## References and Relevant Issues
#11092 , references: #7158

## Detailed Description of the Pull Request / Additional comments

### Allowing Opacity to be set differently in both focused and unfocused
terminals:

![unfocused_opacity](https://github.com/microsoft/terminal/assets/15957528/1c38e40b-4678-43ec-b328-ad79d222579f)

![image](https://github.com/microsoft/terminal/assets/15957528/3e3342a8-7908-41db-9c37-26c89f7f2456)

![jolsen](https://github.com/microsoft/terminal/assets/15957528/68553507-d29e-4513-89ce-b1cd305d28b7)

![image](https://github.com/microsoft/terminal/assets/15957528/18864f60-91d0-4159-87da-2b2ee1637a4c)

## `_runtimeFocusedOpacity`

Mike also had to say something about this:
https://github.com/microsoft/terminal/issues/2531#issuecomment-1668442774

Initially I had something like ` _setOpacity(newAppearance->Opacity());`

But with the introduction of unfocused opacity we encounter new
challenges:
When Adjusting the Opacity with **CTRL+SHIFT+Mouse Scroll Wheel** or
**Set background opacity** in command pallette, the Runtime opacity
changes, but when we go to unfocused and back to focused the opacity
changes back to focused opacity in Settings.

Also when adjusting opacity through the command palette the window
becomes unfocused and then focused again after setting background
opacity hence the ` _setOpacity(newAppearance->Opacity());` would
override the changes made through command palette

![runtimeFocusedOpacity](https://github.com/microsoft/terminal/assets/15957528/4de63057-d658-4b5e-99ad-7db050834ade)

![command_pallette_focusswitches](https://github.com/microsoft/terminal/assets/15957528/372526eb-cf0c-40f8-a4e5-a0739f1f0e05)

With the introduction of unfocused opacity we encounter new challenges.
The runtime opacity stores both the unfocused opacity and focused
opacity from settings at different moments. This all works well until we
combine this with Adjusting the Opacity with **CTRL+SHIFT+Mouse Scroll
Wheel** or **Set background opacity** in command pallette. This brings
the need for a separate Focused Opacity. When we change the runtime
opacity with scroll wheel or through command pallette this value needs
to be stored separately from the one in settings. So we can change back
to it when going to unfocused mode and back to focused instead of the
focused opacity defined in settings.

## `skipUnfocusedOpacity` solves Opacity going from solid to unfocused
to focused bug:

![skipUnfocusedOpacity_bug](https://github.com/microsoft/terminal/assets/15957528/ecc06dcf-fbef-4fef-a40f-68278fdbfb12)

## Validation Steps Performed

- Checked if unfocused Opacity works well when adjusting opacity through
Mouse Scroll Wheel or Command Palette and in combination with Acrylic as
mentioned in "Detailed Description of the Pull Request / Additional
comments"

## PR Checklist

- [x] Closes #11092
- [ ] Tests added/passed
- [x] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it
here:(https://github.com/MicrosoftDocs/terminal/pull/714)
- [ ] Schema updated (if necessary)

(cherry picked from commit 27e1081c8c)
Service-Card-Id: 90949918
Service-Version: 1.19
2023-10-26 14:24:21 -05:00
Dustin L. Howett
b6593e713e build: pass branding into the nuget variable template (#16122)
This fixes a cosmetic issue with the version number in the unpackaged
builds and NuGet packages.

They were showing up as `-preview`, even when they were stable, because
the variable template didn't know about the branding.

(cherry picked from commit 544cdd78af)
Service-Card-Id: 90786432
Service-Version: 1.19
2023-10-26 14:24:20 -05:00
Dustin Howett
7e2be66ec5 Migrate OSS up to 145c4d364 (v1.19.2831.0)
# Conflicts:
#	src/buffer/out/textBuffer.cpp
2023-10-25 13:46:47 -05:00
Dustin Howett
4b58fc6c8e Migrate sources.dep changes from OS 2023-10-25 13:46:06 -05:00
js324
d0d3039963 add single quotes to WSL drag and drop (#16214)
Wrap single quotes to drag and dropped paths in WSL

## References and Relevant Issues
#15646  , #8109 

## Detailed Description of the Pull Request / Additional comments
First time contributor, from what I understand from reading #15646 and #8109 , issue is asking for single quotes added to a drag and dropped path always, regardless of whitespace and special characters, in WSL.

## Validation Steps Performed
Tested drag and drop changes in WSL and non WSL sources.

Closes #15646
2023-10-24 14:46:56 -07:00
Mike Griese
d8c7719bfb Clear the system menu when we refrigerate a window (#16225)
As in the title. Also fixes a crash for refrigeration with the rainbow
border.

Closes #16211

Tested by manually forcing us into Windows 10 mode (to refrigerate the
window). That immediately repros the bug, which was simple enough to
fix.
2023-10-24 11:28:59 -07:00
Leonard Hecker
e1c69a99ce Fix UIA and marks regressions due to cooked read (#16105)
The initial cooked read (= conhost readline) rewrite had two flaws:
* Using viewport scrolls under ConPTY to avoid emitting newlines
resulted in various bugs around marks, coloring, etc. It's still
somewhat unclear why this happened, but the next issue is related and
much worse.
* Rewriting the input line every time causes problems with accessibility
tools, as they'll re-announce unchanged parts again and again.

The solution to these is to simply stop writing the unchanged parts of
the prompt. To do this, code was added to measure the size of text
without actually inserting them into the buffer. Since this meant that
the "interactive" mode of `WriteCharsLegacy` would need to be duplicated
for the new code, I instead moved those parts into `COOKED_READ_DATA`.
That way we can now have the interactive transform of the prompt (=
Ctrl+C -> ^C) and the two text functions (measure text & actually write
text) are now agnostic to this transformation.

Closes #16034
Closes #16044

## Validation Steps Performed
* A vision impaired user checked it out and it seemed fine 
2023-10-23 17:27:01 -07:00
Leonard Hecker
d496a5fb80 Fix rectangular clipboard copying initiated from the app menu (#16197)
cd6b083 had 2 issues:
* Improper testing with Ctrl+M instead of Edit > Mark.
* Wrong SelectionState function being used. When the selection is
  initiated without keyboard or mouse, `IsKeyboardMarkSelection`
  returns false. The proper function to use is `IsLineSelection`.

Closes #15153

## Validation Steps Performed
* Run Far
* Start selection via Edit>Mark
* Hold Alt while dragging to make a rectangular selection
* Right click
* Clipboard contains a rectangular copy 
2023-10-20 11:10:31 -05:00
Leonard Hecker
08f30330d1 COOKED_READ: Fix reference counting woes (#16187)
This restores the original code from before 821ae3a where
the `.GetMainBuffer()` call was accidentally removed.

Closes #16158

## Validation Steps Performed
* Run this Python script:
  ```py
  import sys
  while True:
    sys.stdout.write("\033[?1049h")
    sys.stdout.flush()
    sys.stdin.readline()
    sys.stdout.write("\033[?1049l")
  ```
* Press enter repeatedly
* Doesn't crash 
2023-10-18 17:47:19 -07:00
Leonard Hecker
64b5b2884a env: properly handle nulls in REG_SZ strings (#16190)
eb871bf fails to properly handle REG_SZ strings, which are documented as
being null-terminated _and_ length restricted.
`wcsnlen` is the perfect fit for handling this situation as it returns
the position of the first \0, or the given length parameter.

As a drive by improvement, this also drops some redundant code:
* `to_environment_strings_w` which is the same as `to_string`
* Retrieving `USERNAME`/`USERDOMAIN` via `LookupAccountSidW` and
  `COMPUTERNAME` via `GetComputerNameW` is not necessary as the
  variables are "volatile" and I believe there's generally no
  expectation that they change unless you log in again.

Closes #16051

## Validation Steps Performed
* Run this in PowerShell to insert a env value with \0:
  ```pwsh
  $hklm = [Microsoft.Win32.RegistryKey]::OpenBaseKey(
    [Microsoft.Win32.RegistryHive]::LocalMachine,
    0
  )
  $key = $hklm.OpenSubKey(
    'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',
    $true
  )
  $key.SetValue('test', "foo`0bar")
  ```
* All `EnvTests` still pass 
* (Don't forget to remove the above value again!)
2023-10-18 17:46:16 -07:00
Mike Griese
1745857407 Fix the color of marks (#16106)
Guess what _doesn't_ have the same layout as a bitmap? A `til::color`.

Noticed in 1.19.

Regressed in #16006
2023-10-17 12:11:54 -07:00
AtariDreams
f2c3ddd105 Flip bits instead of checking for them (#16160)
No need to check for if a bit is set before manually clearing or setting
them when xor will do the trick.
2023-10-13 15:47:56 -05:00
Leonard Hecker
0b9f041706 Fix issues and warnings caused by profiles.schema.json (#16103)
This addresses the following issues:
* The JSON Schema spec doesn't actually define whether objects with
  a "properties" key still require `"type": "object"` or not.
  VS Code for instance largely pretends as if it's implied, but when it
  encounters them inside a `oneOf` tree, then it behaves as if it isn't.
  In other words, we need to always set `"type": "object"`.
* Declaring an `oneOf` containing a `"type": "string"` and an `enum`
  doesn't work, because if one of the `enum` cases is given, it results
  in both variants to match, since any `enum` is also a `string`.
  We have to use `anyOf` instead.
* `SuggestionSource` used `"BuiltinSuggestionSource"` inside a `type`
  key which doesn't work. We have to use `$ref` for that.

Closes #13387

## Validation Steps Performed
* VS Code stops complaining 
* https://www.jsonschemavalidator.net/ 
2023-10-13 15:44:14 -05:00
Jaswir
27e1081c8c Allow Opacity to be set differently in both focused and unfocused terminals (#15974)
## Summary of the Pull Request
Closes #11092 

Allowing `opacity `to be set differently in both focused and unfocused
terminals

## References and Relevant Issues
#11092 , references: #7158 

## Detailed Description of the Pull Request / Additional comments

### Allowing Opacity to be set differently in both focused and unfocused
terminals:

![unfocused_opacity](https://github.com/microsoft/terminal/assets/15957528/1c38e40b-4678-43ec-b328-ad79d222579f)

![image](https://github.com/microsoft/terminal/assets/15957528/3e3342a8-7908-41db-9c37-26c89f7f2456)


![jolsen](https://github.com/microsoft/terminal/assets/15957528/68553507-d29e-4513-89ce-b1cd305d28b7)


![image](https://github.com/microsoft/terminal/assets/15957528/18864f60-91d0-4159-87da-2b2ee1637a4c)

## `_runtimeFocusedOpacity`

Mike also had to say something about this:
https://github.com/microsoft/terminal/issues/2531#issuecomment-1668442774

Initially I had something like ` _setOpacity(newAppearance->Opacity());`

But with the introduction of unfocused opacity we encounter new
challenges:
When Adjusting the Opacity with **CTRL+SHIFT+Mouse Scroll Wheel** or
**Set background opacity** in command pallette, the Runtime opacity
changes, but when we go to unfocused and back to focused the opacity
changes back to focused opacity in Settings.

Also when adjusting opacity through the command palette the window
becomes unfocused and then focused again after setting background
opacity hence the ` _setOpacity(newAppearance->Opacity());` would
override the changes made through command palette

![runtimeFocusedOpacity](https://github.com/microsoft/terminal/assets/15957528/4de63057-d658-4b5e-99ad-7db050834ade)


![command_pallette_focusswitches](https://github.com/microsoft/terminal/assets/15957528/372526eb-cf0c-40f8-a4e5-a0739f1f0e05)

With the introduction of unfocused opacity we encounter new challenges.
The runtime opacity stores both the unfocused opacity and focused
opacity from settings at different moments. This all works well until we
combine this with Adjusting the Opacity with **CTRL+SHIFT+Mouse Scroll
Wheel** or **Set background opacity** in command pallette. This brings
the need for a separate Focused Opacity. When we change the runtime
opacity with scroll wheel or through command pallette this value needs
to be stored separately from the one in settings. So we can change back
to it when going to unfocused mode and back to focused instead of the
focused opacity defined in settings.

## `skipUnfocusedOpacity` solves Opacity going from solid to unfocused
to focused bug:

![skipUnfocusedOpacity_bug](https://github.com/microsoft/terminal/assets/15957528/ecc06dcf-fbef-4fef-a40f-68278fdbfb12)

## Validation Steps Performed

- Checked if unfocused Opacity works well when adjusting opacity through
Mouse Scroll Wheel or Command Palette and in combination with Acrylic as
mentioned in "Detailed Description of the Pull Request / Additional
comments"

## PR Checklist

- [x] Closes #11092 
- [ ] Tests added/passed
- [x] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it
here:(https://github.com/MicrosoftDocs/terminal/pull/714)
- [ ] Schema updated (if necessary)
2023-10-13 15:43:38 -05:00
Muhammad Danish
ee17d6c55e Update note regarding WinGet installation (#16159)
## Summary of the Pull Request

Dependency support is now GA in WinGet. Updating the instructions in
README

## References and Relevant Issues

## Detailed Description of the Pull Request / Additional comments

## Validation Steps Performed

## PR Checklist
- [ ] Closes #xxx
- [ ] Tests added/passed
- [ ] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [ ] Schema updated (if necessary)
2023-10-12 15:14:56 -05:00
Dustin L. Howett
544cdd78af build: pass branding into the nuget variable template (#16122)
This fixes a cosmetic issue with the version number in the unpackaged
builds and NuGet packages.

They were showing up as `-preview`, even when they were stable, because
the variable template didn't know about the branding.
2023-10-11 12:58:55 -05:00
Mike Griese
0144cdd7bc Don't end the current mark, if we get one of the same kind (#16107)
If you're already in the "output" state, then an app requesting an
"output" mark probably shouldn't end the current mark and start a new
one. It should just keep on keepin' on.

The decision to end the previous one was arbitrary in the first place,
so let's arbitrarily change it back.

Especially noticable if you hit <kbd>Enter</kbd> during a command,
because the auto-mark prompt work will do a CommandEnd, so long-running
commands will get broken into multiple marks 🥲
2023-10-11 11:40:40 -05:00
inisarg
af8e20c3b6 Dismiss "Failed to reload settings" modals when settings.json is valid (#16119)
Have added a conditional check in `TerminalWindow::UpdateSettings`
method

## PR Checklist
- [X] Closes #15987
2023-10-11 09:02:21 -05:00
Christopher Nguyen
d801375883 Update README with Canary info (#16125)
This PR updates the README with information about Windows Terminal
Canary.

---------

Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
2023-10-11 09:00:29 -05:00
Dustin L. Howett
4efee36376 Upgrade Microsoft.Windows.ImplementationLibrary to 1.0.230824.2 (#16120)
Built locally.
2023-10-11 08:58:01 -05:00
Dustin L. Howett
775e7ebe1f Port the nightly build pipeline to OneBranch as well (#16108)
This pull request also removes the original release and nightly
pipelines, but it does not remove the release pipeline _template_.

I had to demote the Azure job from being a _deployment_ to being a plain
old job, unfortunately. Alas! Review with whitespace disabled (or `git
diff -w`).
2023-10-06 13:16:10 -07:00
Mike Griese
145c4d3641 Bounds check some tab GetAt()s (#16016)
`GetAt` can throw if the index is out of range. We don't check that in
some places. This fixes some of those.

I don't think this will take care of #15689, but it might help?

(cherry picked from commit 5aadddaea9)
Service-Card-Id: 90731981
Service-Version: 1.19
2023-10-05 14:45:00 -05:00
Mike Griese
5aadddaea9 Bounds check some tab GetAt()s (#16016)
`GetAt` can throw if the index is out of range. We don't check that in
some places. This fixes some of those.

I don't think this will take care of #15689, but it might help?
2023-10-05 09:31:20 -05:00
Mike Griese
d0c228e95a Spec for the Suggestions UI (#14864)
## Summary of the Pull Request

> ## 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.
> 


## Detailed Description of the Pull Request / Additional comments

_\*<sup>\*</sup><sub>\*</sub> read the spec
<sub>\*</sub><sup>\*</sup>\*_

Similar to #14792, a lot of this code is written. This stuff isn't
checked in though, so I'm presenting formally before I start yeeting PRs
out there.

## PR Checklist
- [x] This is a spec for #1595. It also references:
  * #3121
  * #10436
  * #12927
  * #12863
2023-10-05 09:27:30 -05:00
Mike Griese
6ecdae796f Fix closeOnExit: always (#16090)
Well, Pane doesn't _only_ care if the connection isn't entering a
terminal state. It does need to update its own state first.

Regressed in #15335

Closes #16068

(cherry picked from commit 4145f18768)
Service-Card-Id: 90731934
Service-Version: 1.19
2023-10-03 15:42:06 -05:00
inisarg
f6e1126b77 Dismiss flyouts before opening warning dialog when exiting app (#16075)
Updated the function `TerminalPage::CloseWindow` to include logic for
closing context and flyout menus so that they are dismissed before the
warning is displayed.

Closes #16039

(cherry picked from commit aafb91745e)
Service-Card-Id: 90731989
Service-Version: 1.19
2023-10-03 15:42:04 -05:00
Mike Griese
4ee21b38b5 Fix a crash in the GenerateName for SearchForTextArgs (#16054)
Fixes MSFT:46725264

don't explode trying to parse a URL, if the string wasn't one.

(cherry picked from commit 59aaba7c5b)
Service-Card-Id: 90687770
Service-Version: 1.19
2023-10-03 15:42:03 -05:00
Mike Griese
70ad67053d Use weak_ptrs for AppHost for coroutines (#16065)
See MSFT:46763065. Looks like we're in the middle of being
`Refrigerate`d, we're pumping messages, and as we pump messages, we get
to a `co_await` in `AppHost::_WindowInitializedHandler`. When we resume,
we just try to use `this` like everything's fine but OH NO, IT'S NOT.

To fix this, I'm
* Adding `enable_shared_from_this` to `AppHost`
* Holding the `AppHost` in a shared_ptr in WindowThread
- though, this is a singular owning `shared_ptr`. This is probably ripe
for other footguns, but there's little we can do about this.
* whenever we `co_await` in `AppHost`, make sure we grab a weak ref
first, and check it on the other side.

This is another "squint and yep that's a bug" fix, that I haven't been
able to verify locally. This is

[allegedly](https://media.tenor.com/VQi3bktwLdIAAAAC/allegedly-supposedly.gif)
about 10% of our 1.19 crashes after 3 days.

Closes #16061

(cherry picked from commit 8521aae889)
Service-Card-Id: 90731962
Service-Version: 1.19
2023-10-03 15:42:01 -05:00
Mike Griese
47728dc38b Fix tearout with startupActions set. (#16089)
Wow our preview population must just not use `startupActions`. This
obviously never worked in 1.18 Preview.

Closes #16050

(cherry picked from commit f6425dbd59)
Service-Card-Id: 90715243
Service-Version: 1.19
2023-10-03 15:42:00 -05:00
Mike Griese
4145f18768 Fix closeOnExit: always (#16090)
Well, Pane doesn't _only_ care if the connection isn't entering a
terminal state. It does need to update its own state first.

Regressed in #15335

Closes #16068
2023-10-03 13:41:18 -07:00
inisarg
aafb91745e Dismiss flyouts before opening warning dialog when exiting app (#16075)
Updated the function `TerminalPage::CloseWindow` to include logic for
closing context and flyout menus so that they are dismissed before the
warning is displayed.

Closes #16039
2023-10-03 13:35:34 -07:00
Mike Griese
59aaba7c5b Fix a crash in the GenerateName for SearchForTextArgs (#16054)
Fixes MSFT:46725264

don't explode trying to parse a URL, if the string wasn't one.
2023-10-03 13:31:43 -07:00
Mike Griese
8521aae889 Use weak_ptrs for AppHost for coroutines (#16065)
See MSFT:46763065. Looks like we're in the middle of being
`Refrigerate`d, we're pumping messages, and as we pump messages, we get
to a `co_await` in `AppHost::_WindowInitializedHandler`. When we resume,
we just try to use `this` like everything's fine but OH NO, IT'S NOT.

To fix this, I'm
* Adding `enable_shared_from_this` to `AppHost`
* Holding the `AppHost` in a shared_ptr in WindowThread
- though, this is a singular owning `shared_ptr`. This is probably ripe
for other footguns, but there's little we can do about this.
* whenever we `co_await` in `AppHost`, make sure we grab a weak ref
first, and check it on the other side.

This is another "squint and yep that's a bug" fix, that I haven't been
able to verify locally. This is

[allegedly](https://media.tenor.com/VQi3bktwLdIAAAAC/allegedly-supposedly.gif)
about 10% of our 1.19 crashes after 3 days.

Closes #16061
2023-10-03 13:31:01 -07:00
Mike Griese
f6425dbd59 Fix tearout with startupActions set. (#16089)
Wow our preview population must just not use `startupActions`. This
obviously never worked in 1.18 Preview.

Closes #16050
2023-10-03 13:29:38 -07:00
Dustin L. Howett
b9cbf0f24c build: add a OneBranch Official release pipeline (#16081)
This pipeline does everything the existing release pipeline does, except
it does it using the OneBranch official templates.

Most of our existing build infrastructure has been reused, with the
following changes:

- We are no longer using `job-submit-windows-vpack`, as OneBranch does
this for us.
- `job-merge-msix-into-bundle` now supports afterBuildSteps, which we
use to stage the msixbundle into the right place for the vpack
- `job-build-project` supports deleting all non-signed files (which the
OneBranch post-build validation requires)
- `job-build-project` now deletes `console.dll`, which is unused in any
of our builds, because XFGCheck blows up on it for some reason on x86
- `job-publish-symbols` now supports two different types of PAT
ingestion
- I have pulled out the NuGet filename variables into a shared variables
template

I have also introduced a TSA config (which files bugs on us for binary
analysis failures as well as using the word 'sucks' and stuff.)

I have also baselined a number of control flow guard/binary analysis
failures.

(cherry picked from commit 6489f6b39d)
Service-Card-Id: 90706777
Service-Version: 1.19
2023-10-03 12:31:24 -05:00
Dustin L. Howett
6489f6b39d build: add a OneBranch Official release pipeline (#16081)
This pipeline does everything the existing release pipeline does, except
it does it using the OneBranch official templates.

Most of our existing build infrastructure has been reused, with the
following changes:

- We are no longer using `job-submit-windows-vpack`, as OneBranch does
this for us.
- `job-merge-msix-into-bundle` now supports afterBuildSteps, which we
use to stage the msixbundle into the right place for the vpack
- `job-build-project` supports deleting all non-signed files (which the
OneBranch post-build validation requires)
- `job-build-project` now deletes `console.dll`, which is unused in any
of our builds, because XFGCheck blows up on it for some reason on x86
- `job-publish-symbols` now supports two different types of PAT
ingestion
- I have pulled out the NuGet filename variables into a shared variables
template

I have also introduced a TSA config (which files bugs on us for binary
analysis failures as well as using the word 'sucks' and stuff.)

I have also baselined a number of control flow guard/binary analysis
failures.
2023-10-02 14:52:54 -05:00
Mike Griese
1669036e59 Add a note on how to build the Terminal in the OS repo (#16066)
It's been literally 4 years since I worked directly in the OS repo and I
forgot how to build the console 🤦
2023-09-29 20:01:38 -05:00
Dustin L. Howett
4c795b5bcd build: switch the EsrpCodeSigning task to version 3 (#16057)
The version we were using requires .NET 2.1 (wow) which is way out of
support.

Task version 3 supports much newer versions.

(cherry picked from commit ac2b0e744c)
Service-Card-Id: 90688108
Service-Version: 1.19
2023-09-29 15:26:31 -05:00
Dustin L. Howett
828c1ebf66 Fix CFG on our static-lib-only DLL projects (#16056)
Control Flow Guard requires both linker and compiler flags.

It turns out that the MSVC build rules determine whether to _link_ with
CFG based on whether it compiled anything with CFG.

It also turns out that when you don't compile anything (such as in our
DLL projects that only consume a static library!), the build rules can't
guess whether to link with CFG.

Whoops.
We need to force it.

(cherry picked from commit 1b143e34a8)
Service-Card-Id: 90688105
Service-Version: 1.19
2023-09-29 15:26:30 -05:00
Carlos Zamora
3eae898ddc [Schema] Fix incorrect default value for 'allowEmpty' (#16040)
(cherry picked from commit 4382a17352)
Service-Card-Id: 90686477
Service-Version: 1.19
2023-09-29 15:26:29 -05:00
Mike Griese
3e0b3e3925 Theoretical fix for some crashes (#16047)
Found this while looking through dumps for failure
`f544cf8e-1879-c59b-3f0b-1a364b92b974`. That's MSFT:45210947. (1% of our
1.19 crashes)

From the dump I looked at,

Looks like,

* we're on Windows 10
* We're refrigerating a window
* We are pumping the remaining XAML messages as we refrigerate
(`_pumpRemainingXamlMessages`)
* In there, we're finally getting the
`TerminalPage::_CompleteInitialization`
* that calls up to the `_root->Initialized` lambda set up in
`TerminalWindow::Initialize`
* There it tries to get the launch mode from the settings, and explodes.
Presumably _settings is null, but can't see in this dump.

so the window is closing before it's initialized.

When we `_warmWindow = std::move(_host->Refrigerate())`, we call
`AppHost::Refrigerate`, which will null out the TerminalWindow. So when
we're getting to `TerminalWindow::Initialize`, we're calling that on a
nullptr. That's the trick.

We need to revoke the internal Initialized callback. Which makes sense.
It's a lambda that binds _this_ 🤦

---

After more looking, it really doesn't _seem_ like the stacks that are
tracked in `f544cf8e-1879-c59b-3f0b-1a364b92b974` look like the same
stack that I was debugging, but this _is_ a realy issue regardless.

(cherry picked from commit 7073ec01bf)
Service-Card-Id: 90672654
Service-Version: 1.19
2023-09-29 15:26:28 -05:00
Leonard Hecker
057d1334db Fix URL sanitizer for long URLs (#16026)
f1aa699 was fundamentally incorrect as it used `IdnToAscii` and
`IdnToUnicode` on the entire URL, even though these functions only work
on domain names. This commit fixes the issue by using the WinRT `Url`
class and its `AbsoluteUri` and `AbsoluteCanonicalUri` getters.
The algorithm still works the same way though.

Closes #16017

## Validation Steps Performed
* ``"`e]8;;https://www.xn--fcbook-3nf5b.com/`e\test`e]8;;`e\"``
  still shows as two URLs in the popup 
* Shows the given URI if it's canonical and not an IDN 
* Works with >100 char long file:// URIs 

(cherry picked from commit 198c11f36d)
Service-Card-Id: 90642844
Service-Version: 1.19
2023-09-29 15:26:27 -05:00
Mike Griese
f1a868517c Fix a crash for users without a tab theme (#16046)
One day into 1.19, and there's a LOT of hits here (**76.25%** of our
~300 crashes). A crash if the Theme doesn't have a `tab` member.

Regressed in #15948

Closes MSFT:46714723

(cherry picked from commit cf193858f6)
Service-Card-Id: 90670731
Service-Version: 1.19
2023-09-29 15:26:25 -05:00
Dustin L. Howett
ac2b0e744c build: switch the EsrpCodeSigning task to version 3 (#16057)
The version we were using requires .NET 2.1 (wow) which is way out of
support.

Task version 3 supports much newer versions.
2023-09-29 11:25:13 -07:00
Dustin L. Howett
1b143e34a8 Fix CFG on our static-lib-only DLL projects (#16056)
Control Flow Guard requires both linker and compiler flags.

It turns out that the MSVC build rules determine whether to _link_ with
CFG based on whether it compiled anything with CFG.

It also turns out that when you don't compile anything (such as in our
DLL projects that only consume a static library!), the build rules can't
guess whether to link with CFG.

Whoops.
We need to force it.
2023-09-29 11:25:01 -07:00
Carlos Zamora
4382a17352 [Schema] Fix incorrect default value for 'allowEmpty' (#16040) 2023-09-29 05:49:34 -05:00
Dustin L. Howett
cc2ba5350d nightly: upload unpackaged to Az as well; force canary to 11+ (#16049)
Unfortunately, the appLicensing restricted capability we used to make
Canary installable without the store only works on Windows 11. Because
of that, we have to restrict the app package to Windows 11 and above.

I'd rather not leave Windows 10 users out in the cold, so this pull
request also publishes Canary builds to the public storage bucket with
the name `Microsoft.WindowsTerminalCanary_latest_x64.zip` (etc.)

The version number will be kept inside the archive. It remains to be
seen whether that is a good idea!

When combined with #16048, Canary builds from Azure will automatically
run in portable mode!
2023-09-28 15:32:30 -05:00
Dustin L. Howett
3fc5286052 Build unpackaged Canary distributions in portable mode (#16048)
I also added support to the unpackaged distribution script to produce
portable mode packages. It is off by default for AppX->ZIP builds and
**on** by default for Layout->ZIP builds.

This constitutes a change in behavior.
2023-09-28 13:25:26 -05:00
Mike Griese
7073ec01bf Theoretical fix for some crashes (#16047)
Found this while looking through dumps for failure
`f544cf8e-1879-c59b-3f0b-1a364b92b974`. That's MSFT:45210947. (1% of our
1.19 crashes)

From the dump I looked at,

Looks like,

* we're on Windows 10
* We're refrigerating a window
* We are pumping the remaining XAML messages as we refrigerate
(`_pumpRemainingXamlMessages`)
* In there, we're finally getting the
`TerminalPage::_CompleteInitialization`
* that calls up to the `_root->Initialized` lambda set up in
`TerminalWindow::Initialize`
* There it tries to get the launch mode from the settings, and explodes.
Presumably _settings is null, but can't see in this dump.

so the window is closing before it's initialized.

When we `_warmWindow = std::move(_host->Refrigerate())`, we call
`AppHost::Refrigerate`, which will null out the TerminalWindow. So when
we're getting to `TerminalWindow::Initialize`, we're calling that on a
nullptr. That's the trick.

We need to revoke the internal Initialized callback. Which makes sense.
It's a lambda that binds _this_ 🤦

---

After more looking, it really doesn't _seem_ like the stacks that are
tracked in `f544cf8e-1879-c59b-3f0b-1a364b92b974` look like the same
stack that I was debugging, but this _is_ a realy issue regardless.
2023-09-28 13:21:13 -05:00
Leonard Hecker
198c11f36d Fix URL sanitizer for long URLs (#16026)
f1aa699 was fundamentally incorrect as it used `IdnToAscii` and
`IdnToUnicode` on the entire URL, even though these functions only work
on domain names. This commit fixes the issue by using the WinRT `Url`
class and its `AbsoluteUri` and `AbsoluteCanonicalUri` getters.
The algorithm still works the same way though.

Closes #16017

## Validation Steps Performed
* ``"`e]8;;https://www.xn--fcbook-3nf5b.com/`e\test`e]8;;`e\"``
  still shows as two URLs in the popup 
* Shows the given URI if it's canonical and not an IDN 
* Works with >100 char long file:// URIs 
2023-09-28 15:46:26 +00:00
Mike Griese
cf193858f6 Fix a crash for users without a tab theme (#16046)
One day into 1.19, and there's a LOT of hits here (**76.25%** of our
~300 crashes). A crash if the Theme doesn't have a `tab` member.

Regressed in #15948

Closes MSFT:46714723
2023-09-28 09:34:03 -05:00
Tushar Singh
310814bb30 Use MSWord compatible RTF sequence for background text color (#16035)
The `GenRTF(...)` was using `\highlight` control word for sending
background text color in the RTF format during a copy command. This
doesn't work correctly, since many applications (E.g. MSWord) don't
support full RGB with `\highlight`, and instead uses an approximation of
what is received. For example, `rgb(197, 15, 31)` becomes `rgb(255, 0,
255)`. Also, the standard way of using background colors is `\cbN`
control word, which isn't supported as per the [RTF Spec 1.9.1]
in Word.

But it briefly mentioned a workaround at Pg. 23, which seems to work on
all the RTF editors I tested.

The PR makes the changes to use `\chshdng0\chcbpatN` for the background
coloring.

Also did some refactoring to make the implementation concise.

## Validation Steps Performed

Verified that the background is correctly copied on below editors:
- MSWord
- WordPad
- LibreOffice
- Outlook

[RTF Spec 1.9.1]: https://msopenspecs.azureedge.net/files/Archive_References/[MSFT-RTF].pdf
2023-09-27 12:50:09 -05:00
Leonard Hecker
aef2dbd076 Reimplement TextBuffer::Reflow (#15701)
Subjectively speaking, this commit makes 3 improvements:
* Most importantly, it now would work with arbitrary Unicode text.
  (No more `IsGlyphFullWidth` or DBCS handling during reflow.)
* Due to the simpler implementation it hopefully makes review of
  future changes and maintenance simpler. (~3x less LOC.)
* It improves perf. by 1-2 orders of magnitude.
  (At 120x9001 with a full buffer I get 60ms -> 2ms.)

Unfortunately, I'm not confident that the new code replicates the old
code exactly, because I failed to understand it. During development
I simply tried to match its behavior with what I think reflow should do.

Closes #797
Closes #3088
Closes #4968
Closes #6546
Closes #6901
Closes #15964
Closes MSFT:19446208

Related to #5800 and #8000

## Validation Steps Performed
* Unit tests 
* Feature tests 
* Reflow with a scrollback 
* Reflowing the cursor cell causes a forced line-wrap 
  (Even at the end of the buffer. )
* `color 8f` and reflowing retains the background color 
* Enter alt buffer, Resize window, Exit alt buffer 

(cherry picked from commit 74748394c1)
Service-Card-Id: 90642727
Service-Version: 1.19
2023-09-25 19:39:45 -05:00
Leonard Hecker
6183b27547 Fix the prompt sometimes not being erased properly (#15880)
A carriage return (enter key) will increase the _distanceEnd by up to
viewport-width many columns, since it increases the Y distance between
the start and end by 1 (it's a newline after all).
This will make _flushBuffer() think that the new _buffer is way longer
than the old one and so _erase() ends up not erasing the tail end of
the prompt, even if the new prompt is actually shorter.

This commit fixes the issue by separating the newline printing
out from the regular text printing loops.

## Validation Steps Performed
* Run cmd.exe
* Write "echo hello" and press Enter
* Write "foobar foo bar" (don't press Enter)
* Press F7, select "echo hello" and press Enter
* Previous prompt says "echo hello" 

(cherry picked from commit c7f30a86d7)
Service-Card-Id: 90642765
Service-Version: 1.19
2023-09-25 19:39:43 -05:00
Dustin L. Howett
b772b2da57 About: check PackageManager for updates in addition to Store (#16012)
With us adding a .appinstaller distribution of Canary, the Store
services update checker has beome insufficient to determine whether
there are package updates.

App Installer supports us checking for updates by using PackageManager
and the Package interfaces.

We'll use those instead of the Store services interface, and bail out
early if the App Installer gives us an answer.

(cherry picked from commit e0fc3bcd0a)
Service-Card-Id: 90644882
Service-Version: 1.19
2023-09-25 19:39:42 -05:00
Leonard Hecker
74748394c1 Reimplement TextBuffer::Reflow (#15701)
Subjectively speaking, this commit makes 3 improvements:
* Most importantly, it now would work with arbitrary Unicode text.
  (No more `IsGlyphFullWidth` or DBCS handling during reflow.)
* Due to the simpler implementation it hopefully makes review of
  future changes and maintenance simpler. (~3x less LOC.)
* It improves perf. by 1-2 orders of magnitude.
  (At 120x9001 with a full buffer I get 60ms -> 2ms.)

Unfortunately, I'm not confident that the new code replicates the old
code exactly, because I failed to understand it. During development
I simply tried to match its behavior with what I think reflow should do.

Closes #797
Closes #3088
Closes #4968
Closes #6546
Closes #6901
Closes #15964
Closes MSFT:19446208

Related to #5800 and #8000

## Validation Steps Performed
* Unit tests 
* Feature tests 
* Reflow with a scrollback 
* Reflowing the cursor cell causes a forced line-wrap 
  (Even at the end of the buffer. )
* `color 8f` and reflowing retains the background color 
* Enter alt buffer, Resize window, Exit alt buffer 
2023-09-25 17:28:51 -07:00
Leonard Hecker
c7f30a86d7 Fix the prompt sometimes not being erased properly (#15880)
A carriage return (enter key) will increase the _distanceEnd by up to
viewport-width many columns, since it increases the Y distance between
the start and end by 1 (it's a newline after all).
This will make _flushBuffer() think that the new _buffer is way longer
than the old one and so _erase() ends up not erasing the tail end of
the prompt, even if the new prompt is actually shorter.

This commit fixes the issue by separating the newline printing
out from the regular text printing loops.

## Validation Steps Performed
* Run cmd.exe
* Write "echo hello" and press Enter
* Write "foobar foo bar" (don't press Enter)
* Press F7, select "echo hello" and press Enter
* Previous prompt says "echo hello" 
2023-09-25 17:24:29 -07:00
Dustin L. Howett
e0fc3bcd0a About: check PackageManager for updates in addition to Store (#16012)
With us adding a .appinstaller distribution of Canary, the Store
services update checker has beome insufficient to determine whether
there are package updates.

App Installer supports us checking for updates by using PackageManager
and the Package interfaces.

We'll use those instead of the Store services interface, and bail out
early if the App Installer gives us an answer.
2023-09-25 17:24:16 -07:00
Dustin Howett
2ecfac80e7 pgo: PGO specifically for 1.19 branch 2023-09-25 13:42:35 -05:00
Dustin Howett
18dae6dae8 version: bump to 1.20 on main 2023-09-25 13:40:13 -05:00
Dustin L. Howett
86ad3c84cb nightly: deploy an appinstaller to an Azure storage account (!) (#16013)
After the nightly build completes, we'll automatically generate a
.appinstaller and publich it plus the msixbundle to an Azure Storage
account.

I had to add step/job customization to the publish step in the full
release pipeline template.

The .appinstaller hardcodes our XAML dependency, which makes it a bit of
a pain. We can revisit this later, and publish our dependencies
directly and automatically instead of hardcoding them.

I am considering moving the appinstaller generation step to the MSIX
bundling job, but this works right now and is not too terrible.

Closes #774
2023-09-22 22:36:39 +02:00
Mike Griese
29a22c9e8a Don't assert in debug before we're initialized (#16021)
When launching a debug Terminal, `_initializedTerminal` might still be false and the scrollbar might still be 0px tall. This causes the `assert(false)` condition within `_throttledUpdateScrollbar` to be hit.

Regressed in #16006
2023-09-22 10:21:40 -07:00
Leonard Hecker
41f7ed73c1 ConPTY: Fix missing flush on console mode changes (#15991)
Previously, all unknown escape sequences would lead to an immediate call
to `VtEngine::_Flush()`. This lead to problems with nushell which uses
FTCS marks that were unknown to us. Combined with the linewise redrawing
that nushell does, Terminal would get the prompt in two separate frames,
causing a slight flickering.

#14677 fixed this by suppressing the `_Flush()` call when unknown
sequences are encountered. Unfortunately, this triggered a bug due
to our somewhat "inconsistent" architecture in conhost:
`XtermEngine::WriteTerminalW` isn't just used to flush unknown sequences
but also used directly by `InputBuffer::PassThroughWin32MouseRequest`
to write its mouse sequence directly to the ConPTY host.
`VtEngine` already contains a number of specialized member functions
like `RequestWin32Input()` to ensure that `_Flush()` is called
immediately and another member could've been added to solve this issue.
This commit now adds `RequestMouseMode` in the same vein.

But I believe we can make the system more robust in general by using
eager flushing by default (= safe), similar to how a `write()` on a
TCP socket flushes by default, and instead only selectively pause and
unpause flushing with a system similar to `TCP_CORK`.

This seems to work fairly well, as it solves:
* The original nushell bug
* The new bug
* Improves overall throughput by ~33% (due to less flushing)

In particular the last point is noteworthy, as this commit removes
the last performance bottleneck in ConPTY that isn't `VtEngine`.
Around ~95% of all CPU and wall time is spent in there now and any
improvements to `VtEngine` should yield immediately results.

Closes #15711

## Validation Steps Performed
* Clone/Run https://github.com/chrisant996/repro_enable_mouse_input
* Hold Ctrl+Alt and circle with the mouse over the viewport
* Repro.exe prints the current cursor coordinates 
* Run nushell
* No flickering when typing in the prompt 
2023-09-21 16:56:34 -05:00
Leonard Hecker
d38bb906ec Replace WinRT clipboard API with Win32 for pasting (#15360)
The Win32 API is significantly faster than the WinRT one, in the order
of around 300-1000x depending on the CPU and CPU load.

This might slightly improve the situation around #15315, but I suspect
that it requires many more fixes. For instance, we don't really have a
single text input "queue" into which we write. Multiple routines that
`resume_background` just to `WriteFile` into the input pipe are thus
racing against each other, contributing to the laggy feeling.
I also fear that the modern Windows text stack might be inherently
RPC based too, producing worse lag with rising CPU load.

This might fix #14323

## Validation Steps Performed
* Paste text from Edge 
* Paste text from Notepad 
* Right click the address bar in Explorer, choose "Copy address",
  paste text into WT 

---------

Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
2023-09-21 21:55:06 +00:00
Leonard Hecker
fc4a37ee91 Avoid moving the selection while typing a search query (#15998)
This commit fixes 2 issues:
* `ControlCore::ScrollMarks()` would call `ResetIfStale`
  again while the search prompt hasn't changed.
  This has been fixed by using `_cachedSearchResultRows` as
  the indicator for whether it needs to be recreated or not.
* While typing a search query, the selection would move among the
  results with each typed character, because `MovePastCurrentSelection`
  would do what its name indicates. It has been renamed and rewritten
  to be `MoveToCurrentSelection`. To avoid breaking UIA, the previous
  `MovePastPoint` implementation was kept.

Since the new `MoveToCurrentSelection` function would not move past the
current selection anymore, changing the direction would not move past
the current result either. To fix this, we now don't invalidate the
search cache when changing the direction.

Closes #15954

## Validation Steps Performed
* Run ``"helloworld`n"*20`` in pwsh
* Search for "helloworld"
* While typing the characters the selection doesn't move 
* ...nor when searching downwards 
* ...nor when erasing parts of it 
* ...and it behaves identical in conhost 
2023-09-21 11:36:53 +00:00
Mike Griese
c1bdcf8b97 Don't update the settings, unless the theme actually changed (#16004)
`ImmersiveColorSet` gets sent more often than just on a theme change. It notably gets sent when the PC is locked, or the UAC prompt opens.

## Validation Steps Performed

Tested manually by setting the font to `garbo`and:
* locking, then logging back in. No dialog  
* UAC via run dialog + `regedit`. No dialog  
* Actually changing the OS theme. Dialog   

Closes #15732
2023-09-20 13:47:25 -07:00
Mike Griese
75f3d4f3df Use the control that requested the context menu, instead of the active one (#15999)
As mentioned in #15760

> > When you right-click on a non-active pane, it becomes active, but the context menu may be displayed before this happens, thus showing the Restart Connection item based the wrong pane's status.
> 
> As far as I can see, when a pane is (right)clicked:
> 
> 1. If unfocused, `Focus` is called. This goes through the `GotFocus` handler which eventually calls `tab->_UpdateActivePane(sender);`
> 2. `PointerPressed` is raised which eventually shows the context menu
> 
> The first point is done asynchronously, so may update the active pane too late when the menu is already displayed (despite both end up in the UI thread).

To fix this: we plumb the control that the context menu was opened for all the way through to where the event is actually handled (in `_PopulateContextMenu`)

* [x] Tested manually

Co-authored-by: Marco Pelagatti <1140981+mpela81@users.noreply.github.com>
2023-09-20 13:12:24 -07:00
Mike Griese
d272fc4644 Don't explode if we try to parse an empty keys (#16003)
Saving the SUI with an empty "keys" will persist `"keys": ""` to the
JSON.

The keychord parser tries to parse that.
`KeyChordSerialization.cpp@_fromString` returns a KeyChord with both
vkey and scancode set to 0, and the ctor asserts and explodes.

We shouldn't do that. 

Closes #13221
2023-09-20 09:46:38 -07:00
Mike Griese
9b986a16cf Fix enter to restart the first pane in a split (#16001)
I noticed this last week, but forgot to file. If you have a pair of
splits, and `exit -1` the first, you can't use `enter` to restart it.

This PR fixes that. Basically, `TerminalPage` registers it's
`_restartPaneConnection` handler when it makes a new `Pane` object. It
registers the callback straight to the `Pane`. However, when a `Pane`
gets split, it makes a _new_ `Pane` object, and moves the original
content into the new pane. `TerminalPage` however, would never hook up
its own callback to that newly created pane.

This fixes that.
2023-09-20 09:46:28 -07:00
Dustin L. Howett
059f7701f2 Merge PublicTerminalCore into TermControl (#15992)
This pull request moves HwndTerminal into Microsoft.Terminal.Control.Lib
and removes PublicTerminalCore completely.

Microsoft.Terminal.Control.dll now exports the C API from HwndTerminal.

This adds ~100kb to Microsoft.Terminal.Control.dll and ~1400kb to the
WPF package (per architecture) but with the coming interactivity
platform merge it's going to benefit us big time.
2023-09-20 15:21:55 +00:00
Leonard Hecker
b5333f64e5 Improve performance of scrollbar marks (#16006)
This replaces the use of a `<Canvas>` with an `<Image>` for drawing
scrollbar marks. Otherwise, WinUI struggles with the up to ~9000 UI
elements as they get dirtied every time the scrollbar moves.
(FWIW 9000 is not a lot and it should not struggle with that.)

The `<Image>` element has the benefit that we can get hold of a CPU-side
bitmap which we can manually draw our marks into and then swap them into
the UI tree. It draws the same 9000 elements, but now WinUI doesn't
struggle anymore because only 1 element gets invalidated every time.

Closes #15955

## Validation Steps Performed
* Fill the buffer with "e"
* Searching for "e" fills the entire thumb range with white 
* ...doesn't lag when scrolling around 
* ...updates quickly when adding newlines at the end 
* Marks sort of align with their scroll position 
2023-09-20 15:03:53 +00:00
Mike Griese
523edd7941 Don't crash when the checking for updates without a network (#16002)
You can't catch an A/V. 

Closes #15459
2023-09-20 06:35:53 -05:00
™️
394b942a56 Option to default to show icon in tab, hide tabicon or make icon in tab monochrome. (#15948)
Adding enum iconstyle for hiding the icon in the tab #8157 

## Summary of the Pull Request
Please confirm if I am on the right track.
## References and Relevant Issues

## Detailed Description of the Pull Request / Additional comments

## Validation Steps Performed

## PR Checklist
- [ ] Closes #8157
- [x] Tests added/passed
- [ ] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [ ] Schema updated (if necessary)
2023-09-19 20:13:21 +00:00
Mike Griese
59248de1e4 Allow inheriting env vars from wt again and other env var changes too (#15897)
This PR is a few things:

* part the first: Convert the `compatibility.reloadEnvironmentVariables`
setting to a per-profile one.
* The settings should migrate it from the user's old global place to the
new one.
  * We also added it to "Profile>Advanced" while I was here.
* Adds a new pair of commandline flags to `new-tab` and `split-pane`:
`--inheritEnvironment` / `--reloadEnvironment`
* On `wt` launch, bundle the entire environment that `wt` was spawned
with, and put it into the `Remoting.CommandlineArgs`, and give them to
the monarch (and ultimately, down to `TerminalPage` with the
`AppCommandlineArgs`). DO THIS ALWAYS.
* As a part of this, we’ll default to _reloading_ if there’s no explicit
commandline set, and _inheriting_ if there is.
* For example, `wt -- cmd` would inherit, and `wt -p “Command Prompt”`
would reload.[^1]
* This is a little wacky, but we’re trying to separate out the
intentions here:
* `wt -- cmd` feels like “I want to run cmd.exe (in a terminal tab)”.
That feels like the user would _like_ environment variables from the
calling process. They’re doing something more manual, so they get more
refined control over it.
* `wt` (or `wt -p “Command Prompt”`) is more like, “I want to run the
Terminal (or, my Command Prompt profile) using whatever the Terminal
would normally do”. So that feels more like a situation where it should
just reload by default. (Of course, this will respect their settings
here)

## References and Relevant Issues

https://github.com/microsoft/terminal/issues/15496#issuecomment-1692450231
has more notes.

## Detailed Description of the Pull Request / Additional comments
This is so VERY much plumbing. I'll try to leave comments in the
interesting parts.

## PR Checklist
- [x] This is not _all_ of #15496. We're also going to do a `-E foo=bar`
arg on top of this.
- [x] Tests added/passed
- [x] Schema updated

[^1]: In both these cases, plus the `environment` setting, of course.
2023-09-19 15:03:24 -05:00
MPela
2e91e9c6de Display connection state in tab and add context menu entry for restarting connection (#15760)
## Summary of the Pull Request
When a connection is Closed, show an indicator in the respective tab.
When the active pane's connection is Closed, show a "Restart Connection"
action in the right-click context menu and in the tab context menu.

## Validation Steps Performed
- Force close a connection, check the indicator is shown in the tab.
- Right-click on pane shows the Restart Connection action if its
connection is closed
- Right-click on tab shows the Restart Connection action if the active
pane's connection is closed
- Indicator is cleared after connection is restarted (no panes in closed
state)

## PR Checklist
- [x] Closes #14909 
- [x] Tests added/passed
- [ ] Documentation updated
- [ ] Schema updated (if necessary)
2023-09-19 12:01:29 -05:00
Carlos Zamora
3550e19751 Add Auto Prop Name to 'Delete Color Scheme' button (#15994)
Since the "delete color scheme" button is filled with an icon and a Text
Box, the text is not automatically exposed as the autoProp.Name for the
button. We have to do it manually just like we do for "delete profile".

Validated manually using accessibility insights

Closes #15984
2023-09-19 11:59:51 -05:00
Leonard Hecker
4370da9549 Add missing lock guards on Terminal access (#15894)
`Terminal` is used concurrently by at least 4 threads. The table
below lists the class members and the threads that access them
to the best of my knowledge. Where:
* UI: UI Thread
* BG: Background worker threads (`winrt::resume_background`)
* RD: Render thread
* VT: VT connection thread

|                                    | UI | BG | RD | VT |
|------------------------------------|----|----|----|----|
| `_pfnWriteInput`                   | x  | x  |    | x  |
| `_pfnWarningBell`                  |    |    |    | x  |
| `_pfnTitleChanged`                 |    |    |    | x  |
| `_pfnCopyToClipboard`              |    |    |    | x  |
| `_pfnScrollPositionChanged`        | x  | x  |    | x  |
| `_pfnCursorPositionChanged`        |    |    |    | x  |
| `_pfnTaskbarProgressChanged`       |    |    |    | x  |
| `_pfnShowWindowChanged`            |    |    |    | x  |
| `_pfnPlayMidiNote`                 |    |    |    | x  |
| `_pfnCompletionsChanged`           |    |    |    | x  |
| `_renderSettings`                  | x  |    | x  | x  |
| `_stateMachine`                    | x  |    |    | x  |
| `_terminalInput`                   | x  |    |    | x  |
| `_title`                           | x  |    | x  | x  |
| `_startingTitle`                   | x  |    | x  |    |
| `_startingTabColor`                | x  |    |    |    |
| `_defaultCursorShape`              | x  |    |    | x  |
| `_systemMode`                      |    | x  | x  | x  |
| `_snapOnInput`                     | x  | x  |    |    |
| `_altGrAliasing`                   | x  |    |    |    |
| `_suppressApplicationTitle`        | x  |    |    | x  |
| `_trimBlockSelection`              | x  |    |    |    |
| `_autoMarkPrompts`                 | x  |    |    |    |
| `_taskbarState`                    | x  |    |    | x  |
| `_taskbarProgress`                 | x  |    |    | x  |
| `_workingDirectory`                | x  |    |    | x  |
| `_fontInfo`                        | x  |    | x  |    |
| `_selection`                       | x  | x  | x  | x  |
| `_blockSelection`                  | x  | x  | x  |    |
| `_wordDelimiters`                  | x  | x  |    |    |
| `_multiClickSelectionMode`         | x  | x  | x  |    |
| `_selectionMode`                   | x  | x  | x  |    |
| `_selectionIsTargetingUrl`         | x  | x  | x  |    |
| `_selectionEndpoint`               | x  | x  | x  |    |
| `_anchorInactiveSelectionEndpoint` | x  | x  | x  |    |
| `_mainBuffer`                      | x  | x  | x  | x  |
| `_altBuffer`                       | x  | x  | x  | x  |
| `_mutableViewport`                 | x  |    | x  | x  |
| `_scrollbackLines`                 | x  |    |    |    |
| `_detectURLs`                      | x  |    |    |    |
| `_altBufferSize`                   | x  | x  | x  | x  |
| `_deferredResize`                  | x  |    |    | x  |
| `_scrollOffset`                    | x  | x  | x  | x  |
| `_patternIntervalTree`             | x  | x  | x  | x  |
| `_lastKeyEventCodes`               | x  |    |    |    |
| `_currentPromptState`              | x  |    |    | x  |

Only 7 members are specific to one thread and don't require locking.
All other members require some for of locking to be safe for use.

To address the issue this changeset adds `LockForReading/LockForWriting`
calls everywhere `_terminal` is accessed in `ControlCore/HwndTerminal`.
Additionally, to ensure these issues don't pop up anymore, it adds to
all `Terminal` functions a debug assertion that the lock is being held.

Finally, because this changeset started off rather modest, it contains
changes that I initially made without being aware about the extent of
the issue. It simplifies the access around `_patternIntervalTree` by
making `_InvalidatePatternTree()` directly use that member.
Furthermore, it simplifies `_terminal->SetCursorOn(!IsCursorOn())` to
`BlinkCursor()`, allowing the code to be shared with `HwndTerminal`.

Ideally `Terminal` should not be that much of a class so that we don't
need such coarse locking. Splitting out selection and rendering state
should allow deduplicating code with conhost and use finer locking.

Closes #9617

## Validation Steps Performed
I tried to use as many Windows Terminal features as I could and fixed
every occurrence of `_assertLocked()` failures.
2023-09-19 11:59:39 -05:00
Mike Griese
f494d68f11 Fix some smaller broadcast bugs (#15993)
## Summary of the Pull Request

Resolves the following in #15812 

> - [x] `toggleBroadcastInput` isn't in the default settings
> - [x] The cursors forget to keep blinking if you focus each pane and
then unfocus them
> - [x] They don't stop blinking when you unbroadcast
> - [x] Broadcast border doesn't appear when you make new panes, but
they ARE broadcasted-to!

## References and Relevant Issues
x-ref:
* #2634
* #14393

## Detailed Description of the Pull Request / Additional comments

There was literally no logic in the original PR for starting the cursor
blinking. It's entirely unknowable how that ever worked. This makes it
all much more explicit.

We're taking the hacky `DisplayCursorWhileBlurred` from #15363, and
promoting that to the less-hacky `CursorVisibility`. Broadcast input
mode can use that to force the cursor to be visible always.


The last checkbox in that issue is harder, and I didn't want to further
pollute this delta with the paste plumbing.
2023-09-19 09:51:30 -05:00
inisarg
5f9624f6ea Make duplicate tabs consider the existing configuration option for its insertion (#15972)
Previously, the duplication method considered only the next to the selected tab(`tab.TabViewIndex() + 1`) as the insert position. Changed that to consider the setting.

Closes #15776
2023-09-18 15:22:38 -07:00
Mike Griese
8daf89e318 Add an openAbout action. (#15990)
Just as it says on the label.
Closes #15986
2023-09-18 11:55:05 -05:00
Leonard Hecker
1f3779e05a AtlasEngine: Harden against invalid soft fonts (#15889)
This is a theoretical improvement for #15553 where Windows Terminal
crashed due to AtlasEngine accessing the soft font bitmap outside of
bounds. The problem is that the soft font cell size was non-zero.
This PR hardens against such situations by checking whether the
requested soft font index is inside the bounds of the bitmaps.
The improvement couldn't be tested as it couldn't be reproduced.
2023-09-18 15:53:45 +00:00
Leonard Hecker
741633ef7a ConPTY: Avoid WINDOW_BUFFER_SIZE_EVENT when the viewport moves (#15935)
`SetConsoleWindowInfoImpl` calls `PostUpdateWindowSize`, which emits a
`CM_SET_WINDOW_SIZE` event, which causes `_InternalSetWindowSize` to be
called, which calls `ScreenBufferSizeChange` which then finally emits a
`WINDOW_BUFFER_SIZE_EVENT` event into the client input buffer.

This messes up applications like which make use of
`WINDOW_BUFFER_SIZE_EVENT` to perform potentially lossy operations.
In case of SSH this results in a resize (SIGWINCH) of the server-side
screen which similarly may result in a response by the shell, etc.
Since that happens over networks and is async, and because our conhost
VT viewport implementation appears to have a number of subtle bugs,
this results in duplicate output lines (sometimes hundreds).

Under Windows Terminal this issue is not as apparent, since ConPTY has
no viewport that can be moved and no scrollback. It only appears as an
issue if a terminal application reacts poorly to the SIGWINCH event.

Closes #15769

## Validation Steps Performed
* Set a breakpoint in `SynthesizeWindowBufferSizeEvent`
* Launch WSL and cause the viewport to move down
  No calls to `SynthesizeWindowBufferSizeEvent` 
* Execute `tput reset`
  Input line moves to row 0 
2023-09-18 15:53:24 +00:00
Dustin L. Howett
2fa8e766bb Stage WinAppDriver into its own folder (#15953)
WinAppDriver depends on a bunch of .NET assemblies that collide *big time*. Let's just quarantine it.

I kept the fallback to $TESTDIR\WinAppDriver.exe because there's a chance that the Windows build depends on it.
2023-09-15 12:59:00 -07:00
Jaswir
4bc34e490c Fix a bug when changing EnableUnfocusedAcrylic at runtime (#15944)
Closes #15943
2023-09-13 12:52:22 -05:00
Dustin L. Howett
37b0cfd32b Fix a number of minor issues that Clang flagged (again!) (#15952)
* `[[nodiscard]]` and `[[maybe_unused]]` must come before `virtual` and
  `static` qualifiers
* We were calling the jsoncpp constructors directly (again) as functions
  (again)
* Some of our preprocessor `#endif` lines were quite messed up
  (`-Winvalid-token`)
* One of our test projects was using somebody else's `precomp.h`

Related to #14871
2023-09-11 20:20:11 +00:00
Leonard Hecker
4ddfc3eaf3 COOKED_READ_DATA: Fix scrolling under ConPTY (#15930)
This commit fixes 3 bugs:
* `COOKED_READ_DATA` failed to initialize its `_distanceCursor` and
  `_distanceEnd` members. I took this as an opportunity to make them
  `ptrdiff_t`, to reduce the likelihood of overflows in the future.
* `COOKED_READ_DATA::_writeChars` added `scrollY` to the written
  distance, even though `WriteCharsLegacy` writes a negative value into
  that out parameter. This was fixed by changing `WriteCharsLegacy` to
  write positive values and by adding a debug assertion.
* `StreamScrollRegion` calls `IncrementCircularBuffer` which causes a
  synchronous (!) ConPTY flush to the output pipe (side note: this is
  the primary reason why newlines are so slow in ConPTY).
  Since cooked reads are supposed to behave like a pager and not write
  into the scrollback, we temporarily mark the buffer as inactive
  which prevents `TextBuffer` from snitching about it to VtEngine.

Even after this change, there's still some weird behavior left:
* You cannot move your cursor back beyond (0,0), because this isn't a
  real pager-like implementation. That might be a neat future extension.
* Writing a lot of text and pressing Ctrl+C doesn't properly place the
  cursor and scroll the buffer, unless the cursor is at the end.
  That might also be worth investigating in the future (minor issue).
* When the viewport is full, backspacing more than 1 line of text
  (using Ctrl+Backspace) doesn't erase all of the affected lines,
  because `COOKED_READ_DATA::_erase` uses the same `WriteCharsLegacy`
  function to write whitespace to erase that text. It's only gone
  after typing one more character.
  I've written the code to mostly fix this, but decided against it
  as I considered the problem to be too niche to warrant extra code.

Closes #15899

## Validation Steps Performed
* Generate some text to paste in PowerShell:
  ```pwsh
  "" + (0..512 | % { "word" + $_.ToString().PadLeft(4, "0") })
  ```
* Launch cmd.exe and paste that text
* No flickering 
* No writing into the scrollback 
* No weird behavior when backspacing 
2023-09-08 17:43:32 -05:00
Leonard Hecker
43535b0d1c Fix identity of canary appxmanifest (#15945)
This commit fixes the identity of our new canary packages.
Additionally, it slightly reorders one block so that the file is
almost entirely in the same layout as the preview appxmanifest,
allowing for a better direct comparison (with git diff, etc.).
2023-09-08 15:28:38 -05:00
Tushar Singh
d19aaf7ead Add support for underline style and color in VT (#15795)
Underline color sequence _SGR 58_ (unlike *SGR 38*, *SGR 48*) only works
with sub parameters, eg. `\e[58:5:<n>m` or `\e[58:2::<r>:<g>:<b>m` will
work, but something like `\e[58;5;<n>m` won't work. This is a
requirement for the implementation to avoid problems with VT clients
that don't support sub parameters.

## Detailed Description

- Added `underlineColor` to `TextAttribute`, and `UnderlineStyle` into
`CharacterAttributes`.
- Added two new entries in `GraphicOptions` namely, `UnderlineColor`
(58) and `UnderlineColorDefault` (59).
- _SGR 58_ renders a sequence with sub parameters in the VT renderer.
- _SGR 4:x_ renders a sequence with sub parameters in the VT renderer,
except for single, double, and no-underline, which still use
backward-compatible _SGR 4_, _SGR 21_ and _SGR 24_.
- `XtermEngine` will send `\e[4m` without any styling information. This
means all underline style (except NoUnderline) will be rendered as
single underline.

## Reference issues
- #7228

### PR Checklist
- [x] update DECRARA, DECCARA to respect underline color and style.
- [x] update DECRQSS to send underline color and style in the query
response.
- [x] update DECRQPSR/DECRSPS/DECCIR
- [x] Tests added
2023-09-08 13:38:05 -05:00
inisarg
5d300b20ed Allows negative values in launch parameters (#15941)
Added a style that allows negative values in the launch position
parameters.


## PR Checklist
- [x] Closes #15832
2023-09-07 21:30:24 +00:00
Jaswir
2f7f759af4 Enable unfocused acrylic (#15923)
## Summary of the Pull Request
Closes #7158 

Enabling Acrylic as both an appearance setting (with all the plumbing),
allowing it to be set differently in both focused and unfocused
terminals. EnableUnfocusedAcrylic Global Setting that controls if
unfocused acrylic is possible so that people can disable that behavior.

## References and Relevant Issues
#7158 , references: #15913 , #11092

## Detailed Description of the Pull Request / Additional comments

### Allowing Acrylic to be set differently in both focused and unfocused
terminals:

#### A

![A](https://github.com/microsoft/terminal/assets/15957528/c43965f2-f458-46ae-af1c-a2107dac981a)

#### B

![B](https://github.com/microsoft/terminal/assets/15957528/e84ef1a8-8f4c-467a-99c2-9427061b3e3e)

#### C

![C](https://github.com/microsoft/terminal/assets/15957528/63fd35ba-a55a-4c1a-8b1c-5b571aa902ed)

#### D

![D](https://github.com/microsoft/terminal/assets/15957528/05108166-1c6e-406e-aec0-80023fc3f57c)

``` json
"profiles":
{
    "list":
    [
        {
            "commandline": "pwsh.exe",
            "name": "A",
            "unfocusedAppearance":
            {
                "useAcrylic": true,
            },
            "useAcrylic": true,
        },
        {
            "commandline": "pwsh.exe",
            "name": "B",
            "unfocusedAppearance":
            {
                "useAcrylic": false,
            },
            "useAcrylic": true,
        },
        {
            "commandline": "pwsh.exe",
            "name": "C",
            "unfocusedAppearance":
            {
                "useAcrylic": true,
            },
            "useAcrylic": false,
        },
        {
            "commandline": "pwsh.exe",
            "name": "D",
            "unfocusedAppearance":
            {
            },
            "useAcrylic": false,
        },
    ]
}
```

- **A**: AcrylicBlur always on
- **B**: Acrylic when focused, not acrylic when unfocused
- **C**: Why the hell not. Not Acrylic when focused, Acrylic when
unfocused.
- **D:**  Possible today by not using Acrylic. 

### EnableUnfocusedACrylic global setting that controls if unfocused
acrylic is possible
So that people can disable that behavior:

![256926990-3c42d99a-67de-4145-bf41-ce3995035136](https://github.com/microsoft/terminal/assets/15957528/eef62c14-d2bd-4737-b86e-dcb3588eb8f7)

### Alternate approaches I considered: 
Using `_InitializeBackgroundBrush` call instead of
`_changeBackgroundColor(bg) in
``TermControl::_UpdateAppearanceFromUIThread`. Comments in this function
mentioned:

``` *.cs'
// In the future, this might need to be changed to a
// _InitializeBackgroundBrush call instead, because we may need to
// switch from a solid color brush to an acrylic one.
```
I considered using this to tackle to problem, but don't see the benefit.
The only time we need to update the brush is when the user changes the
`EnableUnfocusedAcrylic ` setting which is already covered by
`fire_and_forget TermControl::UpdateControlSettings`
        
### Supporting different Opacity in Focused and Unfocused Appearance???
This PR is split up in two parts #7158 covers allowing Acrylic to be set
differently in both focused and unfocused terminals. And
EnableUnfocusedAcrylic Global Setting that controls if unfocused acrylic
is possible so that people can disable that behavior.

#11092 will be about enabling opacity as both an appearance setting,
allowing it to be set differently in both focused and unfocused
terminals.

### Skipping the XAML for now:
“I actually think we may want to skip the XAML on this one for now.
We've been having some discussions about compatibility settings, global
settings, stuff like this, and it might be _more- confusing to have you
do something here. We can always add it in post when we decide where to
put it.”
-- Mike Griese

## Validation Steps Performed

#### When Scrolling Mouse , opacity changes appropriately, on opacity
100 there are no gray lines or artefacts

![edgecase_scrollwheel](https://github.com/microsoft/terminal/assets/15957528/29a1b11e-05b8-4626-abd2-4f084ae94a8d)


![image](https://github.com/microsoft/terminal/assets/15957528/c05ea435-8867-4804-bcdc-2074df08cec1)

#### When Adjusting Opacity through command palette, opacity changes
appropriately, on opacity 100 there are no gray lines or artefacts

![edgecase_adjustopacity](https://github.com/microsoft/terminal/assets/15957528/a59b4d6d-f12e-48da-96bb-3eb333ac4637)


![image](https://github.com/microsoft/terminal/assets/15957528/c05ea435-8867-4804-bcdc-2074df08cec1)

#### When opening command palette state goes to unfocused, the acrylic
and color change appropriately

![edge_case_command_palette](https://github.com/microsoft/terminal/assets/15957528/ec0cd8b5-676e-4235-8231-a10a5689c0b8)


![image](https://github.com/microsoft/terminal/assets/15957528/4300df70-f64b-4001-8731-b3b69471ea78)

#### Stumbled upon a new bug when performing validation steps #15913

![264637964-494d4417-6a35-450a-89f7-52085ef9b546](https://github.com/microsoft/terminal/assets/15957528/fee59c4a-400b-4e40-912b-ea8c638fc979)

## PR Checklist

- [x] Closes #7158
- [X] Tests added/passed
- [X] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [x] Schema updated (if necessary)

---------

Co-authored-by: Mike Griese <migrie@microsoft.com>
2023-09-07 16:19:16 -05:00
Mike Griese
3830c62a81 Update roadmap for 2023 (#15931)
Closes #15661
2023-09-06 15:19:03 -05:00
Mike Griese
2f41d23d6d Update close button visibility based on BOTH settings and readonly mode (#15914)
`TerminalTab::_RecalculateAndApplyReadOnly` didn't know about whether a
tab should be closable or not, based on the theme settings. Similarly
(though, unreported), the theme update in
`TerminalPage::_updateAllTabCloseButtons` didn't really know about
readonly mode.

This fixes both these issues by moving responsibility for the tab close
button visibility into `TabBase` itself.

Closes #15902
2023-09-06 08:51:06 -05:00
Mike Griese
6cff135f37 Don't explode if HKCU\Console is write-protected (#15916)
I manually changed the permissions on `HKCU\Console` to deny "Create
subkey" to myself. Then confirmed that it explodes before this change,
and not after this change.

Closes #15458
2023-09-05 23:25:10 +02:00
Leonard Hecker
b53ddd1b47 AtlasEngine: Fix overly aggressive invalidation (#15929)
When marking newly scrolled in rows as invalidated we used:
```
if (offset < 0)
    ...
else
    ...
```
But it should've been:
```
if (offset < 0)
    ...
else if (offset > 0)
    ...
```
Because now it always set the start of the invalidated rows range to 0.

Additionally, this includes a commented debug helper which I've used
to figure out an unrelated bug. During that search I found this bug.
2023-09-05 23:24:00 +02:00
Mike Griese
0cbde94e4b Show number of search results & positions of hits in scrollbar (#14045)
This is a resurrection of #8588. That PR became painfully stale after
the `ControlCore` split. Original description:

> ## Summary of the Pull Request
> This is a PoC for:
> * Search status in SearchBox (aka number of matches + index of the
current match)
> * Live search (aka search upon typing)
> ## Detailed Description of the Pull Request / Additional comments
> * Introduced this optionally (global setting to enable it)
> * The approach is following:
>   * Every time the filter changes, enumerate all matches
>   * Upon navigation just take the relevant match and select it
> 

I cleaned it up a bit, and added support for also displaying the
positions of the matches in the scrollbar (if `showMarksOnScrollbar` is
also turned on).

It's also been made SUBSTANTIALLY easier after #15858 was merged.

Similar to before, searching while there's piles of output running isn't
_perfect_. But it's pretty awful currently, so that's not the end of the
world.

Gifs below.

* closes #8631 (which is a bullet point in #3920)
* closes #6319


Co-authored-by: Don-Vito <khvitaly@gmail.com>

---------

Co-authored-by: khvitaly <khvitaly@gmail.com>
2023-09-05 16:23:09 -05:00
Mike Griese
c5e0908b98 Update cmd.exe FAQ (#15918)
https://github.com/microsoft/terminal/issues/15870#issuecomment-1701435579
is an important note I think deserves to be committed.
2023-09-05 16:42:05 +00:00
Leonard Hecker
60843faa9e AtlasEngine: Fix invalidation when the cursor is invisible (#15904)
`PaintCursor()` is only called when the cursor is visible, but we need
to invalidate the cursor area even if it isn't. Otherwise a transition
from a visible to an invisible cursor wouldn't be rendered.

I'm confident that this closes #15199

## Validation Steps Performed
* Set blink duration extremely high
* Launch pwsh.exe
* Press Enter a few times
* Press Ctrl+L
* There are never 2 cursors visible, not even briefly 
2023-09-05 11:14:33 +00:00
Leonard Hecker
5fb2518117 AtlasEngine: Fix support for font features (#15912)
Font features require us to skip the fast path via `GetTextComplexity`.
`IDWriteTextLayout` handles it the same way internally.

Closes #15896

## Validation Steps Performed
* Use Cascadia Code
* Set `features: { "ss19": 1 }`
* "0" has a dash in it instead of a dot 
2023-08-31 11:28:22 -05:00
Dustin L. Howett
636be7e514 Canary: add the appLicensing capability (#15905)
This should allow the package to be installed without AppXSvc consulting
the store or the licensing service.

It's free and open-source. It shouldn't need a license to run.
2023-08-30 15:25:36 -05:00
Dustin Howett
a132ba82e7 Merged PR 8628818: [Git2Git] Merged PR 8561941: Scrubs SDKTOOLS_INC_PATH from onecore, onecoreuap
I have been working feverishly to remove the use of undefined macros used in sources\dirs files (such as this one SDKTOOLS_INC_PATH) that our telemetry constantly catches and reports as an issue.

Related work items: MSFT-40126326

Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_we_adept_e4d2 8589e01e23c4ec64ad270dbf0c1beb8a78b5a833
2023-03-15 17:06:21 +00:00
Dustin Howett
7aada2fd1e Merged PR 8612870: [Git2Git] Update WIL's get_token_info output type
A customer reports that `wil::get_token_information` and its use of `wistd::unique_ptr<T>` is hitting a code analysis error in that dynamically-sized token information blocks are allocated with `operator new` but deleted with `delete T*`. This is a "mismatched allocator" error and should be removed.

## What changed?

The output type of token information changed from `wistd::unique_ptr<T>` to `wil::unique_tokeninfo_ptr<T>` which has a custom deleter that uses `operator delete(p)` to match the allocator.

As the new type is incompatible with the old type, all call sites for `wil::GetTokenInformation` were updated to use the new type.

## How was the change tested?

1. Ran the WIL unit tests
2. Prime build of impacted directories

Related: https://github.com/microsoft/wil/pull/306
Related: https://github.com/microsoft/wil/issues/276

Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_we_adept_e4d2 d86d562b7559c2ca8de036085de6e52e80da8c93
2023-03-07 19:00:36 +00:00
Dustin Howett
553ad121af Merged PR 8603508: [Git2Git] Merged PR 8535345: More scrubbing of ONECORE_PRIV_SDK_INC_PATH
I have been working feverishly to remove the use of undefined macros used in
sources\dirs files (such as this one ONECORE_PRIV_SDK_INC_PATH) that our
telemetry constantly catches and reports as an issue.

Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_we_adept_e4d2 bb08e422cfb4dc2f8b99a2c34bac67a61654a572

Related work items: MSFT-40126326
2023-03-07 17:54:31 +00:00
Dustin Howett
154ac2b916 Merged PR 8428085: [Git2Git] Fix a GDI font object leak in FontInfo
"Leak in font object 1952 times in last 2k GDI objects created, that lead console to run out of GDI objects."

Fixes MSFT-42906562

Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_we_adept_e4d2 44f47bf7dbe4bff1986ba5fd8940b56f854c58b7
2023-02-15 19:15:28 +00:00
Dustin Howett
3c104440a8 Merged PR 8189936: [Git2Git] Lift an optional check out of RefreshRowIDs loop to fix a crash
In the most recent compiler ingestion into Windows ("LKG14"), we found
that this particular construction--checking an optional for a value
during this range-for loop--resulted in bad code generation.

When optimized, it generates code that looks effectively like this:

```c++
if (!newRowWidth.has_value()) {
	while (true) {
		// do the row stuff...
		++it;
	}
}
```

The loop never exits, and `_RefreshRowIDs` walks off the end of the
buffer. Whoops.

This commit fixes that issue by tricking the optimizer to go another
way. Leonard tells me it's harmless to call `Resize` a bunch of times,
even if it's a no-op, so I trust that this change results in the right
outcome with none of the crashing.

Fixes MSFT-41456525

Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_we_adept_e4d2 c2b3697c867bddf5660da8b222e99ff4bfd1ea5b
2022-11-29 22:07:37 +00:00
Kieren Wou
b6feabe9cc Merged PR 8188601: [Git2Git] !8082133: LKG14 Build Fix - ARM64EC does not support AVX
Arm64EC does not support AVX and the usage of it in EC compilation is now an error with the LKG14 compiler update. The fix is to conditionalize using AVX for non-EC compilation.

Related work items: MSFT-42045281

Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_we_adept_e4d2 31ca1e08e001988b95ff29a5e098441cae0363bd
2022-11-29 13:35:00 -06:00
Dustin Howett
a0624bedaa Migrate OSS up to c12dc2aa4 2022-11-11 14:11:41 -06:00
433 changed files with 13428 additions and 10652 deletions

View File

@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"XamlStyler.Console": {
"version": "3.2206.4",
"version": "3.2311.2",
"commands": [
"xstyler"
]

View File

@@ -6,8 +6,6 @@
By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.
:warning: The command is written for posix shells. If it doesn't work for you, you can manually _add_ (one word per line) / _remove_ items to `expect.txt` and the `excludes.txt` files.
If the listed items are:
* ... **misspelled**, then please *correct* them instead of using the command.
@@ -36,7 +34,9 @@ https://www.regexplanet.com/advanced/perl/) yours before committing to verify it
* well-formed pattern.
If you can write a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it,
If you can write a [pattern](
https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns
) that would match it,
try adding it to the `patterns.txt` file.
Patterns are Perl 5 Regular Expressions - you can [test](

View File

@@ -1,3 +1,4 @@
aci
admins
allcolors
Apc
@@ -8,11 +9,13 @@ breadcrumbs
bsd
calt
ccmp
ccon
changelog
clickable
clig
CMMI
copyable
Counterintuitively
CtrlDToClose
cybersecurity
dalet
@@ -52,6 +55,7 @@ hyperlinks
iconify
img
inlined
issuetitle
It'd
kje
libfuzzer
@@ -90,10 +94,13 @@ reserialize
reserializes
rlig
runtimes
servicebus
shcha
similaritytolerance
slnt
Sos
ssh
sustainability
stakeholders
sxn
timeline
@@ -115,7 +122,9 @@ vsdevcmd
walkthrough
walkthroughs
We'd
westus
wildcards
workarounds
XBox
YBox
yeru

View File

@@ -28,6 +28,7 @@ CYICON
Dacl
dataobject
dcomp
debugbreak
delayimp
DERR
dlldata
@@ -209,6 +210,7 @@ tlg
TME
tmp
tmpdir
tokeninfo
tolower
toupper
TRACKMOUSEEVENT
@@ -219,16 +221,19 @@ UFIELD
ULARGE
UOI
UPDATEINIFILE
urlmon
userenv
USEROBJECTFLAGS
Vcpp
Viewbox
virtualalloc
vsnwprintf
wcsnlen
wcsstr
wcstoui
WDJ
winhttp
wininet
winmain
winsta
winstamin

View File

@@ -4,6 +4,7 @@ advapi
altform
altforms
appendwttlogging
appinstaller
appx
appxbundle
appxerror
@@ -59,12 +60,13 @@ PRIINFO
propkey
pscustomobject
QWORD
rdpclip
regedit
resfiles
robocopy
SACLs
segoe
sdkddkver
segoe
Shobjidl
sid
Skype

View File

@@ -6,6 +6,7 @@ bhoj
Bhojwani
Bluloco
carlos
craigloewen
dhowett
Diviness
dsafa

View File

@@ -1,23 +1,37 @@
# marker to ignore all code on line
^.*/\* #no-spell-check-line \*/.*$
# marker for ignoring a comment to the end of the line
// #no-spell-check.*$
# marker to ignore all code on line
^.*\bno-spell-check(?:-line|)(?:\s.*|)$
# https://cspell.org/configuration/document-settings/
# cspell inline
^.*\b[Cc][Ss][Pp][Ee][Ll]{2}:\s*[Dd][Ii][Ss][Aa][Bb][Ll][Ee]-[Ll][Ii][Nn][Ee]\b
# patch hunk comments
^\@\@ -\d+(?:,\d+|) \+\d+(?:,\d+|) \@\@ .*
# git index header
index [0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
index (?:[0-9a-z]{7,40},|)[0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
# file permissions
['"`\s][-bcdLlpsw](?:[-r][-w][-Ssx]){2}[-r][-w][-SsTtx]\+?['"`\s]
# css url wrappings
\burl\([^)]+\)
# cid urls
(['"])cid:.*?\g{-1}
# data url in parens
\(data:[^)]*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})[^)]*\)
#\(data:(?:[^) ][^)]*?|)(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})[^)]*\)
# data url in quotes
([`'"])data:.*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1}
([`'"])data:(?:[^ `'"].*?|)(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1}
# data url
data:[-a-zA-Z=;:/0-9+]*,\S*
# https/http/file urls
(?:\b(?:https?|ftp|file)://)[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]
# mailto urls
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
@@ -35,6 +49,9 @@ magnet:[?=:\w]+
# asciinema
\basciinema\.org/a/[0-9a-zA-Z]+
# asciinema v2
^\[\d+\.\d+, "[io]", ".*"\]$
# apple
\bdeveloper\.apple\.com/[-\w?=/]+
# Apple music
@@ -89,7 +106,7 @@ vpc-\w+
# Google Drive
\bdrive\.google\.com/(?:file/d/|open)[-0-9a-zA-Z_?=]*
# Google Groups
\bgroups\.google\.com/(?:(?:forum/#!|d/)(?:msg|topics?|searchin)|a)/[^/\s"]+/[-a-zA-Z0-9$]+(?:/[-a-zA-Z0-9]+)*
\bgroups\.google\.com(?:/[a-z]+/(?:#!|)[^/\s"]+)*
# Google Maps
\bmaps\.google\.com/maps\?[\w&;=]*
# Google themes
@@ -117,6 +134,8 @@ themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+.
(?:\[`?[0-9a-f]+`?\]\(https:/|)/(?:www\.|)github\.com(?:/[^/\s"]+){2,}(?:/[^/\s")]+)(?:[0-9a-f]+(?:[-0-9a-zA-Z/#.]*|)\b|)
# GitHub SHAs
\bgithub\.com(?:/[^/\s"]+){2}[@#][0-9a-f]+\b
# GitHub SHA refs
\[([0-9a-f]+)\]\(https://(?:www\.|)github.com/[-\w]+/[-\w]+/commit/\g{-1}[0-9a-f]*
# GitHub wiki
\bgithub\.com/(?:[^/]+/){2}wiki/(?:(?:[^/]+/|)_history|[^/]+(?:/_compare|)/[0-9a-f.]{40,})\b
# githubusercontent
@@ -128,9 +147,9 @@ themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+.
# git.io
\bgit\.io/[0-9a-zA-Z]+
# GitHub JSON
"node_id": "[-a-zA-Z=;:/0-9+]*"
"node_id": "[-a-zA-Z=;:/0-9+_]*"
# Contributor
\[[^\]]+\]\(https://github\.com/[^/\s"]+\)
\[[^\]]+\]\(https://github\.com/[^/\s"]+/?\)
# GHSA
GHSA(?:-[0-9a-z]{4}){3}
@@ -143,8 +162,8 @@ GHSA(?:-[0-9a-z]{4}){3}
# GitLab commits
\bgitlab\.[^/\s"]*/(?:[^/\s"]+/){2}commits?/[0-9a-f]+\b
# binanace
accounts.binance.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
# binance
accounts\.binance\.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
# bitbucket diff
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}diff(?:stat|)(?:/[^/\s"]+){2}:[0-9a-f]+
@@ -280,9 +299,9 @@ slack://[a-zA-Z0-9?&=]+
\bdropbox\.com/sh?/[^/\s"]+/[-0-9A-Za-z_.%?=&;]+
# ipfs protocol
ipfs://[0-9a-z]*
ipfs://[0-9a-zA-Z]{3,}
# ipfs url
/ipfs/[0-9a-z]*
/ipfs/[0-9a-zA-Z]{3,}
# w3
\bw3\.org/[-0-9a-zA-Z/#.]+
@@ -359,22 +378,33 @@ ipfs://[0-9a-z]*
# tinyurl
\btinyurl\.com/\w+
# codepen
\bcodepen\.io/[\w/]+
# registry.npmjs.org
\bregistry\.npmjs\.org/(?:@[^/"']+/|)[^/"']+/-/[-\w@.]+
# getopts
\bgetopts\s+(?:"[^"]+"|'[^']+')
# ANSI color codes
(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m
(?:\\(?:u00|x)1[Bb]|\x1b|\\u\{1[Bb]\})\[\d+(?:;\d+|)m
# URL escaped characters
\%[0-9A-F][A-F]
\%[0-9A-F][A-F](?=[A-Za-z])
# lower URL escaped characters
\%[0-9a-f][a-f](?=[a-z]{2,})
# IPv6
\b(?:[0-9a-fA-F]{0,4}:){3,7}[0-9a-fA-F]{0,4}\b
#\b(?:[0-9a-fA-F]{0,4}:){3,7}[0-9a-fA-F]{0,4}\b
# c99 hex digits (not the full format, just one I've seen)
0x[0-9a-fA-F](?:\.[0-9a-fA-F]*|)[pP]
# Punycode
\bxn--[-0-9a-z]+
# sha
sha\d+:[0-9]*[a-f]{3,}[0-9a-f]*
# sha-... -- uses a fancy capture
(['"]|&quot;)[0-9a-f]{40,}\g{-1}
(\\?['"]|&quot;)[0-9a-f]{40,}\g{-1}
# hex runs
\b[0-9a-fA-F]{16,}\b
# hex in url queries
@@ -389,18 +419,21 @@ sha\d+:[0-9]*[a-f]{3,}[0-9a-f]*
# Well known gpg keys
.well-known/openpgpkey/[\w./]+
# pki
-----BEGIN.*-----END
# uuid:
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
# hex digits including css/html color classes:
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|u\d+)\b
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|[iu]\d+)\b
# integrity
integrity="sha\d+-[-a-zA-Z=;:/0-9+]{40,}"
integrity=(['"])(?:\s*sha\d+-[-a-zA-Z=;:/0-9+]{40,})+\g{-1}
# https://www.gnu.org/software/groff/manual/groff.html
# man troff content
\\f[BCIPR]
# '
\\\(aq
# '/"
\\\([ad]q
# .desktop mime types
^MimeTypes?=.*$
@@ -409,21 +442,33 @@ integrity="sha\d+-[-a-zA-Z=;:/0-9+]{40,}"
# Localized .desktop content
Name\[[^\]]+\]=.*
# IServiceProvider
\bI(?=(?:[A-Z][a-z]{2,})+\b)
# IServiceProvider / isAThing
\b(?:I|isA)(?=(?:[A-Z][a-z]{2,})+\b)
# crypt
"\$2[ayb]\$.{56}"
(['"])\$2[ayb]\$.{56}\g{-1}
# scrypt / argon
\$(?:scrypt|argon\d+[di]*)\$\S+
# Input to GitHub JSON
content: "[-a-zA-Z=;:/0-9+]*="
# go.sum
\bh1:\S+
# Python stringprefix / binaryprefix
# scala modules
("[^"]+"\s*%%?\s*){2,3}"[^"]+"
# Input to GitHub JSON
content: (['"])[-a-zA-Z=;:/0-9+]*=\g{-1}
# This does not cover multiline strings, if your repository has them,
# you'll want to remove the `(?=.*?")` suffix.
# The `(?=.*?")` suffix should limit the false positives rate
# printf
#%(?:(?:(?:hh?|ll?|[jzt])?[diuoxn]|l?[cs]|L?[fega]|p)(?=[a-z]{2,})|(?:X|L?[FEGA]|p)(?=[a-zA-Z]{2,}))(?=[_a-zA-Z]+\b)(?!%)(?=.*?['"])
# Python string prefix / binary prefix
# Note that there's a high false positive rate, remove the `?=` and search for the regex to see if the matches seem like reasonable strings
(?<!')\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})
(?<!')\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'(?=[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})
# Regular expressions for (P|p)assword
\([A-Z]\|[a-z]\)[a-z]+
@@ -439,16 +484,35 @@ content: "[-a-zA-Z=;:/0-9+]*="
^\s*/\\[b].*/[gim]*\s*(?:\)(?:;|$)|,$)
# javascript replace regex
\.replace\(/[^/\s"]*/[gim]*\s*,
# assign regex
= /[^*]*?(?:[a-z]{3,}|[A-Z]{3,}|[A-Z][a-z]{2,}).*/
# perl regex test
[!=]~ (?:/.*/|m\{.*?\}|m<.*?>|m([|!/@#,;']).*?\g{-1})
# perl qr regex
(?<!\$)\bqr(?:\{.*?\}|<.*?>|\(.*?\)|([|!/@#,;']).*?\g{-1})
# Go regular expressions
regexp?\.MustCompile\(`[^`]*`\)
# regex choice
\(\?:[^)]+\|[^)]+\)
# proto
^\s*(\w+)\s\g{-1} =
# sed regular expressions
sed 's/(?:[^/]*?[a-zA-Z]{3,}[^/]*?/){2}
# node packages
(["'])\@[^/'" ]+/[^/'" ]+\g{-1}
# go install
go install(?:\s+[a-z]+\.[-@\w/.]+)+
# jetbrains schema https://youtrack.jetbrains.com/issue/RSRP-489571
urn:shemas-jetbrains-com
# kubernetes pod status lists
# https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
\w+(?:-\w+)+\s+\d+/\d+\s+(?:Running|Pending|Succeeded|Failed|Unknown)\s+
@@ -460,19 +524,47 @@ go install(?:\s+[a-z]+\.[-@\w/.]+)+
-[0-9a-f]{10}-\w{5}\s
# posthog secrets
posthog\.init\((['"])phc_[^"',]+\g{-1},
([`'"])phc_[^"',]+\g{-1}
# xcode
# xcodeproject scenes
(?:Controller|ID|id)="\w{3}-\w{2}-\w{3}"
(?:Controller|destination|ID|id)="\w{3}-\w{2}-\w{3}"
# xcode api botches
customObjectInstantitationMethod
# configure flags
.* \| --\w{2,}.*?(?=\w+\s\w+)
# font awesome classes
\.fa-[-a-z0-9]+
# bearer auth
(['"])Bear[e][r] .*?\g{-1}
# basic auth
(['"])Basic [-a-zA-Z=;:/0-9+]{3,}\g{-1}
# base64 encoded content
#([`'"])[-a-zA-Z=;:/0-9+]+=\g{-1}
# base64 encoded content in xml/sgml
>[-a-zA-Z=;:/0-9+]+=</
# base64 encoded content, possibly wrapped in mime
#(?:^|[\s=;:?])[-a-zA-Z=;:/0-9+]{50,}(?:[\s=;:?]|$)
# encoded-word
=\?[-a-zA-Z0-9"*%]+\?[BQ]\?[^?]{0,75}\?=
# Time Zones
\b(?:Africa|Atlantic|America|Antarctica|Asia|Australia|Europe|Indian|Pacific)(?:/\w+)+
# linux kernel info
^(?:bugs|flags|Features)\s+:.*
# systemd mode
systemd.*?running in system mode \([-+].*\)$
# Update Lorem based on your content (requires `ge` and `w` from https://github.com/jsoref/spelling; and `review` from https://github.com/check-spelling/check-spelling/wiki/Looking-for-items-locally )
# grep '^[^#].*lorem' .github/actions/spelling/patterns.txt|perl -pne 's/.*i..\?://;s/\).*//' |tr '|' "\n"|sort -f |xargs -n1 ge|perl -pne 's/^[^:]*://'|sort -u|w|sed -e 's/ .*//'|w|review -
# Warning, while `(?i)` is very neat and fancy, if you have some binary files that aren't proper unicode, you might run into:
@@ -483,32 +575,62 @@ customObjectInstantitationMethod
(?:\w|\s|[,.])*\b(?i)(?:amet|consectetur|cursus|dolor|eros|ipsum|lacus|libero|ligula|lorem|magna|neque|nulla|suscipit|tempus)\b(?:\w|\s|[,.])*
# Non-English
[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*
[a-zA-Z]*[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*|[a-zA-Z]{3,}[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]|[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3,}
# highlighted letters
\[[A-Z]\][a-z]+
# French
# This corpus only had capital letters, but you probably want lowercase ones as well.
\b[LN]'+[a-z]{2,}\b
# latex
\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
# latex (check-spelling <= 0.0.21)
#\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
# latex (check-spelling >= 0.0.22)
\\\w{2,}\{
# eslint
"varsIgnorePattern": ".+"
# Windows short paths
[/\\][^/\\]{5,6}~\d{1,2}[/\\]
# in check-spelling@v0.0.22+, printf markers aren't automatically consumed
# printf markers
#(?<!\\)\\[nrt](?=[a-z]{2,})
# alternate markers if you run into latex and friends
#(?<!\\)\\[nrt](?=[a-z]{2,})(?=.*['"`])
# apache
a2(?:en|dis)
# weak e-tag
W/"[^"]+"
# the negative lookahead here is to allow catching 'templatesz' as a misspelling
# but to otherwise recognize a Windows path with \templates\foo.template or similar:
\\(?:necessary|r(?:eport|esolve[dr]?|esult)|t(?:arget|emplates?))(?![a-z])
#\\(?:necessary|r(?:eport|esolve[dr]?|esult)|t(?:arget|emplates?))(?![a-z])
# ignore long runs of a single character:
\b([A-Za-z])\g{-1}{3,}\b
# Note that the next example is no longer necessary if you are using
# to match a string starting with a `#`, use a character-class:
[#]backwards
# version suffix <word>v#
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
# Compiler flags (Scala)
(?:^|[\t ,>"'`=(])-J-[DPWXY](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
# Compiler flags
#(?:^|[\t ,"'`=(])-[DPWXYLlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
# Compiler flags (Unix, Java/Scala)
# Use if you have things like `-Pdocker` and want to treat them as `docker`
#(?:^|[\t ,>"'`=(])-(?:(?:J-|)[DPWXY]|[Llf])(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
# Compiler flags (Windows / PowerShell)
# This is a subset of the more general compiler flags pattern.
# It avoids matching `-Path` to prevent it from being treated as `ath`
#(?:^|[\t ,"'`=(])-(?:[DPL](?=[A-Z]{2,})|[WXYlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,}))
# Compiler flags (linker)
,-B
# curl arguments
\b(?:\\n|)curl(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
# set arguments

View File

@@ -1,21 +1,24 @@
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-excludes
(?:(?i)\.png$)
(?:^|/)(?i)COPYRIGHT
(?:^|/)(?i)LICEN[CS]E
(?:^|/)3rdparty/
(?:^|/)dirs$
(?:^|/)go\.mod$
(?:^|/)go\.sum$
(?:^|/)package(?:-lock|)\.json$
(?:^|/)Pipfile$
(?:^|/)pyproject.toml
(?:^|/)requirements(?:-dev|-doc|-test|)\.txt$
(?:^|/)sources(?:|\.dep)$
(?:^|/)vendor/
\.a$
\.ai$
\.all-contributorsrc$
\.avi$
\.bmp$
\.bz2$
\.cer$
\.class$
\.coveragerc$
\.crl$
\.crt$
\.csr$
@@ -27,11 +30,15 @@
\.eps$
\.exe$
\.gif$
\.git-blame-ignore-revs$
\.gitattributes$
\.gitignore$
\.gitkeep$
\.graffle$
\.gz$
\.icns$
\.ico$
\.ipynb$
\.jar$
\.jks$
\.jpeg$
@@ -41,61 +48,62 @@
\.lock$
\.map$
\.min\..
\.mo$
\.mod$
\.mp3$
\.mp4$
\.o$
\.ocf$
\.otf$
\.p12$
\.parquet$
\.pbxproj$
\.pdf$
\.pem$
\.pfx$
\.png$
\.psd$
\.pyc$
\.pylintrc$
\.qm$
\.runsettings$
\.s$
\.sig$
\.so$
\.svg$
\.svgz$
\.svgz?$
\.sys$
\.tar$
\.tgz$
\.tiff?$
\.ttf$
\.vcxproj\.filters$
\.vsdx$
\.wav$
\.webm$
\.webp$
\.woff
\.woff2?$
\.xcf$
\.xls
\.xlsx?$
\.xpm$
\.yml$
\.xz$
\.zip$
^\.github/actions/spelling/
^\.github/fabricbot.json$
^\.gitignore$
^\Q.git-blame-ignore-revs\E$
^\Q.github/workflows/spelling.yml\E$
^\Qdoc/reference/windows-terminal-logo.ans\E$
^\Qsamples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj.filters\E$
^\Qsrc/host/exe/Host.EXE.vcxproj.filters\E$
^\Qbuild/config/release.gdnbaselines\E$
^\Qsrc/host/ft_host/chafa.txt\E$
^\Qsrc/tools/closetest/CloseTest.vcxproj.filters\E$
^\XamlStyler.json$
^\Qsrc/host/ft_uia/run.bat\E$
^\Qsrc/host/runft.bat\E$
^\Qsrc/tools/lnkd/lnkd.bat\E$
^\Qsrc/tools/pixels/pixels.bat\E$
^build/config/
^consolegit2gitfilters\.json$
^dep/
^doc/reference/master-sequence-list.csv$
^doc/reference/master-sequence-list\.csv$
^doc/reference/UTF8-torture-test\.txt$
^doc/reference/windows-terminal-logo\.ans$
^oss/
^src/host/ft_uia/run\.bat$
^src/host/runft\.bat$
^src/host/runut\.bat$
^samples/PixelShaders/Screenshots/
^src/interactivity/onecore/BgfxEngine\.
^src/renderer/atlas/
^src/renderer/wddmcon/WddmConRenderer\.
@@ -107,14 +115,13 @@
^src/terminal/parser/ut_parser/Base64Test.cpp$
^src/terminal/parser/ut_parser/run\.bat$
^src/tools/benchcat
^src/tools/integrity/dirs$
^src/tools/integrity/packageuwp/ConsoleUWP\.appxSources$
^src/tools/lnkd/lnkd\.bat$
^src/tools/pixels/pixels\.bat$
^src/tools/RenderingTests/main.cpp$
^src/tools/RenderingTests/main\.cpp$
^src/tools/texttests/fira\.txt$
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
^src/types/ColorFix.cpp
^src/types/ut_types/UtilsTests.cpp$
^tools/ReleaseEngineering/ServicingPipeline.ps1$
^src/tools/U8U16Test/(?!en)..\.
^src/types/ColorFix\.cpp$
^src/types/ut_types/UtilsTests\.cpp$
^tools/ReleaseEngineering/ServicingPipeline\.ps1$
^XamlStyler\.json$
ignore$
SUMS$

View File

@@ -0,0 +1,5 @@
EOB
swrapped
wordi
wordiswrapped
wrappe

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
WCAG
winui
appshellintegration
mdtauk
gfycat
Guake
xkcd

View File

@@ -1,4 +1,6 @@
# reject `m_data` as there's a certain OS which has evil defines that break things if it's used elsewhere
# reject `m_data` as VxWorks defined it and that breaks things if it's used elsewhere
# see [fprime](https://github.com/nasa/fprime/commit/d589f0a25c59ea9a800d851ea84c2f5df02fb529)
# and [Qt](https://github.com/qtproject/qt-solutions/blame/fb7bc42bfcc578ff3fa3b9ca21a41e96eb37c1c7/qtscriptclassic/src/qscriptbuffer_p.h#L46)
# \bm_data\b
# If you have a framework that uses `it()` for testing and `fit()` for debugging a specific test,
@@ -6,40 +8,72 @@
# to use this:
#\bfit\(
# s.b. anymore
\bany more[,.]
# s.b. GitHub
\bGithub\b
(?<![&*.]|// |\btype )\bGithub\b(?![{)])
# s.b. GitLab
\bGitlab\b
(?<![&*.]|// |\btype )\bGitlab\b(?![{)])
# s.b. JavaScript
\bJavascript\b
# s.b. macOS or Mac OS X or ...
\bMacOS\b
# s.b. Microsoft
\bMicroSoft\b
# s.b. TypeScript
\bTypescript\b
# s.b. another
\ban[- ]other\b
# s.b. deprecation warning
\b[Dd]epreciation [Ww]arnings?\b
# s.b. greater than
\bgreater then\b
# s.b. in front of
\bin from of\b
# s.b. into
#\sin to\s
# when not phrasal and when `in order to` would be wrong:
# https://thewritepractice.com/into-vs-in-to/
#\sin to\s(?!if\b)
# s.b. is obsolete
\bis obsolescent\b
# s.b. it's or its
\bits[']
# s.b. opt-in
\sopt in\s
#(?<!\sfor)\sopt in\s
# s.b. less than
\bless then\b
# s.b. one of
\bon of\b
# s.b. otherwise
\bother[- ]wise\b
# s.b. or (more|less)
\bore (?:more|less)\b
# s.b. nonexistent
\bnon existing\b
\b[Nn]o[nt][- ]existent\b
# s.b. brief / details/ param / return / retval
(?:^\s*|(?:\*|//|/*)\s+`)[\\@](?:breif|(?:detail|detials)|(?:params(?!\.)|prama?)|ret(?:uns?)|retvl)\b
# s.b. preexisting
[Pp]re[- ]existing
@@ -49,14 +83,37 @@
# s.b. preemptively
[Pp]re[- ]emptively
# s.b. recently changed or recent changes
[Rr]ecent changed
# s.b. reentrancy
[Rr]e[- ]entrancy
# s.b. reentrant
[Rr]e[- ]entrant
# s.b. workaround(s)
#\bwork[- ]arounds?\b
# s.b. understand
\bunder stand\b
# Reject duplicate words
# s.b. workarounds
#\bwork[- ]arounds\b
# s.b. workaround
(?:(?:[Aa]|[Tt]he|ugly)\swork[- ]around\b|\swork[- ]around\s+for)
# s.b. (coarse|fine)-grained
\b(?:coarse|fine) grained\b
# s.b. neither/nor -- or reword
#\bnot\b[^.?!"/(]+\bnor\b
# probably a double negative
# s.b. neither/nor (plus rewording the beginning)
\bnot\b[^.?!"/]*\bneither\b[^.?!"/(]*\bnor\b
# In English, it is generally wrong to have the same word twice in a row without punctuation.
# Duplicated words are generally mistakes.
# There are a few exceptions where it is acceptable (e.g. "that that").
# If the highlighted doubled word pair is in a code snippet, you can write a pattern to mask it.
# If the highlighted doubled word pair is in prose, have someone read the English before you dismiss this error.
\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s

View File

@@ -1,2 +0,0 @@
\\native(?![a-z])
\\nihilist(?![a-z])

View File

@@ -1,8 +0,0 @@
\\registry(?![a-z])
\\release(?![a-z])
\\resources?(?![a-z])
\\result(?![a-z])
\\resultmacros(?![a-z])
\\rules(?![a-z])
\\renderer(?![a-z])
\\rectread(?![a-z])

View File

@@ -1,13 +0,0 @@
\\telemetry(?![a-z])
\\templates(?![a-z])
\\term(?![a-z])
\\terminal(?![a-z])
\\terminalcore(?![a-z])
\\terminalinput(?![a-z])
\\testlist(?![a-z])
\\testmd(?![a-z])
\\testpasses(?![a-z])
\\tests(?![a-z])
\\thread(?![a-z])
\\tools(?![a-z])
\\types?(?![a-z])

View File

@@ -7,10 +7,6 @@ Note: order of the contents of these files can matter.
Lines from an individual file are handled in file order.
Files are selected in alphabetical order.
* [n](0_n.txt), [r](0_r.txt), and [t](0_t.txt) are specifically to work around
a quirk in the spell checker:
it often sees C strings of the form "Hello\nwerld". And would prefer to
spot the typo of `werld`.
* [patterns](patterns.txt) is the main list -- there is nothing
particularly special about the file name (beyond the extension which is
important).

View File

@@ -3,7 +3,7 @@
https?://\S+
[Pp]ublicKeyToken="?[0-9a-fA-F]{16}"?
(?:[{"]|UniqueIdentifier>)[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}(?:[}"]|</UniqueIdentifier)
(?:0[Xx]|\\x|U\+|#)[a-f0-9A-FGgRr]{2,}[Uu]?[Ll]{0,2}\b
(?:0[Xx]|\\x|U\+|#)[a-f0-9A-FGgRr]{2,}(?!\[)[Uu]?[Ll]{0,2}\b
microsoft/cascadia-code\@[0-9a-fA-F]{40}
\d+x\d+Logo
Scro\&ll
@@ -12,7 +12,6 @@ Scro\&ll
TestUtils::VerifyExpectedString\(tb, L"[^"]+"
(?:hostSm|mach)\.ProcessString\(L"[^"]+"
\b([A-Za-z])\g{-1}{3,}\b
0x[0-9A-Za-z]+
Base64::s_(?:En|De)code\(L"[^"]+"
VERIFY_ARE_EQUAL\(L"[^"]+"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\+/"
@@ -24,70 +23,129 @@ ROY\sG\.\sBIV
!(?:(?i)ESC)!\[
!(?:(?i)CSI)!(?:\d+(?:;\d+|)m|[ABCDF])
# Python stringprefix / binaryprefix
\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'
# SSE intrinsics like "_mm_subs_epu16"
\b_mm(?:|256|512)_\w+\b
# ARM NEON intrinsics like "vsubq_u16"
\bv\w+_[fsu](?:8|16|32|64)\b
# color floating numbers
0x[0-9a-f](?:\.[0-9a-f]*p)[-+]\d+f
# AppX package
_\d[0-9a-z]{12}['\.]
# string test
equals_insensitive_ascii\("\w+", "\w+"
# Automatically suggested patterns
# hit-count: 3831 file-count: 582
# IServiceProvider
\bI(?=(?:[A-Z][a-z]{2,})+\b)
# hit-count: 3788 file-count: 599
# IServiceProvider / isAThing
\b(?:I|isA)(?=(?:[A-Z][a-z]{2,})+\b)
# hit-count: 71 file-count: 35
# Compiler flags
(?:^|[\t ,"'`=(])-[D](?=[A-Z]{2,}|[A-Z][a-z])
(?:^|[\t ,"'`=(])-[X](?!aml)(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
# hit-count: 41 file-count: 28
# version suffix <word>v#
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
# hit-count: 20 file-count: 9
# hit-count: 314 file-count: 21
# hex runs
\b[0-9a-fA-F]{16,}\b
# hit-count: 10 file-count: 7
# hit-count: 47 file-count: 11
# special cased printf markers
\\r\\n(?=[a-z])|(?<!\\)\\[nrt](?=[a-z]{2,})(?=.*(?:<.*['"`]|"(?:[;,]|\);)$|\) \+$))
# ConsoleArgumentsTests
--headless\\.*?"
# hit-count: 109 file-count: 62
# Compiler flags (Unix, Java/Scala)
# Use if you have things like `-Pdocker` and want to treat them as `docker`
(?:^|[\t ,>"'`=(])-(?:D(?=[A-Z])|[WX]|f(?=[ms]))(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
# hit-count: 60 file-count: 35
# version suffix <word>v#
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
# hit-count: 2 file-count: 2
# This does not cover multiline strings, if your repository has them,
# you'll want to remove the `(?=.*?")` suffix.
# The `(?=.*?")` suffix should limit the false positives rate
# printf
%(?:s)(?!ize)(?=[a-z]{2,})
# hit-count: 16 file-count: 10
# uuid:
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
# hit-count: 13 file-count: 4
# Non-English
[a-zA-Z]*[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*|[a-zA-Z]{3,}[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]|[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3,}
# hit-count: 7 file-count: 5
# hex digits including css/html color classes:
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|[iu]\d+)\b
# hit-count: 7 file-count: 1
# regex choice
\(\?:[^)]+\|[^)]+\)
# hit-count: 4 file-count: 4
# mailto urls
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
# tar arguments
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
# hit-count: 4 file-count: 1
# ANSI color codes
(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m
(?:\\(?:u00|x)1[Bb]|\x1b|\\u\{1[Bb]\})\[\d+(?:;\d+|)m
# hit-count: 4 file-count: 1
# Update Lorem based on your content (requires `ge` and `w` from https://github.com/jsoref/spelling; and `review` from https://github.com/check-spelling/check-spelling/wiki/Looking-for-items-locally )
# grep '^[^#].*lorem' .github/actions/spelling/patterns.txt|perl -pne 's/.*i..\?://;s/\).*//' |tr '|' "\n"|sort -f |xargs -n1 ge|perl -pne 's/^[^:]*://'|sort -u|w|sed -e 's/ .*//'|w|review -
# Warning, while `(?i)` is very neat and fancy, if you have some binary files that aren't proper unicode, you might run into:
## Operation "substitution (s///)" returns its argument for non-Unicode code point 0x1C19AE (the code point will vary).
## You could manually change `(?i)X...` to use `[Xx]...`
## or you could add the files to your `excludes` file (a version after 0.0.19 should identify the file path)
# Lorem
(?:\w|\s|[,.])*\b(?i)(?:amet|consectetur|cursus|dolor|eros|ipsum|lacus|libero|ligula|lorem|magna|neque|nulla|suscipit|tempus)\b(?:\w|\s|[,.])*
# hit-count: 3 file-count: 3
# mailto urls
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
# hit-count: 2 file-count: 1
# latex
\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
# Python string prefix / binary prefix
# Note that there's a high false positive rate, remove the `?=` and search for the regex to see if the matches seem like reasonable strings
(?<!')\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'(?=[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})
# hit-count: 1 file-count: 1
# hex digits including css/html color classes:
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|u\d+)\b
# Punycode
\bxn--[-0-9a-z]+
# hit-count: 1 file-count: 1
# Non-English
[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*
# latex (check-spelling >= 0.0.22)
\\\w{2,}\{
# hit-count: 1 file-count: 1
# French
# This corpus only had capital letters, but you probably want lowercase ones as well.
\b[LN]'+[a-z]{2,}\b
# tput arguments -- https://man7.org/linux/man-pages/man5/terminfo.5.html -- technically they can be more than 5 chars long...
\btput\s+(?:(?:-[SV]|-T\s*\w+)\s+)*\w{3,5}\b
# Questionably acceptable forms of `in to`
# Personally, I prefer `log into`, but people object
# https://www.tprteaching.com/log-into-log-in-to-login/
\b(?:[Ll]og|[Ss]ign) in to\b
# to opt in
\bto opt in\b
# acceptable duplicates
# ls directory listings
[-bcdlpsw](?:[-r][-w][-sx]){3}\s+\d+\s+(\S+)\s+\g{-1}\s+\d+\s+
# C/idl types + English ...
\s(Guid|long|LONG|that) \g{-1}\s
# javadoc / .net
(?:[\\@](?:groupname|param)|(?:public|private)(?:\s+static|\s+readonly)*)\s+(\w+)\s+\g{-1}\s
[-bcdlpsw](?:[-r][-w][-Ssx]){3}\s+\d+\s+\S+\s+\S+\s+\d+\s+
# mount
\bmount\s+-t\s+(\w+)\s+\g{-1}\b
# C types and repeated CSS values
\s(auto|center|div|Guid|inherit|long|LONG|none|normal|solid|that|thin|transparent|very)(?: \g{-1})+\s
# C struct
\bstruct\s+(\w+)\s+\g{-1}\b
# go templates
\s(\w+)\s+\g{-1}\s+\`(?:graphql|inject|json|yaml):
# doxygen / javadoc / .net
(?:[\\@](?:brief|groupname|t?param|return|retval)|(?:public|private|\[Parameter(?:\(.+\)|)\])(?:\s+static|\s+override|\s+readonly)*)(?:\s+\{\w+\}|)\s+(\w+)\s+\g{-1}\s
# Commit message -- Signed-off-by and friends
^\s*(?:(?:Based-on-patch|Co-authored|Helped|Mentored|Reported|Reviewed|Signed-off)-by|Thanks-to): (?:[^<]*<[^>]*>|[^<]*)\s*$

View File

@@ -1,6 +1,7 @@
^attache$
^attacher$
^attachers$
^bellow$
benefitting
occurences?
^dependan.*

View File

@@ -7,13 +7,13 @@ on:
- labeled
- unlabeled
permissions: {}
permissions: {}
jobs:
add-to-project:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v0.3.0
- uses: actions/add-to-project@v0.5.0
with:
project-url: https://github.com/orgs/microsoft/projects/159
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}

32
.github/workflows/similarIssues.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: GitGudSimilarIssues comments
on:
issues:
types: [opened]
jobs:
getSimilarIssues:
runs-on: ubuntu-latest
outputs:
message: ${{ steps.getBody.outputs.message }}
steps:
- id: getBody
uses: craigloewen-msft/GitGudSimilarIssues@main
with:
issuetitle: ${{ github.event.issue.title }}
repo: ${{ github.repository }}
similaritytolerance: "0.75"
add-comment:
needs: getSimilarIssues
runs-on: ubuntu-latest
permissions:
issues: write
if: needs.getSimilarIssues.outputs.message != ''
steps:
- name: Add comment
run: gh issue comment "$NUMBER" --repo "$REPO" --body "$BODY"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NUMBER: ${{ github.event.issue.number }}
REPO: ${{ github.repository }}
BODY: ${{ needs.getSimilarIssues.outputs.message }}

View File

@@ -5,7 +5,7 @@ name: Spell checking
# https://github.com/check-spelling/check-spelling/wiki/Feature%3A-Restricted-Permissions
#
# `jobs.comment-push` runs when a push is made to a repository and the `jobs.spelling` job needs to make a comment
# (in odd cases, it might actually run just to collapse a commment, but that's fairly rare)
# (in odd cases, it might actually run just to collapse a comment, but that's fairly rare)
# it needs `contents: write` in order to add a comment.
#
# `jobs.comment-pr` runs when a pull_request is made to a repository and the `jobs.spelling` job needs to make a comment
@@ -34,6 +34,29 @@ name: Spell checking
#
# For background, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-with-deploy-key
# Sarif reporting
#
# Access to Sarif reports is generally restricted (by GitHub) to members of the repository.
#
# Requires enabling `security-events: write`
# and configuring the action with `use_sarif: 1`
#
# For information on the feature, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Sarif-output
# Minimal workflow structure:
#
# on:
# push:
# ...
# pull_request_target:
# ...
# jobs:
# # you only want the spelling job, all others should be omitted
# spelling:
# # remove `security-events: write` and `use_sarif: 1`
# # remove `experimental_apply_changes_via_bot: 1`
# ... otherwise adjust the `with:` as you wish
on:
push:
branches:
@@ -43,8 +66,6 @@ on:
pull_request_target:
branches:
- "**"
tags-ignore:
- "**"
types:
- 'opened'
- 'reopened'
@@ -60,10 +81,11 @@ jobs:
contents: read
pull-requests: read
actions: read
security-events: write
outputs:
followup: ${{ steps.spelling.outputs.followup }}
runs-on: ubuntu-latest
if: "contains(github.event_name, 'pull_request') || github.event_name == 'push'"
if: ${{ contains(github.event_name, 'pull_request') || github.event_name == 'push' }}
concurrency:
group: spelling-${{ github.event.pull_request.number || github.ref }}
# note: If you use only_check_changed_files, you do not want cancel-in-progress
@@ -71,35 +93,50 @@ jobs:
steps:
- name: check-spelling
id: spelling
uses: check-spelling/check-spelling@v0.0.21
uses: check-spelling/check-spelling@v0.0.22
with:
suppress_push_for_open_pull_request: 1
suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }}
checkout: true
check_file_names: 1
spell_check_this: check-spelling/spell-check-this@prerelease
spell_check_this: microsoft/terminal@main
post_comment: 0
use_magic_file: 1
extra_dictionary_limit: 10
report-timing: 1
warnings: bad-regex,binary-file,deprecated-feature,ignored-expect-variant,large-file,limited-references,no-newline-at-eof,noisy-file,non-alpha-in-dictionary,token-is-substring,unexpected-line-ending,whitespace-in-dictionary,minified-file,unsupported-configuration,no-files-to-check
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
use_sarif: ${{ (!github.event.pull_request || (github.event.pull_request.head.repo.full_name == github.repository)) && 1 }}
extra_dictionary_limit: 20
extra_dictionaries:
cspell:software-terms/src/software-terms.txt
cspell:python/src/python/python-lib.txt
cspell:node/node.txt
cspell:cpp/src/stdlib-c.txt
cspell:software-terms/dict/softwareTerms.txt
cspell:cpp/src/stdlib-cpp.txt
cspell:fullstack/fullstack.txt
cspell:lorem-ipsum/dictionary.txt
cspell:cpp/src/stdlib-c.txt
cspell:php/dict/php.txt
cspell:filetypes/filetypes.txt
cspell:html/html.txt
cspell:cpp/src/compiler-msvc.txt
cspell:java/src/java.txt
cspell:python/src/common/extra.txt
cspell:powershell/powershell.txt
cspell:node/dict/node.txt
cspell:java/src/java-terms.txt
cspell:aws/aws.txt
cspell:cpp/src/lang-keywords.txt
cspell:npm/npm.txt
cspell:dotnet/dotnet.txt
cspell:python/src/python/python.txt
cspell:css/css.txt
cspell:typescript/dict/typescript.txt
cspell:dotnet/dict/dotnet.txt
cspell:golang/dict/go.txt
cspell:fullstack/dict/fullstack.txt
cspell:cpp/src/compiler-msvc.txt
cspell:python/src/python/python-lib.txt
cspell:mnemonics/src/mnemonics.txt
cspell:cpp/src/stdlib-cmath.txt
check_extra_dictionaries: ''
cspell:css/dict/css.txt
cspell:cpp/src/lang-keywords.txt
cspell:django/dict/django.txt
cspell:python/src/python/python.txt
cspell:html/dict/html.txt
cspell:cpp/src/ecosystem.txt
cspell:cpp/src/compiler-clang-attributes.txt
cspell:npm/dict/npm.txt
cspell:r/src/r.txt
cspell:powershell/dict/powershell.txt
cspell:csharp/csharp.txt
comment-push:
name: Report (Push)
@@ -111,10 +148,10 @@ jobs:
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push'
steps:
- name: comment
uses: check-spelling/check-spelling@v0.0.21
uses: check-spelling/check-spelling@v0.0.22
with:
checkout: true
spell_check_this: check-spelling/spell-check-this@prerelease
spell_check_this: microsoft/terminal@main
task: ${{ needs.spelling.outputs.followup }}
comment-pr:
@@ -123,12 +160,38 @@ jobs:
runs-on: ubuntu-latest
needs: spelling
permissions:
contents: read
pull-requests: write
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
steps:
- name: comment
uses: check-spelling/check-spelling@v0.0.21
uses: check-spelling/check-spelling@v0.0.22
with:
checkout: true
spell_check_this: check-spelling/spell-check-this@prerelease
spell_check_this: microsoft/terminal@main
task: ${{ needs.spelling.outputs.followup }}
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
update:
name: Update PR
permissions:
contents: write
pull-requests: write
actions: read
runs-on: ubuntu-latest
if: ${{
github.repository_owner != 'microsoft' &&
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
contains(github.event.comment.body, '@check-spelling-bot apply')
}}
concurrency:
group: spelling-update-${{ github.event.issue.number }}
cancel-in-progress: false
steps:
- name: apply spelling updates
uses: check-spelling/check-spelling@v0.0.22
with:
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
checkout: true
ssh_key: "${{ secrets.CHECK_SPELLING }}"

View File

@@ -14,7 +14,7 @@ The point of doing all this work in public is to ensure that we are holding ours
The team triages new issues several times a week. During triage, the team uses labels to categorize, manage, and drive the project workflow.
We employ [a bot engine](https://github.com/microsoft/terminal/blob/main/doc/bot.md) to help us automate common processes within our workflow.
We employ [a bot engine](./doc/bot.md) to help us automate common processes within our workflow.
We drive the bot by tagging issues with specific labels which cause the bot engine to close issues, merge branches, etc. This bot engine helps us keep the repo clean by automating the process of notifying appropriate parties if/when information/follow-up is needed, and closing stale issues/PRs after reminders have remained unanswered for several days.

View File

@@ -239,8 +239,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{89CDCC
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Types.Unit.Tests", "src\types\ut_types\Types.Unit.Tests.vcxproj", "{34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PublicTerminalCore", "src\cascadia\PublicTerminalCore\PublicTerminalCore.vcxproj", "{84848BFA-931D-42CE-9ADF-01EE54DE7890}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfTerminalControl", "src\cascadia\WpfTerminalControl\WpfTerminalControl.csproj", "{376FE273-6B84-4EB5-8B30-8DE9D21B022C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_TerminalApp", "src\cascadia\ut_app\TerminalApp.UnitTests.vcxproj", "{CA5CAD1A-9333-4D05-B12A-1905CBF112F9}"
@@ -334,7 +332,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fmt", "src\dep\fmt\fmt.vcxp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfTerminalTestNetCore", "src\cascadia\WpfTerminalTestNetCore\WpfTerminalTestNetCore.csproj", "{1588FD7C-241E-4E7D-9113-43735F3E6BAD}"
ProjectSection(ProjectDependencies) = postProject
{84848BFA-931D-42CE-9ADF-01EE54DE7890} = {84848BFA-931D-42CE-9ADF-01EE54DE7890}
{CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070}
{A22EC5F6-7851-4B88-AC52-47249D437A52} = {A22EC5F6-7851-4B88-AC52-47249D437A52}
EndProjectSection
EndProject
@@ -1711,34 +1709,6 @@ Global
{34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Release|x64.Build.0 = Release|x64
{34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Release|x86.ActiveCfg = Release|Win32
{34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Release|x86.Build.0 = Release|Win32
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.AuditMode|x64.ActiveCfg = AuditMode|x64
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.AuditMode|x64.Build.0 = AuditMode|x64
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.AuditMode|x86.Build.0 = AuditMode|Win32
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|Any CPU.ActiveCfg = Debug|Win32
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|ARM.ActiveCfg = Debug|Win32
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|ARM64.ActiveCfg = Debug|ARM64
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|ARM64.Build.0 = Debug|ARM64
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|x64.ActiveCfg = Debug|x64
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|x64.Build.0 = Debug|x64
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|x86.ActiveCfg = Debug|Win32
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|x86.Build.0 = Debug|Win32
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|Any CPU.ActiveCfg = Release|Win32
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|ARM.ActiveCfg = Release|Win32
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|ARM64.ActiveCfg = Release|ARM64
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|ARM64.Build.0 = Release|ARM64
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|x64.ActiveCfg = Release|x64
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|x64.Build.0 = Release|x64
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|x86.ActiveCfg = Release|Win32
{84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|x86.Build.0 = Release|Win32
{376FE273-6B84-4EB5-8B30-8DE9D21B022C}.AuditMode|Any CPU.ActiveCfg = Release|Any CPU
{376FE273-6B84-4EB5-8B30-8DE9D21B022C}.AuditMode|ARM.ActiveCfg = Debug|Any CPU
{376FE273-6B84-4EB5-8B30-8DE9D21B022C}.AuditMode|ARM.Build.0 = Debug|Any CPU
@@ -2894,7 +2864,6 @@ Global
{05500DEF-2294-41E3-AF9A-24E580B82836} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
{1E4A062E-293B-4817-B20D-BF16B979E350} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
{34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
{84848BFA-931D-42CE-9ADF-01EE54DE7890} = {4DAF0299-495E-4CD1-A982-9BAC16A45932}
{376FE273-6B84-4EB5-8B30-8DE9D21B022C} = {4DAF0299-495E-4CD1-A982-9BAC16A45932}
{CA5CAD1A-9333-4D05-B12A-1905CBF112F9} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
{CA5CAD1A-9A12-429C-B551-8562EC954746} = {59840756-302F-44DF-AA47-441A9D673202}

View File

@@ -1,4 +1,4 @@
![terminal-logos](https://user-images.githubusercontent.com/48369326/115790869-4c852b00-a37c-11eb-97f1-f61972c7800c.png)
![terminal-logos](https://github.com/microsoft/terminal/assets/91625426/333ddc76-8ab2-4eb4-a8c0-4d7b953b1179)
# Welcome to the Windows Terminal, Console and Command-Line repo
@@ -8,8 +8,8 @@ This repository contains the source code for:
* [Windows Terminal Preview](https://aka.ms/terminal-preview)
* The Windows console host (`conhost.exe`)
* Components shared between the two projects
* [ColorTool](https://github.com/microsoft/terminal/tree/main/src/tools/ColorTool)
* [Sample projects](https://github.com/microsoft/terminal/tree/main/samples)
* [ColorTool](./src/tools/ColorTool)
* [Sample projects](./samples)
that show how to consume the Windows Console APIs
Related repositories include:
@@ -21,7 +21,7 @@ Related repositories include:
## Installing and running Windows Terminal
> **Note**\
> [!NOTE]
> Windows Terminal requires Windows 10 2004 (build 19041) or later
### Microsoft Store [Recommended]
@@ -53,7 +53,7 @@ fails for any reason, you can try the following command at a PowerShell prompt:
Add-AppxPackage Microsoft.WindowsTerminal_<versionNumber>.msixbundle
```
> **Note**\
> [!NOTE]
> If you install Terminal manually:
>
> * You may need to install the [VC++ v14 Desktop Framework Package](https://docs.microsoft.com/troubleshoot/cpp/c-runtime-packages-desktop-bridge#how-to-install-and-update-desktop-framework-packages).
@@ -72,8 +72,8 @@ package:
winget install --id Microsoft.WindowsTerminal -e
```
> **Note**\
> Due to [a dependency issue](https://github.com/microsoft/terminal/issues/15663), Terminal's current versions cannot be installed via the Windows Package Manager CLI. To install the stable release 1.17 or later, or the Preview release 1.18 or later, please use an alternative installation method.
> [!NOTE]
> Dependency support is available in WinGet version [1.6.2631 or later](https://github.com/microsoft/winget-cli/releases). To install the Terminal stable release 1.18 or later, please make sure you have the updated version of the WinGet client.
#### Via Chocolatey (unofficial)
@@ -118,9 +118,31 @@ repository.
---
## Installing Windows Terminal Canary
Windows Terminal Canary is a nightly build of Windows Terminal. This build has the latest code from our `main` branch, giving you an opportunity to try features before they make it to Windows Terminal Preview.
Windows Terminal Canary is our least stable offering, so you may discover bugs before we have had a chance to find them.
Windows Terminal Canary is available as an App Installer distribution and a Portable ZIP distribution.
The App Installer distribution supports automatic updates. Due to platform limitations, this installer only works on Windows 11.
The Portable ZIP distribution is a portable application. It will not automatically update and will not automatically check for updates. This portable ZIP distribution works on Windows 10 (19041+) and Windows 11.
| Distribution | Architecture | Link |
|---------------|:---------------:|------------------------------------------------------|
| App Installer | x64, arm64, x86 | [download](https://aka.ms/terminal-canary-installer) |
| Portable ZIP | x64 | [download](https://aka.ms/terminal-canary-zip-x64) |
| Portable ZIP | ARM64 | [download](https://aka.ms/terminal-canary-zip-arm64) |
| Portable ZIP | x86 | [download](https://aka.ms/terminal-canary-zip-x86) |
_Learn more about the [types of Windows Terminal distributions](https://learn.microsoft.com/windows/terminal/distributions)._
---
## Windows Terminal Roadmap
The plan for the Windows Terminal [is described here](/doc/roadmap-2022.md) and
The plan for the Windows Terminal [is described here](/doc/roadmap-2023.md) and
will be updated as the project proceeds.
## Project Build Status
@@ -240,7 +262,7 @@ Cause: You're launching the incorrect solution in Visual Studio.
Solution: Make sure you're building & deploying the `CascadiaPackage` project in
Visual Studio.
> **Note**\
> [!NOTE]
> `OpenConsole.exe` is just a locally-built `conhost.exe`, the classic
> Windows Console that hosts Windows' command-line infrastructure. OpenConsole
> is used by Windows Terminal to connect to and communicate with command-line
@@ -264,7 +286,7 @@ enhance Windows Terminal\!
***BEFORE you start work on a feature/fix***, please read & follow our
[Contributor's
Guide](https://github.com/microsoft/terminal/blob/main/CONTRIBUTING.md) to
Guide](./CONTRIBUTING.md) to
help avoid any wasted or duplicate effort.
## Communicating with the Team
@@ -365,10 +387,10 @@ Please review these brief docs below about our coding practices.
This is a work in progress as we learn what we'll need to provide people in
order to be effective contributors to our project.
* [Coding Style](https://github.com/microsoft/terminal/blob/main/doc/STYLE.md)
* [Code Organization](https://github.com/microsoft/terminal/blob/main/doc/ORGANIZATION.md)
* [Exceptions in our legacy codebase](https://github.com/microsoft/terminal/blob/main/doc/EXCEPTIONS.md)
* [Helpful smart pointers and macros for interfacing with Windows in WIL](https://github.com/microsoft/terminal/blob/main/doc/WIL.md)
* [Coding Style](./doc/STYLE.md)
* [Code Organization](./doc/ORGANIZATION.md)
* [Exceptions in our legacy codebase](./doc/EXCEPTIONS.md)
* [Helpful smart pointers and macros for interfacing with Windows in WIL](./doc/WIL.md)
---

View File

@@ -14,4 +14,4 @@ Support for Windows Terminal is limited to the resources listed above.
[gh-bug]: https://github.com/microsoft/terminal/issues/new?assignees=&labels=Issue-Bug&template=bug_report.md&title=
[gh-feature]: https://github.com/microsoft/terminal/issues/new?assignees=&labels=Issue-Feature&template=Feature_Request.md&title=
[docs]: https://docs.microsoft.com/windows/terminal
[contributor]: https://github.com/microsoft/terminal/blob/main/CONTRIBUTING.md
[contributor]: ./CONTRIBUTING.md

View File

@@ -1,7 +1,7 @@
[
{
"MatchedPath": [
"PublicTerminalCore.dll"
"Microsoft.Terminal.Control/Microsoft.Terminal.Control.dll"
],
"SigningInfo": {
"Operations": [

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<AppInstaller
xmlns="http://schemas.microsoft.com/appx/appinstaller/2017/2"
Version="1.0.0.0"
Uri="$$ROOT$$$$NAME$$.appinstaller">
<MainBundle
Name="$$NAME$$"
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
Version="$$VERSION$$"
Uri="$$ROOT$$$$PACKAGE$$" />
<Dependencies>
<Package
Name="Microsoft.UI.Xaml.2.8"
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
Version="8.2305.5001.0"
ProcessorArchitecture="x64"
Uri="https://github.com/microsoft/microsoft-ui-xaml/releases/download/v2.8.4/Microsoft.UI.Xaml.2.8.x64.appx" />
<Package
Name="Microsoft.UI.Xaml.2.8"
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
Version="8.2305.5001.0"
ProcessorArchitecture="x86"
Uri="https://github.com/microsoft/microsoft-ui-xaml/releases/download/v2.8.4/Microsoft.UI.Xaml.2.8.x86.appx" />
<Package
Name="Microsoft.UI.Xaml.2.8"
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
Version="8.2305.5001.0"
ProcessorArchitecture="arm64"
Uri="https://github.com/microsoft/microsoft-ui-xaml/releases/download/v2.8.4/Microsoft.UI.Xaml.2.8.arm64.appx" />
</Dependencies>
<UpdateSettings>
<OnLaunch
HoursBetweenUpdateChecks="6" />
</UpdateSettings>
</AppInstaller>

6
build/config/tsa.json Normal file
View File

@@ -0,0 +1,6 @@
{
"instanceUrl": "https://microsoft.visualstudio.com",
"projectName": "OS",
"areaPath": "OS\\Windows Client and Services\\ADEPT\\E4D-Engineered for Developers\\SHINE\\Terminal",
"notificationAliases": ["condev@microsoft.com", "duhowett@microsoft.com"]
}

View File

@@ -102,7 +102,7 @@ stages:
- ${{ if ne(variables['Build.Reason'], 'PullRequest') }}:
- stage: CodeIndexer
displayName: Github CodeNav Indexer
displayName: GitHub CodeNav Indexer
dependsOn: []
jobs:
- template: ./templates-v2/job-index-github-codenav.yml

View File

@@ -1,23 +0,0 @@
trigger: none
pr: none
schedules:
- cron: "30 3 * * 2-6" # Run at 03:30 UTC Tuesday through Saturday (After the work day in Pacific, Mon-Fri)
displayName: "Nightly Terminal Build"
branches:
include:
- main
always: false # only run if there's code changes!
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
extends:
template: templates-v2\pipeline-full-release-build.yml
parameters:
branding: Canary
buildTerminal: true
pgoBuildMode: Optimize
codeSign: true
generateSbom: true
publishSymbolsToPublic: true
publishVpackToWindows: false
symbolExpiryTime: 15 # Nightly builds do not keep symbols for very long!

View File

@@ -0,0 +1,53 @@
trigger: none
pr: none
schedules:
- cron: "30 3 * * 2-6" # Run at 03:30 UTC Tuesday through Saturday (After the work day in Pacific, Mon-Fri)
displayName: "Nightly Terminal Build"
branches:
include:
- main
always: false # only run if there's code changes!
parameters:
- name: publishToAzure
displayName: "Deploy to **PUBLIC** Azure Storage"
type: boolean
default: true
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
variables:
- template: templates-v2/variables-nuget-package-version.yml
parameters:
branding: Canary
- template: templates-v2/variables-onebranch-config.yml
extends:
template: templates-v2/pipeline-onebranch-full-release-build.yml
parameters:
official: true
branding: Canary
buildTerminal: true
pgoBuildMode: Optimize
codeSign: true
publishSymbolsToPublic: true
publishVpackToWindows: false
symbolExpiryTime: 15
${{ if eq(true, parameters.publishToAzure) }}:
extraPublishJobs:
- template: build/pipelines/templates-v2/job-deploy-to-azure-storage.yml@self
parameters:
pool: { type: windows }
variables:
ob_git_checkout: false # This job checks itself out
ob_git_skip_checkout_none: true
ob_outputDirectory: "$(Build.SourcesDirectory)/_none"
dependsOn: [PublishSymbols]
storagePublicRootURL: $(AppInstallerRootURL)
subscription: $(AzureSubscriptionName)
storageAccount: $(AzureStorageAccount)
storageContainer: $(AzureStorageContainer)
buildConfiguration: Release
buildPlatforms: [x64, x86, arm64]
environment: production-canary

View File

@@ -44,14 +44,6 @@ parameters:
- x64
- x86
- arm64
- name: codeSign
displayName: "Sign all build outputs"
type: boolean
default: true
- name: generateSbom
displayName: "Generate a Bill of Materials"
type: boolean
default: true
- name: terminalInternalPackageVersion
displayName: "Terminal Internal Package Version"
type: string
@@ -68,9 +60,16 @@ parameters:
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
variables:
- template: templates-v2/variables-nuget-package-version.yml
parameters:
branding: ${{ parameters.branding }}
- template: templates-v2/variables-onebranch-config.yml
extends:
template: templates-v2/pipeline-full-release-build.yml
template: templates-v2/pipeline-onebranch-full-release-build.yml
parameters:
official: true
branding: ${{ parameters.branding }}
buildTerminal: ${{ parameters.buildTerminal }}
buildConPTY: ${{ parameters.buildConPTY }}
@@ -78,8 +77,7 @@ extends:
pgoBuildMode: ${{ parameters.pgoBuildMode }}
buildConfigurations: ${{ parameters.buildConfigurations }}
buildPlatforms: ${{ parameters.buildPlatforms }}
codeSign: ${{ parameters.codeSign }}
generateSbom: ${{ parameters.generateSbom }}
codeSign: true
terminalInternalPackageVersion: ${{ parameters.terminalInternalPackageVersion }}
publishSymbolsToPublic: ${{ parameters.publishSymbolsToPublic }}
publishVpackToWindows: ${{ parameters.publishVpackToWindows }}

View File

@@ -97,7 +97,7 @@ jobs:
flattenFolders: true
- ${{ if eq(parameters.codeSign, true) }}:
- task: EsrpCodeSigning@1
- task: EsrpCodeSigning@3
displayName: Submit *.nupkg to ESRP for code signing
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a

View File

@@ -62,6 +62,9 @@ parameters:
- name: publishArtifacts
type: boolean
default: true
- name: removeAllNonSignedFiles
type: boolean
default: false
jobs:
- job: ${{ parameters.jobName }}
@@ -89,6 +92,11 @@ jobs:
# Yup.
BuildTargetParameter: ' '
SelectedSigningFragments: ' '
# When building the unpackaged distribution, build it in portable mode if it's Canary-branded
${{ if eq(parameters.branding, 'Canary') }}:
UnpackagedBuildArguments: -PortableMode
${{ else }}:
UnpackagedBuildArguments: ' '
JobOutputDirectory: $(Terminal.BinDir)
JobOutputArtifactName: build-$(BuildPlatform)-$(BuildConfiguration)${{ parameters.artifactStem }}
${{ insert }}: ${{ parameters.variables }}
@@ -114,7 +122,7 @@ jobs:
$SignFragments += "wpfdotnet"
}
If ([bool]::Parse("${{ parameters.buildWPF }}")) {
$BuildTargets += "Terminal\wpf\PublicTerminalCore"
$BuildTargets += "Terminal\Control\Microsoft_Terminal_Control"
$SignFragments += "wpf"
}
If ([bool]::Parse("${{ parameters.buildConPTY }}")) {
@@ -168,6 +176,7 @@ jobs:
# - Directories ending in Lib (static lib projects that we fully linked into DLLs which may also contain unnecessary resources)
# - All LocalTests_ project outputs, as they were subsumed into TestHostApp
# - All PDB files inside the WindowsTerminal/ output, which do not belong there.
# - console.dll, which apparently breaks XFGCheck? lol.
- pwsh: |-
$binDir = '$(Terminal.BinDir)'
$ImportLibs = Get-ChildItem $binDir -Recurse -File -Filter '*.exp' | ForEach-Object { $_.FullName -Replace "exp$","lib" }
@@ -184,6 +193,8 @@ jobs:
$Items += Get-ChildItem '$(Terminal.BinDir)' -Filter '*.pdb' -Recurse
}
$Items += Get-ChildItem $binDir -Filter 'console.dll'
$Items | Remove-Item -Recurse -Force -Verbose -ErrorAction:Ignore
displayName: Clean up static libs and extra symbols
errorActionPreference: silentlyContinue # It's OK if this silently fails
@@ -224,7 +235,7 @@ jobs:
# Code-sign everything we just put together.
# We run the signing in Terminal.BinDir, because all of the signing batches are relative to the final architecture/configuration output folder.
- task: EsrpCodeSigning@1
- task: EsrpCodeSigning@3
displayName: Submit Signing Request
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
@@ -241,6 +252,14 @@ jobs:
Write-Host "##vso[task.setvariable variable=WindowsTerminalPackagePath]${PackageFilename}"
displayName: Re-pack the new Terminal package after signing
# Some of our governed pipelines explicitly fail builds that have *any* non-codesigned filed (!)
- ${{ if eq(parameters.removeAllNonSignedFiles, true) }}:
- pwsh: |-
Get-ChildItem "$(Terminal.BinDir)" -Recurse -Include "*.dll","*.exe" |
Where-Object { (Get-AuthenticodeSignature $_).Status -Ne "Valid" } |
Remove-Item -Verbose -Force
displayName: Remove all non-signed output files
- ${{ else }}: # No Signing
- ${{ if or(parameters.buildTerminal, parameters.buildEverything) }}:
- pwsh: |-
@@ -255,7 +274,7 @@ jobs:
- pwsh: |-
$XamlAppxPath = (Get-Item "src\cascadia\CascadiaPackage\AppPackages\*\Dependencies\$(BuildPlatform)\Microsoft.UI.Xaml*.appx").FullName
$outDir = New-Item -Type Directory "$(Terminal.BinDir)/_unpackaged" -ErrorAction:Ignore
& .\build\scripts\New-UnpackagedTerminalDistribution.ps1 -TerminalAppX $(WindowsTerminalPackagePath) -XamlAppX $XamlAppxPath -Destination $outDir.FullName
& .\build\scripts\New-UnpackagedTerminalDistribution.ps1 $(UnpackagedBuildArguments) -TerminalAppX $(WindowsTerminalPackagePath) -XamlAppX $XamlAppxPath -Destination $outDir.FullName
displayName: Build Unpackaged Distribution (from MSIX)
condition: and(succeeded(), ne(variables.WindowsTerminalPackagePath, ''))

View File

@@ -0,0 +1,92 @@
parameters:
- name: buildConfiguration
type: string
- name: buildPlatforms
type: object
- name: pool
type: object
default: []
- name: dependsOn
type: object
default: null
- name: artifactStem
type: string
default: ''
- name: variables
type: object
default: {}
- name: environment
type: string
- name: storagePublicRootURL
type: string
- name: subscription
type: string
- name: storageAccount
type: string
- name: storageContainer
type: string
jobs:
- job: DeployAzure
${{ if ne(length(parameters.pool), 0) }}:
pool: ${{ parameters.pool }}
displayName: Publish to Azure Storage (Prod)
dependsOn: ${{ parameters.dependsOn }}
variables:
${{ insert }}: ${{ parameters.variables }}
steps:
- download: none
- checkout: self
clean: true
fetchDepth: 1
fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here
submodules: true
persistCredentials: True
- task: DownloadPipelineArtifact@2
displayName: Download MSIX Bundle Artifact
inputs:
artifactName: appxbundle-${{ parameters.buildConfiguration }}${{ parameters.artifactStem }}
downloadPath: '$(Build.SourcesDirectory)/_out'
itemPattern: '**/*.msixbundle'
- ${{ each platform in parameters.buildPlatforms }}:
- task: DownloadPipelineArtifact@2
displayName: Download unpackaged build for ${{ platform }} ${{ parameters.buildConfiguration }}
inputs:
artifactName: build-${{ platform }}-${{ parameters.buildConfiguration }}${{ parameters.artifactStem }}
downloadPath: '$(Build.SourcesDirectory)/_unpackaged'
itemPattern: '**/_unpackaged/*.zip'
- pwsh: |-
$b = Get-Item _out/*.msixbundle
./build/scripts/New-AppInstallerFromTemplateAndBundle.ps1 -BundlePath $b.FullName -AppInstallerTemplatePath ./build/config/template.appinstaller -AppInstallerRoot "${{ parameters.storagePublicRootURL }}" -OutputPath _out/Microsoft.WindowsTerminalCanary.appinstaller
displayName: "Produce AppInstaller for MSIX bundle"
- pwsh: |-
$zips = Get-ChildItem -Recurse -Filter *.zip _unpackaged
$zips | ForEach-Object {
$name = $_.Name
$parts = $name.Split('_')
$parts[1] = "latest"
$name = [String]::Join('_', $parts)
$_ | Move-Item -Destination (Join-Path "_out" $name)
}
displayName: "Wrangle Unpackaged builds into place, rename"
- powershell: |-
Get-PackageProvider -Name NuGet -ForceBootstrap
Install-Module -Verbose -AllowClobber -Force Az.Accounts, Az.Storage, Az.Network, Az.Resources, Az.Compute
displayName: Install Azure Module Dependencies
- task: AzureFileCopy@5
displayName: Publish to Storage Account
inputs:
sourcePath: _out/*
Destination: AzureBlob
azureSubscription: ${{ parameters.subscription }}
storage: ${{ parameters.storageAccount }}
ContainerName: ${{ parameters.storageContainer }}
AdditionalArgumentsForBlobCopy: "--content-type application/octet-stream"

View File

@@ -1,6 +1,6 @@
jobs:
- job: CodeNavIndexer
displayName: Run Github CodeNav Indexer
displayName: Run GitHub CodeNav Indexer
pool: { vmImage: windows-2022 }
steps:

View File

@@ -29,6 +29,9 @@ parameters:
- name: publishArtifacts
type: boolean
default: true
- name: afterBuildSteps
type: stepList
default: []
jobs:
- job: ${{ parameters.jobName }}
@@ -48,6 +51,8 @@ jobs:
BundleStemName: Microsoft.WindowsTerminal
${{ elseif eq(parameters.branding, 'Preview') }}:
BundleStemName: Microsoft.WindowsTerminalPreview
${{ elseif eq(parameters.branding, 'Canary') }}:
BundleStemName: Microsoft.WindowsTerminalCanary
${{ else }}:
BundleStemName: WindowsTerminalDev
JobOutputDirectory: '$(System.ArtifactsDirectory)/bundle'
@@ -83,11 +88,13 @@ jobs:
$Components[0] = ([int]$Components[0] + $VersionEpoch)
$BundleVersion = $Components -Join "."
New-Item -Type Directory "$(System.ArtifactsDirectory)/bundle"
.\build\scripts\Create-AppxBundle.ps1 -InputPath 'bin/' -ProjectName CascadiaPackage -BundleVersion $BundleVersion -OutputPath "$(System.ArtifactsDirectory)\bundle\$(BundleStemName)_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
$BundlePath = "$(System.ArtifactsDirectory)\bundle\$(BundleStemName)_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
.\build\scripts\Create-AppxBundle.ps1 -InputPath 'bin/' -ProjectName CascadiaPackage -BundleVersion $BundleVersion -OutputPath $BundlePath
Write-Host "##vso[task.setvariable variable=MsixBundlePath]${BundlePath}"
displayName: Create msixbundle
- ${{ if eq(parameters.codeSign, true) }}:
- task: EsrpCodeSigning@1
- task: EsrpCodeSigning@3
displayName: Submit *.msixbundle to ESRP for code signing
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
@@ -137,6 +144,8 @@ jobs:
ValidateSignature: true
Verbosity: 'Verbose'
- ${{ parameters.afterBuildSteps }}
- ${{ if eq(parameters.publishArtifacts, true) }}:
- publish: $(JobOutputDirectory)
artifact: $(JobOutputArtifactName)

View File

@@ -82,7 +82,7 @@ jobs:
versionEnvVar: XES_PACKAGEVERSIONNUMBER
- ${{ if eq(parameters.codeSign, true) }}:
- task: EsrpCodeSigning@1
- task: EsrpCodeSigning@3
displayName: Submit *.nupkg to ESRP for code signing
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a

View File

@@ -17,6 +17,12 @@ parameters:
- name: symbolExpiryTime
type: string
default: 36530 # This is the default from PublishSymbols@2
- name: variables
type: object
default: {}
- name: symbolPatGoesInTaskInputs
type: boolean
default: false
jobs:
- job: ${{ parameters.jobName }}
@@ -27,6 +33,8 @@ jobs:
${{ else }}:
displayName: Publish Symbols Internally
dependsOn: ${{ parameters.dependsOn }}
variables:
${{ insert }}: ${{ parameters.variables }}
steps:
- checkout: self
clean: true
@@ -76,6 +84,8 @@ jobs:
SymbolsProduct: 'Windows Terminal Converged Symbols'
SymbolsVersion: '$(XES_APPXMANIFESTVERSION)'
SymbolExpirationInDays: ${{ parameters.symbolExpiryTime }}
${{ if eq(parameters.symbolPatGoesInTaskInputs, true) }}:
Pat: $(ADO_microsoftpublicsymbols_PAT)
# The ADO task does not support indexing of GitHub sources.
# There is a bug which causes this task to fail if LIB includes an inaccessible path (even though it does not depend on it).
# To work around this issue, we just force LIB to be any dir that we know exists.
@@ -83,4 +93,5 @@ jobs:
env:
LIB: $(Build.SourcesDirectory)
ArtifactServices_Symbol_AccountName: microsoftpublicsymbols
ArtifactServices_Symbol_PAT: $(ADO_microsoftpublicsymbols_PAT)
${{ if ne(parameters.symbolPatGoesInTaskInputs, true) }}:
ArtifactServices_Symbol_PAT: $(ADO_microsoftpublicsymbols_PAT)

View File

@@ -51,6 +51,9 @@ parameters:
type: boolean
default: false
- name: extraPublishJobs
type: object
default: []
- name: pool
type: object
default:
@@ -58,28 +61,9 @@ parameters:
demands: ImageOverride -equals SHINE-VS17-Latest
variables:
# If we are building a branch called "release-*", change the NuGet suffix
# to "preview". If we don't do that, XES will set the suffix to "release1"
# because it truncates the value after the first period.
# We also want to disable the suffix entirely if we're Release branded while
# on a release branch.
# main is special, however. XES ignores main. Since we never produce actual
# shipping builds from main, we want to force it to have a beta label as
# well.
#
# In effect:
# BRANCH / BRANDING | Release | Preview
# ------------------|----------------------------|-----------------------------
# release-* | 1.12.20220427 | 1.13.20220427-preview
# main | 1.14.20220427-experimental | 1.14.20220427-experimental
# all others | 1.14.20220427-mybranch | 1.14.20220427-mybranch
${{ if startsWith(variables['Build.SourceBranchName'], 'release-') }}:
${{ if eq(parameters.branding, 'Release') }}:
NoNuGetPackBetaVersion: true
${{ else }}:
NuGetPackBetaVersion: preview
${{ elseif eq(variables['Build.SourceBranchName'], 'main') }}:
NuGetPackBetaVersion: experimental
- template: variables-nuget-package-version.yml
parameters:
branding: ${{ parameters.branding }}
resources:
repositories:
@@ -193,4 +177,5 @@ stages:
includePublicSymbolServer: ${{ parameters.publishSymbolsToPublic }}
symbolExpiryTime: ${{ parameters.symbolExpiryTime }}
- ${{ parameters.extraPublishJobs }}
...

View File

@@ -0,0 +1,265 @@
parameters:
- name: official
type: boolean
default: false
- name: branding
type: string
default: Release
values:
- Release
- Preview
- Canary
- Dev
- name: buildTerminal
type: boolean
default: true
- name: buildConPTY
type: boolean
default: false
- name: buildWPF
type: boolean
default: false
- name: pgoBuildMode
type: string
default: Optimize
values:
- Optimize
- Instrument
- None
- name: buildConfigurations
type: object
default:
- Release
- name: buildPlatforms
type: object
default:
- x64
- x86
- arm64
- name: codeSign
type: boolean
default: true
- name: terminalInternalPackageVersion
type: string
default: '0.0.8'
- name: publishSymbolsToPublic
type: boolean
default: true
- name: symbolExpiryTime
type: string
default: 36530 # This is the default from PublishSymbols@2
- name: publishVpackToWindows
type: boolean
default: false
- name: extraPublishJobs
type: object
default: []
resources:
repositories:
- repository: templates
type: git
name: OneBranch.Pipelines/GovernedTemplates
ref: refs/heads/main
extends:
${{ if eq(parameters.official, true) }}:
template: v2/Microsoft.Official.yml@templates # https://aka.ms/obpipelines/templates
${{ else }}:
template: v2/Microsoft.NonOfficial.yml@templates
parameters:
featureFlags:
WindowsHostVersion: 1ESWindows2022
platform:
name: 'windows_undocked'
product: 'Windows Terminal'
cloudvault: # https://aka.ms/obpipelines/cloudvault
enabled: false
globalSdl: # https://aka.ms/obpipelines/sdl
tsa:
enabled: true
configFile: '$(Build.SourcesDirectory)\build\config\tsa.json'
binskim:
break: false
scanOutputDirectoryOnly: true
policheck:
break: false
severity: Note
baseline:
baselineFile: '$(Build.SourcesDirectory)\build\config\release.gdnbaselines'
suppressionSet: default
stages:
- stage: Build
displayName: Build
dependsOn: []
jobs:
- template: ./build/pipelines/templates-v2/job-build-project.yml@self
parameters:
pool: { type: windows }
variables:
ob_git_checkout: false # This job checks itself out
ob_git_skip_checkout_none: true
ob_outputDirectory: $(JobOutputDirectory)
ob_artifactBaseName: $(JobOutputArtifactName)
publishArtifacts: false # Handled by OneBranch
branding: ${{ parameters.branding }}
buildTerminal: ${{ parameters.buildTerminal }}
buildConPTY: ${{ parameters.buildConPTY }}
buildWPF: ${{ parameters.buildWPF }}
pgoBuildMode: ${{ parameters.pgoBuildMode }}
buildConfigurations: ${{ parameters.buildConfigurations }}
buildPlatforms: ${{ parameters.buildPlatforms }}
generateSbom: false # this is handled by onebranch
removeAllNonSignedFiles: true # appease the overlords
codeSign: ${{ parameters.codeSign }}
beforeBuildSteps: # Right before we build, lay down the universal package and localizations
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- task: UniversalPackages@0
displayName: Download terminal-internal Universal Package
inputs:
feedListDownload: 2b3f8893-a6e8-411f-b197-a9e05576da48
packageListDownload: e82d490c-af86-4733-9dc4-07b772033204
versionListDownload: ${{ parameters.terminalInternalPackageVersion }}
- template: ./build/pipelines/templates-v2/steps-fetch-and-prepare-localizations.yml@self
parameters:
includePseudoLoc: true
- ${{ if eq(parameters.buildWPF, true) }}:
# Add an Any CPU build flavor for the WPF control bits
- template: ./build/pipelines/templates-v2/job-build-project.yml@self
parameters:
pool: { type: windows }
variables:
ob_git_checkout: false # This job checks itself out
ob_git_skip_checkout_none: true
ob_outputDirectory: $(JobOutputDirectory)
ob_artifactBaseName: $(JobOutputArtifactName)
publishArtifacts: false # Handled by OneBranch
jobName: BuildWPF
branding: ${{ parameters.branding }}
buildTerminal: false
buildWPFDotNetComponents: true
buildConfigurations: ${{ parameters.buildConfigurations }}
buildPlatforms:
- Any CPU
generateSbom: false # this is handled by onebranch
removeAllNonSignedFiles: true # appease the overlords
codeSign: ${{ parameters.codeSign }}
beforeBuildSteps:
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
# WPF doesn't need the localizations or the universal package, but if it does... put them here.
- stage: Package
displayName: Package
dependsOn: [Build]
jobs:
- ${{ if eq(parameters.buildTerminal, true) }}:
- template: ./build/pipelines/templates-v2/job-merge-msix-into-bundle.yml@self
parameters:
pool: { type: windows }
variables:
ob_git_checkout: false # This job checks itself out
ob_git_skip_checkout_none: true
ob_outputDirectory: $(JobOutputDirectory)
ob_artifactBaseName: $(JobOutputArtifactName)
### This job is also in charge of submitting the vpack to Windows if it's enabled
ob_createvpack_enabled: ${{ and(parameters.buildTerminal, parameters.publishVpackToWindows) }}
ob_updateOSManifest_enabled: ${{ and(parameters.buildTerminal, parameters.publishVpackToWindows) }}
### If enabled above, these options are in play.
ob_createvpack_packagename: 'WindowsTerminal.app'
ob_createvpack_owneralias: 'conhost@microsoft.com'
ob_createvpack_description: 'VPack for the Windows Terminal Application'
ob_createvpack_targetDestinationDirectory: '$(Destination)'
ob_createvpack_propsFile: false
ob_createvpack_provData: true
ob_createvpack_metadata: '$(Build.SourceVersion)'
ob_createvpack_topLevelRetries: 0
ob_createvpack_failOnStdErr: true
ob_createvpack_taskLogVerbosity: Detailed
ob_createvpack_verbose: true
ob_createvpack_vpackdirectory: '$(JobOutputDirectory)\vpack'
ob_updateOSManifest_gitcheckinConfigPath: '$(Build.SourcesDirectory)\build\config\GitCheckin.json'
# We're skipping the 'fetch' part of the OneBranch rules, but that doesn't mean
# that it doesn't expect to have downloaded a manifest directly to some 'destination'
# folder that it can then update and upload.
# Effectively: it says "destination" but it means "source"
# DH: Don't ask why.
ob_updateOSManifest_destination: $(XES_VPACKMANIFESTDIRECTORY)
ob_updateOSManifest_skipFetch: true
publishArtifacts: false # Handled by OneBranch
jobName: Bundle
branding: ${{ parameters.branding }}
buildConfigurations: ${{ parameters.buildConfigurations }}
buildPlatforms: ${{ parameters.buildPlatforms }}
generateSbom: false # Handled by onebranch
codeSign: ${{ parameters.codeSign }}
afterBuildSteps:
# This directory has to exist, even if we aren't using createvpack, because the Guardian rules demand it.
- pwsh: |-
New-Item "$(JobOutputDirectory)/vpack" -Type Directory
displayName: Make sure the vpack directory exists
- ${{ if parameters.publishVpackToWindows }}:
- pwsh: |-
Copy-Item -Verbose -Path "$(MsixBundlePath)" -Destination (Join-Path "$(JobOutputDirectory)/vpack" 'Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle')
displayName: Stage msixbundle for vpack
- ${{ if eq(parameters.buildConPTY, true) }}:
- template: ./build/pipelines/templates-v2/job-package-conpty.yml@self
parameters:
pool: { type: windows }
variables:
ob_git_checkout: false # This job checks itself out
ob_git_skip_checkout_none: true
ob_outputDirectory: $(JobOutputDirectory)
ob_artifactBaseName: $(JobOutputArtifactName)
publishArtifacts: false # Handled by OneBranch
buildConfigurations: ${{ parameters.buildConfigurations }}
buildPlatforms: ${{ parameters.buildPlatforms }}
generateSbom: false # this is handled by onebranch
codeSign: ${{ parameters.codeSign }}
- ${{ if eq(parameters.buildWPF, true) }}:
- template: ./build/pipelines/templates-v2/job-build-package-wpf.yml@self
parameters:
pool: { type: windows }
variables:
ob_git_checkout: false # This job checks itself out
ob_git_skip_checkout_none: true
ob_outputDirectory: $(JobOutputDirectory)
ob_artifactBaseName: $(JobOutputArtifactName)
publishArtifacts: false # Handled by OneBranch
buildConfigurations: ${{ parameters.buildConfigurations }}
buildPlatforms: ${{ parameters.buildPlatforms }}
generateSbom: false # this is handled by onebranch
codeSign: ${{ parameters.codeSign }}
- stage: Publish
displayName: Publish
dependsOn: [Build, Package]
jobs:
- template: ./build/pipelines/templates-v2/job-publish-symbols.yml@self
parameters:
pool: { type: windows }
includePublicSymbolServer: ${{ parameters.publishSymbolsToPublic }}
symbolPatGoesInTaskInputs: true # onebranch tries to muck with the PAT variable, so we need to change how it get the PAT
symbolExpiryTime: ${{ parameters.symbolExpiryTime }}
variables:
ob_git_checkout: false # This job checks itself out
ob_git_skip_checkout_none: true
ob_outputDirectory: $(Build.ArtifactStagingDirectory)
# Without this, OneBranch will nerf our symbol tasks
ob_symbolsPublishing_enabled: true
- ${{ parameters.extraPublishJobs }}

View File

@@ -0,0 +1,27 @@
parameters:
- name: branding
type: string
variables:
# If we are building a branch called "release-*", change the NuGet suffix
# to "preview". If we don't do that, XES will set the suffix to "release1"
# because it truncates the value after the first period.
# We also want to disable the suffix entirely if we're Release branded while
# on a release branch.
# main is special, however. XES ignores main. Since we never produce actual
# shipping builds from main, we want to force it to have a beta label as
# well.
#
# In effect:
# BRANCH / BRANDING | Release | Preview
# ------------------|----------------------------|-----------------------------
# release-* | 1.12.20220427 | 1.13.20220427-preview
# main | 1.14.20220427-experimental | 1.14.20220427-experimental
# all others | 1.14.20220427-mybranch | 1.14.20220427-mybranch
${{ if startsWith(variables['Build.SourceBranchName'], 'release-') }}:
${{ if eq(parameters.branding, 'Release') }}:
NoNuGetPackBetaVersion: true
${{ else }}:
NuGetPackBetaVersion: preview
${{ elseif eq(variables['Build.SourceBranchName'], 'main') }}:
NuGetPackBetaVersion: experimental

View File

@@ -0,0 +1,2 @@
variables:
WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:latest'

View File

@@ -0,0 +1,42 @@
[CmdletBinding()]
Param(
[Parameter(Mandatory,
HelpMessage="Path to the .msixbundle")]
[string]
$BundlePath,
[Parameter(Mandatory,
HelpMessage="Path to the .appinstaller template")]
[string]
$AppInstallerTemplatePath,
[string]
$AppInstallerRoot,
[Parameter(Mandatory,
HelpMessage="Output Path")]
[string]
$OutputPath
)
$ErrorActionPreference = "Stop"
$sentinelFile = New-TemporaryFile
$directory = New-Item -Type Directory "$($sentinelFile.FullName)_Package"
Remove-Item $sentinelFile -Force -EA:Ignore
$bundle = (Get-Item $BundlePath)
& tar.exe -x -f $bundle.FullName -C $directory AppxMetadata/AppxBundleManifest.xml
$xml = [xml](Get-Content (Join-Path $directory "AppxMetadata\AppxBundleManifest.xml"))
$name = $xml.Bundle.Identity.Name
$version = $xml.Bundle.Identity.Version
$doc = (Get-Content -ReadCount 0 $AppInstallerTemplatePath)
$doc = $doc -Replace '\$\$ROOT\$\$',$AppInstallerRoot
$doc = $doc -Replace '\$\$NAME\$\$',$name
$doc = $doc -Replace '\$\$VERSION\$\$',$version
$doc = $doc -Replace '\$\$PACKAGE\$\$',$bundle.Name
$doc | Out-File -Encoding utf8NoBOM $OutputPath
Get-Item $OutputPath

View File

@@ -25,7 +25,12 @@ Param(
[Parameter(HelpMessage="Path to makeappx.exe", ParameterSetName='Layout')]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\MakeAppx.exe"
$MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\MakeAppx.exe",
[Parameter(HelpMessage="Include the portable mode marker file by default", ParameterSetName='AppX')]
[Parameter(HelpMessage="Include the portable mode marker file by default", ParameterSetName='Layout')]
[switch]
$PortableMode = $PSCmdlet.ParameterSetName -eq 'Layout'
)
$filesToRemove = @("*.xml", "*.winmd", "Appx*", "Images/*Tile*", "Images/*Logo*") # Remove from Terminal
@@ -128,6 +133,11 @@ $finalTerminalPriFile = Join-Path $terminalAppPath "resources.pri"
# Packaging
########
$portableModeMarkerFile = Join-Path $terminalAppPath ".portable"
If ($PortableMode) {
"" | Out-File $portableModeMarkerFile
}
If ($PSCmdlet.ParameterSetName -Eq "AppX") {
# We only produce a ZIP when we're combining two AppX directories.
New-Item -ItemType Directory -Path $Destination -ErrorAction:SilentlyContinue | Out-Null

View File

@@ -5,7 +5,7 @@
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
<XesBaseYearForStoreVersion>2023</XesBaseYearForStoreVersion>
<VersionMajor>1</VersionMajor>
<VersionMinor>19</VersionMinor>
<VersionMinor>20</VersionMinor>
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
</PropertyGroup>
</Project>

View File

@@ -9,7 +9,7 @@
<package id="Microsoft.VisualStudio.Setup.Configuration.Native" version="2.3.2262" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.UI.Xaml" version="2.8.4" targetFramework="native" />
<package id="Microsoft.Web.WebView2" version="1.0.1661.34" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.220201.1" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.230824.2" targetFramework="native" developmentDependency="true" />
<!-- Managed packages -->
<package id="Appium.WebDriver" version="3.0.0.2" targetFramework="net45" />

View File

@@ -5,10 +5,10 @@
`.../console/published/wincon.w` in the OS repo when you submit the PR.
The branch won't build without it.
* For now, you can update winconp.h with your consumable changes.
* Define registry name (ex `CONSOLE_REGISTRY_CURSORCOLOR`)
* Add the setting to `CONSOLE_STATE_INFO`
* Define registry name (ex: `CONSOLE_REGISTRY_CURSORCOLOR`)
* Add the setting to `CONSOLE_STATE_INFO`.
* Define the property key ID and the property key itself.
- Yes, the large majority of the `DEFINE_PROPERTYKEY` defs are the same, it's only the last byte of the guid that changes
- Yes, the large majority of the `DEFINE_PROPERTYKEY` defs are the same, it's only the last byte of the guid that changes.
2. Add matching fields to Settings.hpp
- Add getters, setters, the whole drill.
@@ -17,9 +17,9 @@
- We need to add it to *reading and writing* the registry from the propsheet, and *reading* the link from the propsheet. Yes, that's weird, but the propsheet is smart enough to re-use ShortcutSerialization::s_SetLinkValues, but not smart enough to do the same with RegistrySerialization.
- `src/propsheet/registry.cpp`
- `propsheet/registry.cpp@InitRegistryValues` should initialize the default value for the property.
- `propsheet/registry.cpp@GetRegistryValues` should make sure to read the property from the registry
- `propsheet/registry.cpp@GetRegistryValues` should make sure to read the property from the registry.
4. Add the field to the propslib registry map
4. Add the field to the propslib registry map.
5. Add the value to `ShortcutSerialization.cpp`
- Read the value in `ShortcutSerialization::s_PopulateV2Properties`
@@ -30,11 +30,11 @@ Now, your new setting should be stored just like all the other properties.
7. Update the feature test properties to get add the setting as well
- `ft_uia/Common/NativeMethods.cs@WinConP`:
- `Wtypes.PROPERTYKEY PKEY_Console_`
- `NT_CONSOLE_PROPS`
- `Wtypes.PROPERTYKEY PKEY_Console_`.
- `NT_CONSOLE_PROPS`.
8. Add the default value for the setting to `win32k-settings.man`
- If the setting shouldn't default to 0 or `nullptr`, then you'll need to set the default value of the setting in `win32k-settings.man`.
9. Update `Settings::InitFromStateInfo` and `Settings::CreateConsoleStateInfo` to get/set the value in a CONSOLE_STATE_INFO appropriately
9. Update `Settings::InitFromStateInfo` and `Settings::CreateConsoleStateInfo` to get/set the value in a CONSOLE_STATE_INFO appropriately.

96
doc/COOKED_READ_DATA.md Normal file
View File

@@ -0,0 +1,96 @@
# COOKED_READ_DATA, aka conhost's readline implementation
## Test instructions
All of the following ✅ marks must be fulfilled during manual testing:
* ASCII input
* Chinese input (中文維基百科) ❔
* Resizing the window properly wraps/unwraps wide glyphs ❌
Broken due to `TextBuffer::Reflow` bugs
* Surrogate pair input (🙂) ❔
* Resizing the window properly wraps/unwraps surrogate pairs ❌
Broken due to `TextBuffer::Reflow` bugs
* In cmd.exe
* Create 2 file: "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 ✅
* Minimum size of 40x10 characters ✅
* Width expands to fit the widest history command ✅
* Height expands up to 20 rows with longer histories ✅
* F9 starts "command number" prompt ✅
* Left/Right paste 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 ✅
* Wide text rendering during pagination with >20 entries ✅
* Shift+Up/Down moves history items around ✅
* Home navigates to first entry ✅
* End navigates to last entry ✅
* PageUp navigates by 20 items at a time or to first ✅
* PageDown navigates by 20 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 ✅

View File

@@ -27,6 +27,8 @@ I would highly recommend that Gulp convert to using PowerShell scripts and that
Original Source: https://github.com/microsoft/terminal/issues/217#issuecomment-404240443
_Addendum_: cmd.exe is the literal embodiment of [xkcd#1172]([url](https://xkcd.com/1172/)). Every change, no matter how small, will break _someone_.
## <a name="screenPerf"></a>Why is typing-to-screen performance better than every other app?
I really do not mind when someone comes by and decides to tell us that we're doing a good job at something. We hear so many complaints every day that a post like this is a breath of fresh air. Thanks for your thanks!
@@ -49,7 +51,7 @@ Will this UI enhancement come to other apps on Windows? Almost certainly not. Th
Will we try to keep it from regressing? Yes! Right now it's sort of a manual process. We identify that something is getting slow and then we go haul out [WPR](https://docs.microsoft.com/en-us/windows-hardware/test/wpt/windows-performance-recorder) and start taking traces. We stare down the hot paths and try to reason out what is going on and then improve them. For instance, in the last cycle or two, we focused on heap allocations as a major area where we could improve our end-to-end performance, changing a ton of our code to use stack-constructed iterator-like facades over the underlying request buffer instead of translating and allocating it into a new heap space for each level of processing.
As an aside, @bitcrazed wants us to automate performance tests in some conhost specific way, but I haven't quite figured out a controlled environment to do this in yet. The Windows Engineering System runs performance tests each night that give us a coarse grained way of knowing if we messed something up for the whole operating system, and they technically offer a fine grained way for us to insert our own performance tests... but I just haven't got around to that yet. If you have an idea for a way for us to do this in an automated fashion, I'm all ears.
As an aside, @bitcrazed wants us to automate performance tests in some conhost specific way, but I haven't quite figured out a controlled environment to do this in yet. The Windows Engineering System runs performance tests each night that give us a coarse-grained way of knowing if we messed something up for the whole operating system, and they technically offer a fine-grained way for us to insert our own performance tests... but I just haven't got around to that yet. If you have an idea for a way for us to do this in an automated fashion, I'm all ears.
If there's anything else you'd like to know, let me know. I could go on all day. I deleted like 15 tangents from this reply before posting it....

View File

@@ -32,7 +32,6 @@
* `/src/cascadia/TerminalApp` - This DLL represents the implementation of the Windows Terminal application. This includes parsing settings, hosting tabs & panes with Terminals in them, and displaying other UI elements. This DLL is almost entirely UWP-like code, and shouldn't be doing any Win32-like UI work.
* `/src/cascadia/WindowsTerminal` - This EXE provides Win32 hosting for the TerminalApp. It will set up XAML islands, and is responsible for drawing the window, either as a standard window or with content in the titlebar (non-client area).
* `/src/cascadia/CascadiaPackage` - This is a project for packaging the Windows Terminal and its dependencies into an .appx/.msix for deploying to the machine.
* `/src/cascadia/PublicTerminalCore` - This is a DLL wrapper for the TerminalCore and Renderer, similar to `TermControl`, which exposes some exported functions that so the Terminal can be used from C#.
* `/src/cascadia/WpfTerminalControl` - A DLL implementing a WPF version of the Terminal Control.
* `/src/host` The meat of the windows console host. This includes buffer, input, output, windowing, server management, clipboard, and most interactions with the console host window that arent stated anywhere else. Were trying to pull things out that are reusable into other libraries, but its a work in progress
* `/src/host/lib` Builds the reusable LIB copy of the host
@@ -126,8 +125,6 @@
* Private calls into the Windows Window Manager to perform privileged actions related to the console process (working to eliminate) or for High DPI stuff (also working to eliminate)
* `Userprivapi.cpp`
* `Windowdpiapi.cpp`
* New UTF8 state machine in progress to improve Bash (and other apps) support for UTF-8 in console
* `Utf8ToWideCharParser.cpp`
* Window resizing/layout/management/window messaging loops and all that other stuff that has us interact with Windows to create a visual display surface and control the user interaction entry point
* `Window.cpp`
* `Windowproc.cpp`

View File

@@ -86,12 +86,19 @@
]
},
"BuiltinSuggestionSource": {
"enum": [
"commandHistory",
"tasks",
"all"
],
"type": "string"
"type": "string",
"anyOf": [
{
"type": "string"
},
{
"enum": [
"commandHistory",
"tasks",
"all"
]
}
]
},
"SuggestionSource": {
"default": "all",
@@ -99,15 +106,17 @@
"$comment": "`tasks` and `local` are sources that would be added by the Tasks feature, as a follow-up",
"oneOf": [
{
"type": [ "string", "null", "BuiltinSuggestionSource" ]
"type": "null"
},
{
"$ref": "#/$defs/BuiltinSuggestionSource"
},
{
"type": "array",
"items": { "type": "BuiltinSuggestionSource" }
},
{
"type": "array",
"items": { "type": "string" }
"items": {
"$ref": "#/$defs/BuiltinSuggestionSource"
},
"uniqueItems": true
}
]
},
@@ -201,10 +210,6 @@
"desktopWallpaper"
]
}
],
"type": [
"string",
"null"
]
},
"backgroundImageOpacity": {
@@ -269,6 +274,17 @@
"experimental.pixelShaderPath": {
"description": "Use to set a path to a pixel shader to use with the Terminal when unfocused. Overrides `experimental.retroTerminalEffect`. This is an experimental feature, and its continued existence is not guaranteed.",
"type": "string"
},
"useAcrylic": {
"description": "When set to true, the window will have an acrylic material background when unfocused. When set to false, the window will have a plain, untextured background when unfocused.",
"type": "boolean"
},
"opacity": {
"default": 100,
"description": "Sets the opacity of the window for the profile when unfocused. Accepts values from 0-100.",
"maximum": 100,
"minimum": 0,
"type": "number"
}
},
"type": "object"
@@ -374,8 +390,12 @@
},
"ShortcutActionName": {
"enum": [
"addMark",
"adjustFontSize",
"adjustOpacity",
"clearAllMarks",
"clearBuffer",
"clearMark",
"closeOtherPanes",
"closeOtherTabs",
"closePane",
@@ -386,6 +406,7 @@
"copy",
"duplicateTab",
"expandSelectionToWord",
"experimental.colorSelection",
"exportBuffer",
"find",
"findMatch",
@@ -393,64 +414,60 @@
"globalSummon",
"identifyWindow",
"identifyWindows",
"markMode",
"moveFocus",
"movePane",
"swapPane",
"markMode",
"moveTab",
"multipleActions",
"newTab",
"newWindow",
"nextTab",
"openAbout",
"openNewTabDropdown",
"openSettings",
"openSystemMenu",
"openTabColorPicker",
"openTabRenamer",
"openWindowRenamer",
"paste",
"prevTab",
"renameTab",
"openSystemMenu",
"openTabRenamer",
"quakeMode",
"quit",
"renameTab",
"renameWindow",
"resetFontSize",
"resizePane",
"renameWindow",
"restoreLastClosed",
"scrollDown",
"scrollDownPage",
"scrollToBottom",
"scrollToMark",
"scrollToTop",
"scrollUp",
"scrollUpPage",
"scrollToBottom",
"scrollToTop",
"searchWeb",
"selectAll",
"sendInput",
"setColorScheme",
"setFocusMode",
"setFullScreen",
"setMaximized",
"setTabColor",
"showSuggestions",
"splitPane",
"swapPane",
"switchSelectionEndpoint",
"switchToTab",
"tabSearch",
"toggleAlwaysOnTop",
"toggleBlockSelection",
"toggleFocusMode",
"selectAll",
"setFocusMode",
"switchSelectionEndpoint",
"toggleFullscreen",
"setFullScreen",
"setMaximized",
"togglePaneZoom",
"toggleSplitOrientation",
"toggleReadOnlyMode",
"toggleShaderEffects",
"toggleSplitOrientation",
"wt",
"quit",
"adjustOpacity",
"restoreLastClosed",
"addMark",
"scrollToMark",
"clearMark",
"clearAllMarks",
"searchWeb",
"experimental.colorSelection",
"unbound"
],
"type": "string"
@@ -640,6 +657,7 @@
"$ref": "#/$defs/NewTabMenuEntry"
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
@@ -668,7 +686,7 @@
},
"allowEmpty": {
"description": "Whether to render a folder without entries, or to hide it",
"default": "false",
"default": false,
"type": "boolean"
}
}
@@ -682,6 +700,7 @@
"$ref": "#/$defs/NewTabMenuEntry"
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
@@ -698,6 +717,7 @@
"$ref": "#/$defs/NewTabMenuEntry"
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
@@ -719,6 +739,7 @@
"$ref": "#/$defs/NewTabMenuEntry"
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
@@ -735,6 +756,7 @@
"$ref": "#/$defs/NewTabMenuEntry"
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
@@ -775,6 +797,7 @@
]
},
"ShortcutAction": {
"type": "object",
"properties": {
"action": {
"description": "The action to execute",
@@ -783,8 +806,7 @@
},
"required": [
"action"
],
"type": "object"
]
},
"AdjustFontSizeAction": {
"description": "Arguments corresponding to an Adjust Font Size Action",
@@ -793,6 +815,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -817,6 +840,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -858,6 +882,7 @@
"$ref": "#/$defs/NewTerminalArgs"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -874,6 +899,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -898,6 +924,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -922,6 +949,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -946,6 +974,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -970,6 +999,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -994,6 +1024,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1018,6 +1049,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1045,6 +1077,7 @@
"$ref": "#/$defs/NewTerminalArgs"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1077,6 +1110,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1114,6 +1148,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1141,6 +1176,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1162,6 +1198,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1183,6 +1220,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1207,6 +1245,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1227,6 +1266,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1247,6 +1287,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1267,6 +1308,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1291,6 +1333,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1319,6 +1362,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1347,6 +1391,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1375,6 +1420,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1399,6 +1445,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1423,6 +1470,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1446,6 +1494,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1471,6 +1520,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1492,6 +1542,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1519,6 +1570,7 @@
"$ref": "#/$defs/NewTerminalArgs"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1535,6 +1587,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1556,6 +1609,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1577,6 +1631,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1598,6 +1653,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1619,6 +1675,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1641,6 +1698,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1662,6 +1720,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1683,6 +1742,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1734,6 +1794,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1750,6 +1811,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1773,6 +1835,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1801,6 +1864,7 @@
"$ref": "#/$defs/ShortcutAction"
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
@@ -1887,7 +1951,11 @@
"properties": {
"applicationTheme": {
"description": "Which UI theme the Terminal should use for controls",
"enum": [ "light", "dark", "system" ],
"enum": [
"light",
"dark",
"system"
],
"type": "string"
},
"useMica": {
@@ -1918,7 +1986,11 @@
"type": "string",
"description": "The name of the theme. This will be displayed in the settings UI.",
"not": {
"enum": [ "light", "dark", "system" ]
"enum": [
"light",
"dark",
"system"
]
}
},
"tab": {
@@ -1935,6 +2007,7 @@
"ThemePair": {
"additionalProperties": false,
"description": "A pair of Theme names, to allow the Terminal to switch theme based on the OS theme",
"type": "object",
"properties": {
"light": {
"type": "string",
@@ -2116,16 +2189,16 @@
},
"name": {
"description": "The name that will appear in the command palette. If one isn't provided, the terminal will attempt to automatically generate a name.\nIf name is a string, it will be the name of the command.\nIf name is a object, the key property of the object will be used to lookup a localized string resource for the command",
"properties": {
"key": {
"type": "string"
}
},
"type": [
"string",
"object",
"null"
]
],
"properties": {
"key": {
"type": "string"
}
}
},
"iterateOn": {
"type": "string",
@@ -2162,6 +2235,7 @@
"Globals": {
"additionalProperties": true,
"description": "Properties that affect the entire window, regardless of the profile settings.",
"type": "object",
"properties": {
"alwaysOnTop": {
"default": false,
@@ -2173,6 +2247,11 @@
"description": "When set to true, tabs are always displayed. When set to false and \"showTabsInTitlebar\" is set to false, tabs only appear after opening a new tab.",
"type": "boolean"
},
"compatibility.enableUnfocusedAcrylic": {
"default": true,
"description": "When set to true, unfocused windows can have acrylic instead of opaque.",
"type": "boolean"
},
"centerOnLaunch": {
"default": false,
"description": "When set to `true`, the terminal window will auto-center itself on the display it opens on. The terminal will use the \"initialPosition\" to determine which display to open on.",
@@ -2270,11 +2349,6 @@
"description": "When set to true, the background image for the currently focused profile is expanded to encompass the entire window, beneath other panes.",
"type": "boolean"
},
"compatibility.reloadEnvironmentVariables": {
"default": true,
"description": "When set to true, when opening a new tab or pane it will get reloaded environment variables.",
"type": "boolean"
},
"initialCols": {
"default": 120,
"description": "The number of columns displayed in the window upon first load. If \"launchMode\" is set to \"maximized\" (or \"maximizedFocus\"), this property is ignored.",
@@ -2376,10 +2450,17 @@
"theme": {
"default": "dark",
"description": "Sets the theme of the application. This value should be the name of one of the themes defined in `themes`. The Terminal also includes the themes `dark`, `light`, and `system`.",
"oneOf": [
"anyOf": [
{
"type": "string"
},
{
"enum": [
"dark",
"light",
"system"
]
},
{
"$ref": "#/$defs/ThemePair"
}
@@ -2489,12 +2570,12 @@
},
"required": [
"defaultProfile"
],
"type": "object"
]
},
"Profile": {
"description": "Properties specific to a unique profile.",
"additionalProperties": false,
"type": "object",
"properties": {
"acrylicOpacity": {
"default": 0.5,
@@ -2523,6 +2604,11 @@
"null"
]
},
"compatibility.reloadEnvironmentVariables": {
"default": true,
"description": "When set to true, when opening a new tab or pane it will get reloaded environment variables.",
"type": "boolean"
},
"unfocusedAppearance": {
"$ref": "#/$defs/AppearanceConfig",
"description": "Sets the appearance of the terminal when it is unfocused.",
@@ -2541,7 +2627,7 @@
},
"backgroundImage": {
"description": "Sets the file location of the image to draw over the window background.",
"oneOf": [
"anyOf": [
{
"type": [
"string",
@@ -2553,10 +2639,6 @@
"desktopWallpaper"
]
}
],
"type": [
"string",
"null"
]
},
"backgroundImageAlignment": {
@@ -2893,8 +2975,7 @@
"description": "When set to true, the window will have an acrylic material background. When set to false, the window will have a plain, untextured background.",
"type": "boolean"
}
},
"type": "object"
}
},
"ProfileList": {
"description": "A list of profiles and the properties specific to each.",
@@ -2909,6 +2990,7 @@
},
"ProfilesObject": {
"description": "A list of profiles and default settings that apply to all of them",
"type": "object",
"properties": {
"list": {
"$ref": "#/$defs/ProfileList"
@@ -2917,12 +2999,12 @@
"description": "The default settings that apply to every profile.",
"$ref": "#/$defs/Profile"
}
},
"type": "object"
}
},
"SchemeList": {
"description": "Properties are specific to each color scheme. ColorTool is a great tool you can use to create and explore new color schemes. All colors use hex color format.",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
@@ -3011,8 +3093,7 @@
"$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI yellow."
}
},
"type": "object"
}
},
"type": "array"
}
@@ -3022,6 +3103,7 @@
"$ref": "#/$defs/Globals"
},
{
"type": "object",
"additionalItems": true,
"properties": {
"profiles": {

View File

@@ -1,5 +1,9 @@
# Terminal 2022 Roadmap
> **NOTE**
>
> This document has been superseded by the [Terminal 2023 Roadmap]. Please refer to that document for the updated roadmap.
## Overview
This document outlines the roadmap of features we're planning for the Windows Terminal during 2022. This serves as a successor to the [Terminal v2 Roadmap], to reflect changes to our planning going forward.
@@ -111,7 +115,7 @@ Incoming issues/asks/etc. are triaged several times a week, labeled appropriatel
[Up Next]: https://github.com/microsoft/terminal/milestone/37
[Backlog]: https://github.com/microsoft/terminal/milestone/45
[Terminal v2 Roadmap]: https://github.com/microsoft/terminal/tree/main/doc/terminal-v2-roadmap.md
[Terminal v2 Roadmap]: ./terminal-v2-roadmap.md
[Windows Terminal Preview 1.2 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-2-release/
[Windows Terminal Preview 1.3 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-3-release/
@@ -126,3 +130,5 @@ Incoming issues/asks/etc. are triaged several times a week, labeled appropriatel
[Windows Terminal Preview 1.12 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-12-release/
[Windows Terminal Preview 1.13 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-13-release/
[Windows Terminal Preview 1.14 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-14-release/
[Terminal 2023 Roadmap]: ./roadmap-2023.md

76
doc/roadmap-2023.md Normal file
View File

@@ -0,0 +1,76 @@
# Terminal 2023 Roadmap
## Overview
This document outlines the roadmap of features we're planning for the Windows Terminal during 2023. This serves as a successor to the [2022 Roadmap], to reflect changes to our planning going forward.
## Release cadence
We've settled on a roughly quarterly release cycle - about once every three months. In May we released [Terminal 1.18]. We're targeting 1.19 for sometime in late September, and 1.20 likely in early January 2024. (These timelines are rough estimates, not strict rules. For example, 1.18's release was pushed back slightly to better align with Build 2023.)
New features will go into [Windows Terminal Preview](https://aka.ms/terminal-preview) first. Typically, one release after they've been in Preview, those features will move into [Windows Terminal](https://aka.ms/terminal) ("Terminal Stable"). In the case of some more risky or experimental features, we might hold them to only Preview builds for an extended period[^1].
| Quarter | Date | Release Version | Preview Release Blog Post |
| --------|------------|---------------- | ------------------------- |
| CY23 Q1 | 2023-01-24 | [Terminal 1.17] | [Windows Terminal Preview 1.17 Release] |
| CY23 Q2 | 2023-05-23 | [Terminal 1.18] | [Windows Terminal Preview 1.18 Release] |
| CY23 Q3 | | [Terminal 1.19] | [Windows Terminal Preview 1.19 Release] |
| CY23 Q4 | | [Terminal 1.20] | [Windows Terminal Preview 1.20 Release] |
Within a single milestone, we typically reserve the last month as "bake time", to polish off bugfixes and get the release ready to ship. In this last month, we'll likely slow down our ingestion of community PRs just to stabilize what's already in `main`. For example, a given release might look like:
```mermaid
gantt
title Proposed Terminal Releases 1.14-1.18
dateFormat YYYY-MM-DD
axisFormat %d %b
section Terminal 1.18
Lock down & bake :l18, 2023-05-09 , 2w
Release 1.18 :milestone, 2023-05-23, 0
1.18 becomes Stable :milestone, after l19, 0
section Terminal 1.19
Features :f19, after l18, 10w
Bugfix :b19, after f19 , 4w
Lock down & bake :l19, after b19 , 2w
Release 1.19 :milestone, after l19, 0
```
_informative, not normative_
## Up next in the Terminal
### Terminal 1.19
* Canary builds. Nightly builds of the Terminal from `main`. More unstable, but quicker access to experimental features.
* Terminal AI. While this will only be shipping in Canary builds to begin with, the v0 implementation will be available roughly at the same time as 1.19.
* The Suggestions UI. This is the starting point for shell completions [#3121], tasks [#1595], and probably Terminal AI at some point too.
* Unicode input for `cmd.exe` (and any other console app using "cooked reads"). See [#15567]
* Miscellaneous performance improvements. Conhost should be a _lot_ faster now.
* Broadcast input mode, for sending text to multiple panes at once.
## Team member "north stars"
For a more fluid take on what each of the team's personal goals are, head on over to [Core team North Stars]. This has a list of more long-term goals that each team member is working towards, but not things that are necessarily committed work.
[^1]: A conclusive list of these features can be found at [../src/features.xml](../src/features.xml). Note that this is a raw XML doc used to light up specific parts of the codebase, and not something authored for human consumption.
[2022 Roadmap]: ./roadmap-2022.md
[Terminal 1.17]: https://github.com/microsoft/terminal/releases/tag/v1.17.1023
[Terminal 1.18]: https://github.com/microsoft/terminal/releases/tag/v1.18.1462.0
[Windows Terminal Preview 1.17 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-17-release/
[Windows Terminal Preview 1.18 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-18-release/
[@DHowett]: https://github.com/DHowett
[@zadjii-msft]: https://github.com/zadjii-msft
[@lhecker]: https://github.com/lhecker
[@carlos-zamora]: https://github.com/carlos-zamora
[@PankajBhojwani]: https://github.com/PankajBhojwani
[Core team North Stars]: https://github.com/microsoft/terminal/wiki/Core-team-North-Stars
[#1595]: https://github.com/microsoft/terminal/issues/1595
[#3121]: https://github.com/microsoft/terminal/issues/3121
[#15567]: https://github.com/microsoft/terminal/issues/15567

View File

@@ -435,7 +435,7 @@ ultimately deemed it to be out of scope for the initial spec review.
<!-- Footnotes -->
[#2046]: https://github.com/microsoft/terminal/issues/2046
[Command Palette, Addendum 1]: https://github.com/microsoft/terminal/blob/main/doc/specs/%232046%20-%20Unified%20keybindings%20and%20commands%2C%20and%20synthesized%20action%20names.md
[Command Palette, Addendum 1]: ../%232046%20-%20Unified%20keybindings%20and%20commands%2C%20and%20synthesized%20action%20names.md
[#3337]: https://github.com/microsoft/terminal/issues/3337
[#6899]: https://github.com/microsoft/terminal/issues/6899

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 KiB

View File

@@ -0,0 +1,744 @@
---
author: Mike Griese
created on: 2022-08-22
last updated: 2023-08-03
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
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.
![](vscode-shell-suggestions.gif)
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 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.
![](shell-autocomplete-july-2022-000.gif)
A prototype of the recent commands UI, powered by shell integration:
![](command-history-suggestions.gif)
A prototype of the tasks UI, powered by the user's settings:
![](tasks-suggestions.gif)
(admittedly, the `TeachingTip` in that gif is a prototype and was later replaced
with a better version.)
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**").
![An example of the menu mode](3121-suggestion-menu-2023-000.gif)
#### 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
of the Suggestions UI vs. the **palette** version. In the palette version, the
user won't be pressing tab to tab-complete at the shell - the focus is out of
the of terminal and in the Suggestions UI. With the menu version, the focus is
still "in the terminal", and users would expect tab to tab-complete.
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[[1](#footnote-1)]. 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 different 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[[2](#footnote-2)].
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 `commandHistory` source. In that
particular case, the TerminalPage will query the active TermControl for a list
of its 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 its 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 additional property:
* `"useCommandline"`: `bool` (**default**: `true`)
* `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, regardless of what the user has typed.
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`.
The primary use case for `useCommandline: false` was for `"nesting": "source"`.
When filtering a list of ["Tasks...", "Recent commands...", "Recent
directories...", "Docker...", "Git..."], then there's minimal value to start by
filtering to "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.
#### Who owns this menu?
There was some discussion of who should own the suggestions menu. The control
itself? Or the app hosting the control?
A main argument for hosting this UI in the control itself is that any consumer
of the `TermControl` should be able to display the [shell-driven autocompletion]
menu. And they should get the UI from us "for free". Consumers shouldn't need to
reimplement it themselves. 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.
A big argument in favor of having the app layer host the control: Consider an
app like Visual Studio. When they embed the control, they'll want to style the
shell-completions UI in their own way. They already have their own intellisense
menu, and their own UI paradigm.
For now, we'll leave this as something that's owned by the app layer. When we
get around to finalizing the [shell-driven autocompletion] design, we can
iterate on ideas for supporting both consumers that want to use a pre-built
suggestions control, or consumers who want to bring their own.
## Tenets
<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.
The Terminal will have no way to localize suggestions that are provided via
[shell-driven autocompletion]. These are just verbatim strings that the shell
told us to use. We don't consider this to be something to worry about, however.
This is no different than the fact that Terminal cannot localize the `Get-Help`
(or any other) output of PowerShell.
</td></tr>
</table>
## Implementation Plan
This is more of an informative outline, rather than a normative one. Many of the
things from Crawl, Walk, and Run are all already in PRs as of the time of this
spec's review.
### 🐣 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 an 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
* [ ] Expose the _current_ commandline from the `TermControl`
* [ ] Add a `useCommandline` property to `suggestions`, to pre-populate the search with the current commandline.
* [ ] Persist recent commands / directories accordingly
### 🏃‍♂️ 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 ambitious 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. "
}
}
}
]
},
"BuiltinSuggestionSource": {
"enum": [
"commandHistory",
"directoryHistory",
"tasks",
"local",
"all"
],
"type": "string"
},
"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", "BuiltinSuggestionSource" ]
},
{
"type": "array",
"items": { "type": "BuiltinSuggestionSource" }
},
{
"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. We already have a docs page dedicated to this, so
we could start by linking to that page. More notes on this in [Automatic shell
integration](#Automatic-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
#### 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 expose 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:
![TeachingTip with description](https://user-images.githubusercontent.com/18356694/222244568-243a6482-92d9-4c3c-bffc-54ad97f01f69.gif)
Actions in the settings could also accept an optional `description` property, to
specify the string that would be presented in that flyout.
#### Automatic shell integration
A large portion of these features all rely on shell integration being enabled by
the user. However, this is not a trivial thing for the Terminal to do on behalf
of the user. Shell integration relies on changes to the user's shell config. If
the Terminal were to try and configure those itself, we may accidentally destroy
configuration that the user has already set up. Hence why the Terminal can't
just have a "Light up all the bells and whistles" toggle in the Settings UI.
This is a non-trivial problem to solve, so it is being left as a future
consideration, for a later spec. It deserves its own spec to sort out how we
should expose this to users and safely implement it.
#### Pre-filtering the UI & filter by source
> **Note**: _This is a brainstorm I considered while writing this spec. I would
> 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 menu 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 separate 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 is in the "Future considerations" section. I think it is 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 versions 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.
* ...
#### 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 better 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 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.
## Resources
These are some other work streams that have a lot of tie-in to the Suggestions
UI. These are all being spec'd at roughly the same time, so links may not be
fully up to date.
* [Shell integration]
* [Shell-driven autocompletion]
* [Tasks]
### Footnotes
<a name="footnote-1"><a>[1]: We've had discussion in the past ([#7285]) about
possibly creating a more abstract "Live filtering list view" to replace the
Command Palette. We could most certainly use that here too. We've decided to
initially go with a fork for now.
<a name="footnote-2"><a>[2]: Obviously, we're not having a real discussion about
extensions in this doc. This example is solely to show that there's room for
extensions to work with the "source" property in this design. What the final
shape of extensions will be is very much still to be determined.
[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
[#7285]: https://github.com/microsoft/terminal/issues/7285
[#14939]: https://github.com/microsoft/terminal/issues/7285
[#keep]: https://github.com/zadjii/keep
[VsCode Tasks]: ../../../.vscode/tasks.json
<!-- Note: This is its own spec in progress, but for the time being #12862 will do -->
[Tasks]: https://github.com/microsoft/terminal/issues/12862
<!-- Note: This is just a link to the PR that introduced the shell integration spec -->
[shell integration]: https://github.com/microsoft/terminal/pull/14792
<!-- Note: If I ever write a spec for this, go ahead and replace this link -->
[shell-driven autocompletion]: https://github.com/microsoft/terminal/issues/3121

Binary file not shown.

After

Width:  |  Height:  |  Size: 965 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 KiB

View File

@@ -605,4 +605,4 @@ as well as 3 schemes: "Scheme 1", "Scheme 2", and "Scheme 3".
<!-- Footnotes -->
[Command Palette Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%232046%20-%20Command%20Palette.md
[Command Palette Spec]: ./%232046%20-%20Command%20Palette.md

View File

@@ -612,8 +612,8 @@ You could have a profile that layers on an existing profile, with elevated-speci
[#8514]: https://github.com/microsoft/terminal/issues/8514
[#10276]: https://github.com/microsoft/terminal/issues/10276
[Process Model 2.0 Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%235000%20-%20Process%20Model%202.0.md
[Configuration object for profiles]: https://github.com/microsoft/terminal/blob/main/doc/specs/Configuration%20object%20for%20profiles.md
[Session Management Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%234472%20-%20Windows%20Terminal%20Session%20Management.md
[Process Model 2.0 Spec]: ../%235000%20-%20Process%20Model%202.0.md
[Configuration object for profiles]: ../%233062%20-%20Appearance configuration object for profiles.md
[Session Management Spec]: ./%234472%20-%20Windows%20Terminal%20Session%20Management.md
[The Old New Thing: How can I launch an unelevated process from my elevated process, redux]: https://devblogs.microsoft.com/oldnewthing/20190425-00/?p=102443
[Workspace Trust]: https://code.visualstudio.com/docs/editor/workspace-trust

View File

@@ -559,4 +559,4 @@ runtime.
[Tab Tear-out in the community toolkit]: https://github.com/windows-toolkit/Sample-TabView-TearOff
[Quake mode scenarios]: https://github.com/microsoft/terminal/issues/653#issuecomment-661370107
[`ISwapChainPanelNative2::SetSwapChainHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/windows.ui.xaml.media.dxinterop/nf-windows-ui-xaml-media-dxinterop-iswapchainpanelnative2-setswapchainhandle
[Process Model 2.0 Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%235000%20-%20Process%20Model%202.0/%235000%20-%20Process%20Model%202.0.md
[Process Model 2.0 Spec]: ./doc/specs/%235000%20-%20Process%20Model%202.0/%235000%20-%20Process%20Model%202.0.md

View File

@@ -730,7 +730,7 @@ user to differentiate between the two behaviors.
[#5727]: https://github.com/microsoft/terminal/issues/5727
[#9992]: https://github.com/microsoft/terminal/issues/9992
[Process Model 2.0 Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%235000%20-%20Process%20Model%202.0/%235000%20-%20Process%20Model%202.0.md
[Process Model 2.0 Spec]: ../%235000%20-%20Process%20Model%202.0/%235000%20-%20Process%20Model%202.0.md
[Quake 3 sample]: https://youtu.be/ZmR6HQbuHPA?t=27
[`RegisterHotKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerhotkey
[`dev/migrie/f/653-QUAKE-MODE`]: https://github.com/microsoft/terminal/tree/dev/migrie/f/653-QUAKE-MODE

View File

@@ -215,8 +215,8 @@ actions manually.
the tab context menu or the control context menu.
<!-- Footnotes -->
[Command Palette Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%232046%20-%20Command%20Palette.md
[New Tab Menu Customization Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%231571%20-%20New%20Tab%20Menu%20Customization.md
[Command Palette Spec]: ./doc/specs/%232046%20-%20Command%20Palette.md
[New Tab Menu Customization Spec]: ./doc/specs/%231571%20-%20New%20Tab%20Menu%20Customization.md
[#1571]: https://github.com/microsoft/terminal/issues/1571
[#1912]: https://github.com/microsoft/terminal/issues/1912

View File

@@ -290,7 +290,7 @@ though. **I recommend we ignore this for now, and leave this as a follow-up**.
For reference, refer to the following from iTerm2:
![image](https://user-images.githubusercontent.com/2578976/64075757-fa971980-ccee-11e9-9e44-47aaf3bca76c.png)
We don't have a menu bar like on MacOS, but we do have a tab context menu. We
We don't have a menu bar like on macOS, but we do have a tab context menu. We
could add these items as a nested entry under each tab. If we wanted to do this,
we should also make sure to dynamically change the icon of the MenuItem to
reflect the current broadcast state.

View File

@@ -373,7 +373,7 @@ changes, or the active pane in a tab changes:
`TabRowControl` to match.
The `tab.cornerRadius` might be a bit trickier to implement. Currently, there's
not a XAML resource that controls this, nor is this something that's exposed by
no XAML resource that controls this, nor is this something that's exposed by
the TabView control. Fortunately, this is something that's exposed to us
programmatically. We'll need to manually set that value on each `TabViewItem` as
we create new tabs. When we reload settings, we'll need to make sure to come

View File

@@ -142,4 +142,4 @@ Feature Notes:
[#4472]: https://github.com/microsoft/terminal/issues/4472
[#8048]: https://github.com/microsoft/terminal/pull/8048
[Terminal 2022 Roadmap]: https://github.com/microsoft/terminal/tree/main/doc/roadmap-2022.md
[Terminal 2022 Roadmap]: ./roadmap-2022.md

View File

@@ -95,7 +95,7 @@
#define HAVE_AVX512
#endif
#if defined(X86_OR_X64)
#if defined(X86_OR_X64) && !defined(_M_ARM64EC)
/* MSVC compatible compilers (Windows) */
#if defined(_MSC_VER)
/* clang-cl (LLVM 10 from 2020) requires /arch:AVX2 or

View File

@@ -11,7 +11,7 @@
#include "../../types/inc/GlyphWidth.hpp"
#include "../../inc/conattrs.hpp"
static constexpr TextAttribute InvalidTextAttribute{ INVALID_COLOR, INVALID_COLOR };
static constexpr TextAttribute InvalidTextAttribute{ INVALID_COLOR, INVALID_COLOR, INVALID_COLOR };
// Routine Description:
// - This is a fill-mode iterator for one particular wchar. It will repeat forever if fillLimit is 0.

View File

@@ -152,11 +152,15 @@ til::CoordType CharToColumnMapper::GetTrailingColumnAt(ptrdiff_t offset) noexcep
return col;
}
// If given a pointer inside the ROW's text buffer, this function will return the corresponding column.
// This function in particular returns the glyph's first column.
til::CoordType CharToColumnMapper::GetLeadingColumnAt(const wchar_t* str) noexcept
{
return GetLeadingColumnAt(str - _chars);
}
// If given a pointer inside the ROW's text buffer, this function will return the corresponding column.
// This function in particular returns the glyph's last column (this matters for wide glyphs).
til::CoordType CharToColumnMapper::GetTrailingColumnAt(const wchar_t* str) noexcept
{
return GetTrailingColumnAt(str - _chars);
@@ -364,11 +368,16 @@ void ROW::TransferAttributes(const til::small_rle<TextAttribute, uint16_t, 1>& a
void ROW::CopyFrom(const ROW& source)
{
RowCopyTextFromState state{ .source = source };
CopyTextFrom(state);
TransferAttributes(source.Attributes(), _columnCount);
_lineRendition = source._lineRendition;
_wrapForced = source._wrapForced;
RowCopyTextFromState state{
.source = source,
.sourceColumnLimit = source.GetReadableColumnCount(),
};
CopyTextFrom(state);
TransferAttributes(source.Attributes(), _columnCount);
}
// Returns the previous possible cursor position, preceding the given column.
@@ -382,7 +391,17 @@ til::CoordType ROW::NavigateToPrevious(til::CoordType column) const noexcept
// Returns the row width if column is beyond the width of the row.
til::CoordType ROW::NavigateToNext(til::CoordType column) const noexcept
{
return _adjustForward(_clampedColumn(column + 1));
return _adjustForward(_clampedColumnInclusive(column + 1));
}
// Returns the starting column of the glyph at the given column.
// In other words, if you have 3 wide glyphs
// AA BB CC
// 01 23 45 <-- column
// then `AdjustToGlyphStart(3)` returns 2.
til::CoordType ROW::AdjustToGlyphStart(til::CoordType column) const noexcept
{
return _adjustBackward(_clampedColumn(column));
}
// Routine Description:
@@ -719,11 +738,12 @@ try
if (sourceColBeg < sourceColLimit)
{
charOffsets = source._charOffsets.subspan(sourceColBeg, static_cast<size_t>(sourceColLimit) - sourceColBeg + 1);
const auto charsOffset = charOffsets.front() & CharOffsetsMask;
const auto beg = size_t{ charOffsets.front() } & CharOffsetsMask;
const auto end = size_t{ charOffsets.back() } & CharOffsetsMask;
// We _are_ using span. But C++ decided that string_view and span aren't convertible.
// _chars is a std::span for performance and because it refers to raw, shared memory.
#pragma warning(suppress : 26481) // Don't use pointer arithmetic. Use span instead (bounds.1).
chars = { source._chars.data() + charsOffset, source._chars.size() - charsOffset };
chars = { source._chars.data() + beg, end - beg };
}
WriteHelper h{ *this, state.columnBegin, state.columnLimit, chars };
@@ -939,6 +959,16 @@ til::CoordType ROW::MeasureLeft() const noexcept
til::CoordType ROW::MeasureRight() const noexcept
{
if (_wrapForced)
{
auto width = _columnCount;
if (_doubleBytePadded)
{
width--;
}
return width;
}
const auto text = GetText();
const auto beg = text.begin();
const auto end = text.end();

View File

@@ -136,6 +136,7 @@ public:
til::CoordType NavigateToPrevious(til::CoordType column) const noexcept;
til::CoordType NavigateToNext(til::CoordType column) const noexcept;
til::CoordType AdjustToGlyphStart(til::CoordType column) const noexcept;
void ClearCell(til::CoordType column);
OutputCellIterator WriteCells(OutputCellIterator it, til::CoordType columnBegin, std::optional<bool> wrap = std::nullopt, std::optional<til::CoordType> limitRight = std::nullopt);

View File

@@ -7,7 +7,7 @@
// Keeping TextColor compact helps us keeping TextAttribute compact,
// which in turn ensures that our buffer memory usage is low.
static_assert(sizeof(TextAttribute) == 12);
static_assert(sizeof(TextAttribute) == 16);
static_assert(alignof(TextAttribute) == 2);
// Ensure that we can memcpy() and memmove() the struct for performance.
static_assert(std::is_trivially_copyable_v<TextAttribute>);
@@ -156,6 +156,25 @@ uint16_t TextAttribute::GetHyperlinkId() const noexcept
return _hyperlinkId;
}
TextColor TextAttribute::GetUnderlineColor() const noexcept
{
return _underlineColor;
}
// Method description:
// - Retrieves the underline style of the text.
// - If the attribute is not the **current** attribute of the text buffer,
// (eg. reading an attribute from another part of the text buffer, which
// was modified using DECRARA), this might return an invalid style. In this
// case, treat the style as singly underlined.
// Return value:
// - The underline style.
UnderlineStyle TextAttribute::GetUnderlineStyle() const noexcept
{
const auto styleAttr = WI_EnumValue(_attrs & CharacterAttributes::UnderlineStyle);
return static_cast<UnderlineStyle>(styleAttr >> UNDERLINE_STYLE_SHIFT);
}
void TextAttribute::SetForeground(const TextColor foreground) noexcept
{
_foreground = foreground;
@@ -166,6 +185,13 @@ void TextAttribute::SetBackground(const TextColor background) noexcept
_background = background;
}
void TextAttribute::SetUnderlineColor(const TextColor color) noexcept
{
// Index16 colors are not supported for underline colors.
assert(!color.IsIndex16());
_underlineColor = color;
}
void TextAttribute::SetForeground(const COLORREF rgbForeground) noexcept
{
_foreground = TextColor(rgbForeground);
@@ -277,14 +303,12 @@ bool TextAttribute::IsCrossedOut() const noexcept
return WI_IsFlagSet(_attrs, CharacterAttributes::CrossedOut);
}
// Method description:
// - Returns true if the text is underlined with any underline style.
bool TextAttribute::IsUnderlined() const noexcept
{
return WI_IsFlagSet(_attrs, CharacterAttributes::Underlined);
}
bool TextAttribute::IsDoublyUnderlined() const noexcept
{
return WI_IsFlagSet(_attrs, CharacterAttributes::DoublyUnderlined);
const auto style = GetUnderlineStyle();
return (style != UnderlineStyle::NoUnderline);
}
bool TextAttribute::IsOverlined() const noexcept
@@ -332,14 +356,14 @@ void TextAttribute::SetCrossedOut(bool isCrossedOut) noexcept
WI_UpdateFlag(_attrs, CharacterAttributes::CrossedOut, isCrossedOut);
}
void TextAttribute::SetUnderlined(bool isUnderlined) noexcept
// Method description:
// - Sets underline style to singly, doubly, or one of the extended styles.
// Arguments:
// - style - underline style to set.
void TextAttribute::SetUnderlineStyle(const UnderlineStyle style) noexcept
{
WI_UpdateFlag(_attrs, CharacterAttributes::Underlined, isUnderlined);
}
void TextAttribute::SetDoublyUnderlined(bool isDoublyUnderlined) noexcept
{
WI_UpdateFlag(_attrs, CharacterAttributes::DoublyUnderlined, isDoublyUnderlined);
const auto shiftedStyle = WI_EnumValue(style) << UNDERLINE_STYLE_SHIFT;
_attrs = (_attrs & ~CharacterAttributes::UnderlineStyle) | static_cast<CharacterAttributes>(shiftedStyle);
}
void TextAttribute::SetOverlined(bool isOverlined) noexcept
@@ -374,6 +398,11 @@ void TextAttribute::SetDefaultBackground() noexcept
_background = TextColor();
}
void TextAttribute::SetDefaultUnderlineColor() noexcept
{
_underlineColor = TextColor{};
}
// Method description:
// - Resets only the rendition character attributes, which includes everything
// except the Protected attribute.

View File

@@ -27,6 +27,17 @@ Revision History:
#include "WexTestClass.h"
#endif
enum class UnderlineStyle
{
NoUnderline = 0U,
SinglyUnderlined = 1U,
DoublyUnderlined = 2U,
CurlyUnderlined = 3U,
DottedUnderlined = 4U,
DashedUnderlined = 5U,
Max = DashedUnderlined
};
class TextAttribute final
{
public:
@@ -34,7 +45,8 @@ public:
_attrs{ CharacterAttributes::Normal },
_foreground{},
_background{},
_hyperlinkId{ 0 }
_hyperlinkId{ 0 },
_underlineColor{}
{
}
@@ -42,16 +54,28 @@ public:
_attrs{ gsl::narrow_cast<WORD>(wLegacyAttr & USED_META_ATTRS) },
_foreground{ gsl::at(s_legacyForegroundColorMap, wLegacyAttr & FG_ATTRS) },
_background{ gsl::at(s_legacyBackgroundColorMap, (wLegacyAttr & BG_ATTRS) >> 4) },
_hyperlinkId{ 0 }
_hyperlinkId{ 0 },
_underlineColor{}
{
}
constexpr TextAttribute(const COLORREF rgbForeground,
const COLORREF rgbBackground) noexcept :
const COLORREF rgbBackground,
const COLORREF rgbUnderline = INVALID_COLOR) noexcept :
_attrs{ CharacterAttributes::Normal },
_foreground{ rgbForeground },
_background{ rgbBackground },
_hyperlinkId{ 0 }
_hyperlinkId{ 0 },
_underlineColor{ rgbUnderline }
{
}
constexpr TextAttribute(const CharacterAttributes attrs, const TextColor foreground, const TextColor background, const uint16_t hyperlinkId, const TextColor underlineColor) noexcept :
_attrs{ attrs },
_foreground{ foreground },
_background{ background },
_hyperlinkId{ hyperlinkId },
_underlineColor{ underlineColor }
{
}
@@ -87,7 +111,6 @@ public:
bool IsInvisible() const noexcept;
bool IsCrossedOut() const noexcept;
bool IsUnderlined() const noexcept;
bool IsDoublyUnderlined() const noexcept;
bool IsOverlined() const noexcept;
bool IsReverseVideo() const noexcept;
bool IsProtected() const noexcept;
@@ -98,8 +121,7 @@ public:
void SetBlinking(bool isBlinking) noexcept;
void SetInvisible(bool isInvisible) noexcept;
void SetCrossedOut(bool isCrossedOut) noexcept;
void SetUnderlined(bool isUnderlined) noexcept;
void SetDoublyUnderlined(bool isDoublyUnderlined) noexcept;
void SetUnderlineStyle(const UnderlineStyle underlineStyle) noexcept;
void SetOverlined(bool isOverlined) noexcept;
void SetReverseVideo(bool isReversed) noexcept;
void SetProtected(bool isProtected) noexcept;
@@ -118,8 +140,11 @@ public:
TextColor GetForeground() const noexcept;
TextColor GetBackground() const noexcept;
uint16_t GetHyperlinkId() const noexcept;
TextColor GetUnderlineColor() const noexcept;
UnderlineStyle GetUnderlineStyle() const noexcept;
void SetForeground(const TextColor foreground) noexcept;
void SetBackground(const TextColor background) noexcept;
void SetUnderlineColor(const TextColor color) noexcept;
void SetForeground(const COLORREF rgbForeground) noexcept;
void SetBackground(const COLORREF rgbBackground) noexcept;
void SetIndexedForeground(const BYTE fgIndex) noexcept;
@@ -131,6 +156,7 @@ public:
void SetDefaultForeground() noexcept;
void SetDefaultBackground() noexcept;
void SetDefaultUnderlineColor() noexcept;
void SetDefaultRenditionAttributes() noexcept;
bool BackgroundIsDefault() const noexcept;
@@ -147,8 +173,8 @@ public:
// global ^ local == false: the foreground attribute is the visible foreground, so we care about the backgrounds being identical
const auto checkForeground = (inverted != IsReverseVideo());
return !IsAnyGridLineEnabled() && // grid lines have a visual representation
// crossed out, doubly and singly underlined have a visual representation
WI_AreAllFlagsClear(_attrs, CharacterAttributes::CrossedOut | CharacterAttributes::DoublyUnderlined | CharacterAttributes::Underlined) &&
// styled underline and crossed out have a visual representation
!IsUnderlined() && WI_IsFlagClear(_attrs, CharacterAttributes::CrossedOut) &&
// hyperlinks have a visual representation
!IsHyperlink() &&
// all other attributes do not have a visual representation
@@ -175,6 +201,7 @@ private:
uint16_t _hyperlinkId; // sizeof: 2, alignof: 2
TextColor _foreground; // sizeof: 4, alignof: 1
TextColor _background; // sizeof: 4, alignof: 1
TextColor _underlineColor; // sizeof: 4, alignof: 1
#ifdef UNIT_TESTING
friend class TextBufferTests;

View File

@@ -14,16 +14,15 @@ bool Search::ResetIfStale(Microsoft::Console::Render::IRenderData& renderData, c
const auto lastMutationId = textBuffer.GetLastMutationId();
if (_needle == needle &&
_reverse == reverse &&
_caseInsensitive == caseInsensitive &&
_lastMutationId == lastMutationId)
{
_step = reverse ? -1 : 1;
return false;
}
_renderData = &renderData;
_needle = needle;
_reverse = reverse;
_caseInsensitive = caseInsensitive;
_lastMutationId = lastMutationId;
@@ -34,14 +33,40 @@ bool Search::ResetIfStale(Microsoft::Console::Render::IRenderData& renderData, c
return true;
}
void Search::MovePastCurrentSelection()
void Search::MoveToCurrentSelection()
{
if (_renderData->IsSelectionActive())
{
MovePastPoint(_renderData->GetTextBuffer().ScreenToBufferPosition(_renderData->GetSelectionAnchor()));
MoveToPoint(_renderData->GetTextBuffer().ScreenToBufferPosition(_renderData->GetSelectionAnchor()));
}
}
void Search::MoveToPoint(const til::point anchor) noexcept
{
if (_results.empty())
{
return;
}
const auto count = gsl::narrow_cast<ptrdiff_t>(_results.size());
ptrdiff_t index = 0;
if (_step < 0)
{
for (index = count - 1; index >= 0 && til::at(_results, index).start > anchor; --index)
{
}
}
else
{
for (index = 0; index < count && til::at(_results, index).start < anchor; ++index)
{
}
}
_index = (index + count) % count;
}
void Search::MovePastPoint(const til::point anchor) noexcept
{
if (_results.empty())
@@ -50,18 +75,17 @@ void Search::MovePastPoint(const til::point anchor) noexcept
}
const auto count = gsl::narrow_cast<ptrdiff_t>(_results.size());
const auto highestIndex = count - 1;
auto index = _reverse ? highestIndex : 0;
ptrdiff_t index = 0;
if (_reverse)
if (_step < 0)
{
for (; index >= 0 && til::at(_results, index).start >= anchor; --index)
for (index = count - 1; index >= 0 && til::at(_results, index).start >= anchor; --index)
{
}
}
else
{
for (; index <= highestIndex && til::at(_results, index).start <= anchor; ++index)
for (index = 0; index < count && til::at(_results, index).start <= anchor; ++index)
{
}
}
@@ -71,8 +95,10 @@ void Search::MovePastPoint(const til::point anchor) noexcept
void Search::FindNext() noexcept
{
const auto count = gsl::narrow_cast<ptrdiff_t>(_results.size());
_index = (_index + _step + count) % count;
if (const auto count{ gsl::narrow_cast<ptrdiff_t>(_results.size()) })
{
_index = (_index + _step + count) % count;
}
}
const til::point_span* Search::GetCurrent() const noexcept
@@ -85,8 +111,31 @@ const til::point_span* Search::GetCurrent() const noexcept
return nullptr;
}
void Search::HighlightResults() const
{
std::vector<til::inclusive_rect> toSelect;
const auto& textBuffer = _renderData->GetTextBuffer();
for (const auto& r : _results)
{
const auto rbStart = textBuffer.BufferToScreenPosition(r.start);
const auto rbEnd = textBuffer.BufferToScreenPosition(r.end);
til::inclusive_rect re;
re.top = rbStart.y;
re.bottom = rbEnd.y;
re.left = rbStart.x;
re.right = rbEnd.x;
toSelect.emplace_back(re);
}
_renderData->SelectSearchRegions(std::move(toSelect));
}
// Routine Description:
// - Takes the found word and selects it in the screen buffer
bool Search::SelectCurrent() const
{
if (const auto s = GetCurrent())
@@ -100,5 +149,16 @@ bool Search::SelectCurrent() const
return true;
}
_renderData->ClearSelection();
return false;
}
const std::vector<til::point_span>& Search::Results() const noexcept
{
return _results;
}
ptrdiff_t Search::CurrentMatch() const noexcept
{
return _index;
}

View File

@@ -27,18 +27,22 @@ public:
bool ResetIfStale(Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, bool reverse, bool caseInsensitive);
void MovePastCurrentSelection();
void MoveToCurrentSelection();
void MoveToPoint(til::point anchor) noexcept;
void MovePastPoint(til::point anchor) noexcept;
void FindNext() noexcept;
const til::point_span* GetCurrent() const noexcept;
void HighlightResults() const;
bool SelectCurrent() const;
const std::vector<til::point_span>& Results() const noexcept;
ptrdiff_t CurrentMatch() const noexcept;
private:
// _renderData is a pointer so that Search() is constexpr default constructable.
Microsoft::Console::Render::IRenderData* _renderData = nullptr;
std::wstring_view _needle;
bool _reverse = false;
std::wstring _needle;
bool _caseInsensitive = false;
uint64_t _lastMutationId = 0;

View File

@@ -416,6 +416,88 @@ size_t TextBuffer::GraphemePrev(const std::wstring_view& chars, size_t position)
return til::utf16_iterate_prev(chars, position);
}
// Ever wondered how much space a piece of text needs before inserting it? This function will tell you!
// It fundamentally behaves identical to the various ROW functions around `RowWriteState`.
//
// Set `columnLimit` to the amount of space that's available (e.g. `buffer_width - cursor_position.x`)
// and it'll return the amount of characters that fit into this space. The out parameter `columns`
// will contain the amount of columns this piece of text has actually used.
//
// Just like with `RowWriteState` one special case is when not all text fits into the given space:
// In that case, this function always returns exactly `columnLimit`. This distinction is important when "inserting"
// a wide glyph but there's only 1 column left. That 1 remaining column is supposed to be padded with whitespace.
size_t TextBuffer::FitTextIntoColumns(const std::wstring_view& chars, til::CoordType columnLimit, til::CoordType& columns) noexcept
{
columnLimit = std::max(0, columnLimit);
const auto beg = chars.begin();
const auto end = chars.end();
auto it = beg;
const auto asciiEnd = beg + std::min(chars.size(), gsl::narrow_cast<size_t>(columnLimit));
// ASCII fast-path: 1 char always corresponds to 1 column.
for (; it != asciiEnd && *it < 0x80; ++it)
{
}
const auto dist = gsl::narrow_cast<size_t>(it - beg);
auto col = gsl::narrow_cast<til::CoordType>(dist);
if (it == asciiEnd) [[likely]]
{
columns = col;
return dist;
}
// Unicode slow-path where we need to count text and columns separately.
for (;;)
{
auto ptr = &*it;
const auto wch = *ptr;
size_t len = 1;
col++;
// Even in our slow-path we can avoid calling IsGlyphFullWidth if the current character is ASCII.
// It also allows us to skip the surrogate pair decoding at the same time.
if (wch >= 0x80)
{
if (til::is_surrogate(wch))
{
const auto it2 = it + 1;
if (til::is_leading_surrogate(wch) && it2 != end && til::is_trailing_surrogate(*it2))
{
len = 2;
}
else
{
ptr = &UNICODE_REPLACEMENT;
}
}
col += IsGlyphFullWidth({ ptr, len });
}
// If we ran out of columns, we need to always return `columnLimit` and not `cols`,
// because if we tried inserting a wide glyph into just 1 remaining column it will
// fail to fit, but that remaining column still has been used up. When the caller sees
// `columns == columnLimit` they will line-wrap and continue inserting into the next row.
if (col > columnLimit)
{
columns = columnLimit;
return gsl::narrow_cast<size_t>(it - beg);
}
// But if we simply ran out of text we just need to return the actual number of columns.
it += len;
if (it == end)
{
columns = col;
return chars.size();
}
}
}
// Pretend as if `position` is a regular cursor in the TextBuffer.
// This function will then pretend as if you pressed the left/right arrow
// keys `distance` amount of times (negative = left, positive = right).
@@ -806,9 +888,9 @@ void TextBuffer::IncrementCircularBuffer(const TextAttribute& fillAttributes)
// - The viewport
//Return value:
// - Coordinate position (relative to the text buffer)
til::point TextBuffer::GetLastNonSpaceCharacter(std::optional<const Microsoft::Console::Types::Viewport> viewOptional) const
til::point TextBuffer::GetLastNonSpaceCharacter(const Viewport* viewOptional) const
{
const auto viewport = viewOptional.has_value() ? viewOptional.value() : GetSize();
const auto viewport = viewOptional ? *viewOptional : GetSize();
til::point coordEndOfText;
// Search the given viewport by starting at the bottom.
@@ -1070,46 +1152,40 @@ void TextBuffer::Reset() noexcept
// - newSize - new size of screen.
// Return Value:
// - Success if successful. Invalid parameter if screen buffer size is unexpected. No memory if allocation failed.
[[nodiscard]] NTSTATUS TextBuffer::ResizeTraditional(til::size newSize) noexcept
void TextBuffer::ResizeTraditional(til::size newSize)
{
// Guard against resizing the text buffer to 0 columns/rows, which would break being able to insert text.
newSize.width = std::max(newSize.width, 1);
newSize.height = std::max(newSize.height, 1);
try
TextBuffer newBuffer{ newSize, _currentAttributes, 0, false, _renderer };
const auto cursorRow = GetCursor().GetPosition().y;
const auto copyableRows = std::min<til::CoordType>(_height, newSize.height);
til::CoordType srcRow = 0;
til::CoordType dstRow = 0;
if (cursorRow >= newSize.height)
{
TextBuffer newBuffer{ newSize, _currentAttributes, 0, false, _renderer };
const auto cursorRow = GetCursor().GetPosition().y;
const auto copyableRows = std::min<til::CoordType>(_height, newSize.height);
til::CoordType srcRow = 0;
til::CoordType dstRow = 0;
if (cursorRow >= newSize.height)
{
srcRow = cursorRow - newSize.height + 1;
}
for (; dstRow < copyableRows; ++dstRow, ++srcRow)
{
newBuffer.GetMutableRowByOffset(dstRow).CopyFrom(GetRowByOffset(srcRow));
}
// NOTE: Keep this in sync with _reserve().
_buffer = std::move(newBuffer._buffer);
_bufferEnd = newBuffer._bufferEnd;
_commitWatermark = newBuffer._commitWatermark;
_initialAttributes = newBuffer._initialAttributes;
_bufferRowStride = newBuffer._bufferRowStride;
_bufferOffsetChars = newBuffer._bufferOffsetChars;
_bufferOffsetCharOffsets = newBuffer._bufferOffsetCharOffsets;
_width = newBuffer._width;
_height = newBuffer._height;
_SetFirstRowIndex(0);
srcRow = cursorRow - newSize.height + 1;
}
CATCH_RETURN();
return S_OK;
for (; dstRow < copyableRows; ++dstRow, ++srcRow)
{
newBuffer.GetMutableRowByOffset(dstRow).CopyFrom(GetRowByOffset(srcRow));
}
// NOTE: Keep this in sync with _reserve().
_buffer = std::move(newBuffer._buffer);
_bufferEnd = newBuffer._bufferEnd;
_commitWatermark = newBuffer._commitWatermark;
_initialAttributes = newBuffer._initialAttributes;
_bufferRowStride = newBuffer._bufferRowStride;
_bufferOffsetChars = newBuffer._bufferOffsetChars;
_bufferOffsetCharOffsets = newBuffer._bufferOffsetCharOffsets;
_width = newBuffer._width;
_height = newBuffer._height;
_SetFirstRowIndex(0);
}
void TextBuffer::SetAsActiveBuffer(const bool isActiveBuffer) noexcept
@@ -1253,36 +1329,32 @@ til::point TextBuffer::_GetWordStartForAccessibility(const til::point target, co
{
auto result = target;
const auto bufferSize = GetSize();
auto stayAtOrigin = false;
// ignore left boundary. Continue until readable text found
while (_GetDelimiterClassAt(result, wordDelimiters) != DelimiterClass::RegularChar)
{
if (!bufferSize.DecrementInBounds(result))
if (result == bufferSize.Origin())
{
// first char in buffer is a DelimiterChar or ControlChar
// we can't move any further back
stayAtOrigin = true;
break;
//looped around and hit origin (no word between origin and target)
return result;
}
bufferSize.DecrementInBounds(result);
}
// make sure we expand to the left boundary or the beginning of the word
while (_GetDelimiterClassAt(result, wordDelimiters) == DelimiterClass::RegularChar)
{
if (!bufferSize.DecrementInBounds(result))
if (result == bufferSize.Origin())
{
// first char in buffer is a RegularChar
// we can't move any further back
break;
return result;
}
bufferSize.DecrementInBounds(result);
}
// move off of delimiter and onto word start
if (!stayAtOrigin && _GetDelimiterClassAt(result, wordDelimiters) != DelimiterClass::RegularChar)
{
bufferSize.IncrementInBounds(result);
}
// move off of delimiter
bufferSize.IncrementInBounds(result);
return result;
}
@@ -1300,10 +1372,16 @@ til::point TextBuffer::_GetWordStartForSelection(const til::point target, const
const auto bufferSize = GetSize();
const auto initialDelimiter = _GetDelimiterClassAt(result, wordDelimiters);
const bool isControlChar = initialDelimiter == DelimiterClass::ControlChar;
// expand left until we hit the left boundary or a different delimiter class
while (result.x > bufferSize.Left() && (_GetDelimiterClassAt(result, wordDelimiters) == initialDelimiter))
while (result != bufferSize.Origin() && _GetDelimiterClassAt(result, wordDelimiters) == initialDelimiter)
{
//prevent selection wrapping on whitespace selection
if (isControlChar && result.x == bufferSize.Left())
{
break;
}
bufferSize.DecrementInBounds(result);
}
@@ -1381,25 +1459,21 @@ til::point TextBuffer::_GetWordEndForAccessibility(const til::point target, cons
}
else
{
auto iter{ GetCellDataAt(result, bufferSize) };
while (iter && iter.Pos() != limit && _GetDelimiterClassAt(iter.Pos(), wordDelimiters) == DelimiterClass::RegularChar)
while (result != limit && result != bufferSize.BottomRightInclusive() && _GetDelimiterClassAt(result, wordDelimiters) == DelimiterClass::RegularChar)
{
// Iterate through readable text
++iter;
bufferSize.IncrementInBounds(result);
}
while (iter && iter.Pos() != limit && _GetDelimiterClassAt(iter.Pos(), wordDelimiters) != DelimiterClass::RegularChar)
while (result != limit && result != bufferSize.BottomRightInclusive() && _GetDelimiterClassAt(result, wordDelimiters) != DelimiterClass::RegularChar)
{
// expand to the beginning of the NEXT word
++iter;
bufferSize.IncrementInBounds(result);
}
result = iter.Pos();
// Special case: we tried to move one past the end of the buffer,
// but iter prevented that (because that pos doesn't exist).
// Special case: we tried to move one past the end of the buffer
// Manually increment onto the EndExclusive point.
if (!iter)
if (result == bufferSize.BottomRightInclusive())
{
bufferSize.IncrementInBounds(result, true);
}
@@ -1419,19 +1493,18 @@ til::point TextBuffer::_GetWordEndForSelection(const til::point target, const st
{
const auto bufferSize = GetSize();
// can't expand right
if (target.x == bufferSize.RightInclusive())
{
return target;
}
auto result = target;
const auto initialDelimiter = _GetDelimiterClassAt(result, wordDelimiters);
const bool isControlChar = initialDelimiter == DelimiterClass::ControlChar;
// expand right until we hit the right boundary or a different delimiter class
while (result.x < bufferSize.RightInclusive() && (_GetDelimiterClassAt(result, wordDelimiters) == initialDelimiter))
// expand right until we hit the right boundary as a ControlChar or a different delimiter class
while (result != bufferSize.BottomRightInclusive() && _GetDelimiterClassAt(result, wordDelimiters) == initialDelimiter)
{
bufferSize.IncrementInBounds(result);
if (isControlChar && result.x == bufferSize.RightInclusive())
{
break;
}
bufferSize.IncrementInBoundsCircular(result);
}
if (_GetDelimiterClassAt(result, wordDelimiters) != initialDelimiter)
@@ -2201,6 +2274,7 @@ std::string TextBuffer::GenHTML(const TextAndColor& rows,
// Routine Description:
// - Generates an RTF document based on the passed in text and color data
// RTF 1.5 Spec: https://www.biblioscape.com/rtf15_spec.htm
// RTF 1.9.1 Spec: https://msopenspecs.azureedge.net/files/Archive_References/[MSFT-RTF].pdf
// Arguments:
// - rows - the text and color data we will format & encapsulate
// - backgroundColor - default background color for characters, also used in padding
@@ -2220,10 +2294,18 @@ std::string TextBuffer::GenRTF(const TextAndColor& rows, const int fontHeightPoi
// Standard RTF header.
// This is similar to the header generated by WordPad.
// \ansi - specifies that the ANSI char set is used in the current doc
// \ansicpg1252 - represents the ANSI code page which is used to perform the Unicode to ANSI conversion when writing RTF text
// \deff0 - specifies that the default font for the document is the one at index 0 in the font table
// \nouicompat - ?
// \ansi:
// Specifies that the ANSI char set is used in the current doc.
// \ansicpg1252:
// Represents the ANSI code page which is used to perform
// the Unicode to ANSI conversion when writing RTF text.
// \deff0:
// Specifies that the default font for the document is the one
// at index 0 in the font table.
// \nouicompat:
// Some features are blocked by default to maintain compatibility
// with older programs (Eg. Word 97-2003). `nouicompat` disables this
// behavior, and unblocks these features. See: Spec 1.9.1, Pg. 51.
rtfBuilder << "\\rtf1\\ansi\\ansicpg1252\\deff0\\nouicompat";
// font table
@@ -2232,17 +2314,25 @@ std::string TextBuffer::GenRTF(const TextAndColor& rows, const int fontHeightPoi
// map to keep track of colors:
// keys are colors represented by COLORREF
// values are indices of the corresponding colors in the color table
std::unordered_map<COLORREF, int> colorMap;
auto nextColorIndex = 1; // leave 0 for the default color and start from 1.
std::unordered_map<COLORREF, size_t> colorMap;
// RTF color table
std::ostringstream colorTableBuilder;
colorTableBuilder << "{\\colortbl ;";
colorTableBuilder << "\\red" << static_cast<int>(GetRValue(backgroundColor))
<< "\\green" << static_cast<int>(GetGValue(backgroundColor))
<< "\\blue" << static_cast<int>(GetBValue(backgroundColor))
<< ";";
colorMap[backgroundColor] = nextColorIndex++;
const auto getColorTableIndex = [&](const COLORREF color) -> size_t {
// Exclude the 0 index for the default color, and start with 1.
const auto [it, inserted] = colorMap.emplace(color, colorMap.size() + 1);
if (inserted)
{
colorTableBuilder << "\\red" << static_cast<int>(GetRValue(color))
<< "\\green" << static_cast<int>(GetGValue(color))
<< "\\blue" << static_cast<int>(GetBValue(color))
<< ";";
}
return it->second;
};
// content
std::ostringstream contentBuilder;
@@ -2252,7 +2342,12 @@ std::string TextBuffer::GenRTF(const TextAndColor& rows, const int fontHeightPoi
// \fs specifies font size in half-points i.e. \fs20 results in a font size
// of 10 pts. That's why, font size is multiplied by 2 here.
contentBuilder << "\\pard\\slmult1\\f0\\fs" << std::to_string(2 * fontHeightPoints)
<< "\\highlight1"
// Set the background color for the page. But, the
// standard way (\cbN) to do this isn't supported in Word.
// However, the following control words sequence works
// in Word (and other RTF editors also) for applying the
// text background color. See: Spec 1.9.1, Pg. 23.
<< "\\chshdng0\\chcbpat" << getColorTableIndex(backgroundColor)
<< " ";
std::optional<COLORREF> fgColor = std::nullopt;
@@ -2302,43 +2397,8 @@ std::string TextBuffer::GenRTF(const TextAndColor& rows, const int fontHeightPoi
if (colorChanged)
{
writeAccumulatedChars(false);
auto bkColorIndex = 0;
if (colorMap.find(bkColor.value()) != colorMap.end())
{
// color already exists in the map, just retrieve the index
bkColorIndex = colorMap[bkColor.value()];
}
else
{
// color not present in the map, so add it
colorTableBuilder << "\\red" << static_cast<int>(GetRValue(bkColor.value()))
<< "\\green" << static_cast<int>(GetGValue(bkColor.value()))
<< "\\blue" << static_cast<int>(GetBValue(bkColor.value()))
<< ";";
colorMap[bkColor.value()] = nextColorIndex;
bkColorIndex = nextColorIndex++;
}
auto fgColorIndex = 0;
if (colorMap.find(fgColor.value()) != colorMap.end())
{
// color already exists in the map, just retrieve the index
fgColorIndex = colorMap[fgColor.value()];
}
else
{
// color not present in the map, so add it
colorTableBuilder << "\\red" << static_cast<int>(GetRValue(fgColor.value()))
<< "\\green" << static_cast<int>(GetGValue(fgColor.value()))
<< "\\blue" << static_cast<int>(GetBValue(fgColor.value()))
<< ";";
colorMap[fgColor.value()] = nextColorIndex;
fgColorIndex = nextColorIndex++;
}
contentBuilder << "\\highlight" << bkColorIndex
<< "\\cf" << fgColorIndex
contentBuilder << "\\chshdng0\\chcbpat" << getColorTableIndex(bkColor.value())
<< "\\cf" << getColorTableIndex(fgColor.value())
<< " ";
}
@@ -2412,204 +2472,181 @@ void TextBuffer::_AppendRTFText(std::ostringstream& contentBuilder, const std::w
// the new buffer. The rows's new value is placed back into this parameter.
// Return Value:
// - S_OK if we successfully copied the contents to the new buffer, otherwise an appropriate HRESULT.
HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer,
TextBuffer& newBuffer,
const std::optional<Viewport> lastCharacterViewport,
std::optional<std::reference_wrapper<PositionInformation>> positionInfo)
try
void TextBuffer::Reflow(TextBuffer& oldBuffer, TextBuffer& newBuffer, const Viewport* lastCharacterViewport, PositionInformation* positionInfo)
{
const auto& oldCursor = oldBuffer.GetCursor();
auto& newCursor = newBuffer.GetCursor();
// We need to save the old cursor position so that we can
// place the new cursor back on the equivalent character in
// the new buffer.
const auto cOldCursorPos = oldCursor.GetPosition();
const auto cOldLastChar = oldBuffer.GetLastNonSpaceCharacter(lastCharacterViewport);
til::point oldCursorPos = oldCursor.GetPosition();
til::point newCursorPos;
const auto cOldRowsTotal = cOldLastChar.y + 1;
// BODGY: We use oldCursorPos in two critical places below:
// * To compute an oldHeight that includes at a minimum the cursor row
// * For REFLOW_JANK_CURSOR_WRAP (see comment below)
// Both of these would break the reflow algorithm, but the latter of the two in particular
// would cause the main copy loop below to deadlock. In other words, these two lines
// protect this function against yet-unknown bugs in other parts of the code base.
oldCursorPos.x = std::clamp(oldCursorPos.x, 0, oldBuffer._width - 1);
oldCursorPos.y = std::clamp(oldCursorPos.y, 0, oldBuffer._height - 1);
til::point cNewCursorPos;
auto fFoundCursorPos = false;
auto foundOldMutable = false;
auto foundOldVisible = false;
// Loop through all the rows of the old buffer and reprint them into the new buffer
til::CoordType iOldRow = 0;
for (; iOldRow < cOldRowsTotal; iOldRow++)
const auto lastRowWithText = oldBuffer.GetLastNonSpaceCharacter(lastCharacterViewport).y;
auto mutableViewportTop = positionInfo ? positionInfo->mutableViewportTop : til::CoordTypeMax;
auto visibleViewportTop = positionInfo ? positionInfo->visibleViewportTop : til::CoordTypeMax;
til::CoordType oldY = 0;
til::CoordType newY = 0;
til::CoordType newX = 0;
til::CoordType newWidth = newBuffer.GetSize().Width();
til::CoordType newYLimit = til::CoordTypeMax;
const auto oldHeight = std::max(lastRowWithText, oldCursorPos.y) + 1;
const auto newHeight = newBuffer.GetSize().Height();
const auto newWidthU16 = gsl::narrow_cast<uint16_t>(newWidth);
// Copy oldBuffer into newBuffer until oldBuffer has been fully consumed.
for (; oldY < oldHeight && newY < newYLimit; ++oldY)
{
// Fetch the row and its "right" which is the last printable character.
const auto& row = oldBuffer.GetRowByOffset(iOldRow);
const auto cOldColsTotal = oldBuffer.GetLineWidth(iOldRow);
auto iRight = row.MeasureRight();
const auto& oldRow = oldBuffer.GetRowByOffset(oldY);
// If we're starting a new row, try and preserve the line rendition
// from the row in the original buffer.
const auto newBufferPos = newCursor.GetPosition();
if (newBufferPos.x == 0)
// A pair of double height rows should optimally wrap as a union (i.e. after wrapping there should be 4 lines).
// But for this initial implementation I chose the alternative approach: Just truncate them.
if (oldRow.GetLineRendition() != LineRendition::SingleWidth)
{
auto& newRow = newBuffer.GetMutableRowByOffset(newBufferPos.y);
newRow.SetLineRendition(row.GetLineRendition());
}
// There is a special case here. If the row has a "wrap"
// flag on it, but the right isn't equal to the width (one
// index past the final valid index in the row) then there
// were a bunch trailing of spaces in the row.
// (But the measuring functions for each row Left/Right do
// not count spaces as "displayable" so they're not
// included.)
// As such, adjust the "right" to be the width of the row
// to capture all these spaces
if (row.WasWrapForced())
{
iRight = cOldColsTotal;
// And a combined special case.
// If we wrapped off the end of the row by adding a
// piece of padding because of a double byte LEADING
// character, then remove one from the "right" to
// leave this padding out of the copy process.
if (row.WasDoubleBytePadded())
// Since rows with a non-standard line rendition should be truncated it's important
// that we pretend as if the previous row ended in a newline, even if it didn't.
// This is what this if does: It newlines.
if (newX)
{
iRight--;
}
}
// Loop through every character in the current row (up to
// the "right" boundary, which is one past the final valid
// character)
til::CoordType iOldCol = 0;
const auto copyRight = iRight;
for (; iOldCol < copyRight; iOldCol++)
{
if (iOldCol == cOldCursorPos.x && iOldRow == cOldCursorPos.y)
{
cNewCursorPos = newCursor.GetPosition();
fFoundCursorPos = true;
newX = 0;
newY++;
}
// TODO: MSFT: 19446208 - this should just use an iterator and the inserter...
const auto glyph = row.GlyphAt(iOldCol);
const auto dbcsAttr = row.DbcsAttrAt(iOldCol);
const auto textAttr = row.GetAttrByColumn(iOldCol);
auto& newRow = newBuffer.GetMutableRowByOffset(newY);
newBuffer.InsertCharacter(glyph, dbcsAttr, textAttr);
}
// GH#32: Copy the attributes from the rest of the row into this new buffer.
// From where we are in the old buffer, to the end of the row, copy the
// remaining attributes.
// - if the old buffer is smaller than the new buffer, then just copy
// what we have, as it was. We already copied all _text_ with colors,
// but it's possible for someone to just put some color into the
// buffer to the right of that without any text (as just spaces). The
// buffer looks weird to the user when we resize and it starts losing
// those colors, so we need to copy them over too... as long as there
// is space. The last attr in the row will be extended to the end of
// the row in the new buffer.
// - if the old buffer is WIDER, than we might have wrapped onto a new
// line. Use the cursor's position's Y so that we know where the new
// row is, and start writing at the cursor position. Again, the attr
// in the last column of the old row will be extended to the end of the
// row that the text was flowed onto.
// - if the text in the old buffer didn't actually fill the whole
// line in the new buffer, then we didn't wrap. That's fine. just
// copy attributes from the old row till the end of the new row, and
// move on.
const auto newRowY = newCursor.GetPosition().y;
auto& newRow = newBuffer.GetMutableRowByOffset(newRowY);
auto newAttrColumn = newCursor.GetPosition().x;
const auto newWidth = newBuffer.GetLineWidth(newRowY);
// Stop when we get to the end of the buffer width, or the new position
// for inserting an attr would be past the right of the new buffer.
for (auto copyAttrCol = iOldCol;
copyAttrCol < cOldColsTotal && newAttrColumn < newWidth;
copyAttrCol++, newAttrColumn++)
{
// TODO: MSFT: 19446208 - this should just use an iterator and the inserter...
const auto textAttr = row.GetAttrByColumn(copyAttrCol);
newRow.SetAttrToEnd(newAttrColumn, textAttr);
}
// If we found the old row that the caller was interested in, set the
// out value of that parameter to the cursor's current Y position (the
// new location of the _end_ of that row in the buffer).
if (positionInfo.has_value())
{
if (!foundOldMutable)
// See the comment marked with "REFLOW_RESET".
if (newY >= newHeight)
{
if (iOldRow >= positionInfo.value().get().mutableViewportTop)
newRow.Reset(newBuffer._initialAttributes);
}
newRow.CopyFrom(oldRow);
newRow.SetWrapForced(false);
if (oldY == oldCursorPos.y)
{
newCursorPos = { newRow.AdjustToGlyphStart(oldCursorPos.x), newY };
}
if (oldY >= mutableViewportTop)
{
positionInfo->mutableViewportTop = newY;
mutableViewportTop = til::CoordTypeMax;
}
if (oldY >= visibleViewportTop)
{
positionInfo->visibleViewportTop = newY;
visibleViewportTop = til::CoordTypeMax;
}
newY++;
continue;
}
// Rows don't store any information for what column the last written character is in.
// We simply truncate all trailing whitespace in this implementation.
auto oldRowLimit = oldRow.MeasureRight();
if (oldY == oldCursorPos.y)
{
// REFLOW_JANK_CURSOR_WRAP:
// Pretending as if there's always at least whitespace in front of the cursor has the benefit that
// * the cursor retains its distance from any preceding text.
// * when a client application starts writing on this new, empty line,
// enlarging the buffer unwraps the text onto the preceding line.
oldRowLimit = std::max(oldRowLimit, oldCursorPos.x + 1);
}
til::CoordType oldX = 0;
// Copy oldRow into newBuffer until oldRow has been fully consumed.
// We use a do-while loop to ensure that line wrapping occurs and
// that attributes are copied over even for seemingly empty rows.
do
{
// This if condition handles line wrapping.
// Only if we write past the last column we should wrap and as such this if
// condition is in front of the text insertion code instead of behind it.
// A SetWrapForced of false implies an explicit newline, which is the default.
if (newX >= newWidth)
{
newBuffer.GetMutableRowByOffset(newY).SetWrapForced(true);
newX = 0;
newY++;
}
// REFLOW_RESET:
// If we shrink the buffer vertically, for instance from 100 rows to 90 rows, we will write 10 rows in the
// new buffer twice. We need to reset them before copying text, or otherwise we'll see the previous contents.
// We don't need to be smart about this. Reset() is fast and shrinking doesn't occur often.
if (newY >= newHeight && newX == 0)
{
// We need to ensure not to overwrite the row the cursor is on.
if (newY >= newYLimit)
{
positionInfo.value().get().mutableViewportTop = newCursor.GetPosition().y;
foundOldMutable = true;
break;
}
newBuffer.GetMutableRowByOffset(newY).Reset(newBuffer._initialAttributes);
}
if (!foundOldVisible)
auto& newRow = newBuffer.GetMutableRowByOffset(newY);
RowCopyTextFromState state{
.source = oldRow,
.columnBegin = newX,
.columnLimit = til::CoordTypeMax,
.sourceColumnBegin = oldX,
.sourceColumnLimit = oldRowLimit,
};
newRow.CopyTextFrom(state);
const auto& oldAttr = oldRow.Attributes();
auto& newAttr = newRow.Attributes();
const auto attributes = oldAttr.slice(gsl::narrow_cast<uint16_t>(oldX), oldAttr.size());
newAttr.replace(gsl::narrow_cast<uint16_t>(newX), newAttr.size(), attributes);
newAttr.resize_trailing_extent(newWidthU16);
if (oldY == oldCursorPos.y && oldCursorPos.x >= oldX)
{
if (iOldRow >= positionInfo.value().get().visibleViewportTop)
{
positionInfo.value().get().visibleViewportTop = newCursor.GetPosition().y;
foundOldVisible = true;
}
// In theory AdjustToGlyphStart ensures we don't put the cursor on a trailing wide glyph.
// In practice I don't think that this can possibly happen. Better safe than sorry.
newCursorPos = { newRow.AdjustToGlyphStart(oldCursorPos.x - oldX + newX), newY };
// If there's so much text past the old cursor position that it doesn't fit into new buffer,
// then the new cursor position will be "lost", because it's overwritten by unrelated text.
// We have two choices how can handle this:
// * If the new cursor is at an y < 0, just put the cursor at (0,0)
// * Stop writing into the new buffer before we overwrite the new cursor position
// This implements the second option. There's no fundamental reason why this is better.
newYLimit = newY + newHeight;
}
if (oldY >= mutableViewportTop)
{
positionInfo->mutableViewportTop = newY;
mutableViewportTop = til::CoordTypeMax;
}
if (oldY >= visibleViewportTop)
{
positionInfo->visibleViewportTop = newY;
visibleViewportTop = til::CoordTypeMax;
}
}
// If we didn't have a full row to copy, insert a new
// line into the new buffer.
// Only do so if we were not forced to wrap. If we did
// force a word wrap, then the existing line break was
// only because we ran out of space.
if (iRight < cOldColsTotal && !row.WasWrapForced())
oldX = state.sourceColumnEnd;
newX = state.columnEnd;
} while (oldX < oldRowLimit);
// If the row had an explicit newline we also need to newline. :)
if (!oldRow.WasWrapForced())
{
if (!fFoundCursorPos && (iRight == cOldCursorPos.x && iOldRow == cOldCursorPos.y))
{
cNewCursorPos = newCursor.GetPosition();
fFoundCursorPos = true;
}
// Only do this if it's not the final line in the buffer.
// On the final line, we want the cursor to sit
// where it is done printing for the cursor
// adjustment to follow.
if (iOldRow < cOldRowsTotal - 1)
{
newBuffer.NewlineCursor();
}
else
{
// If we are on the final line of the buffer, we have one more check.
// We got into this code path because we are at the right most column of a row in the old buffer
// that had a hard return (no wrap was forced).
// However, as we're inserting, the old row might have just barely fit into the new buffer and
// caused a new soft return (wrap was forced) putting the cursor at x=0 on the line just below.
// We need to preserve the memory of the hard return at this point by inserting one additional
// hard newline, otherwise we've lost that information.
// We only do this when the cursor has just barely poured over onto the next line so the hard return
// isn't covered by the soft one.
// e.g.
// The old line was:
// |aaaaaaaaaaaaaaaaaaa | with no wrap which means there was a newline after that final a.
// The cursor was here ^
// And the new line will be:
// |aaaaaaaaaaaaaaaaaaa| and show a wrap at the end
// | |
// ^ and the cursor is now there.
// If we leave it like this, we've lost the newline information.
// So we insert one more newline so a continued reflow of this buffer by resizing larger will
// continue to look as the original output intended with the newline data.
// After this fix, it looks like this:
// |aaaaaaaaaaaaaaaaaaa| no wrap at the end (preserved hard newline)
// | |
// ^ and the cursor is now here.
const auto coordNewCursor = newCursor.GetPosition();
if (coordNewCursor.x == 0 && coordNewCursor.y > 0)
{
if (newBuffer.GetRowByOffset(coordNewCursor.y - 1).WasWrapForced())
{
newBuffer.NewlineCursor();
}
}
}
newX = 0;
newY++;
}
}
@@ -2617,85 +2654,40 @@ try
// printable character. This is to fix the `color 2f` scenario, where you
// change the buffer colors then resize and everything below the last
// printable char gets reset. See GH #12567
auto newRowY = newCursor.GetPosition().y + 1;
const auto newHeight = newBuffer.GetSize().Height();
const auto oldHeight = oldBuffer._estimateOffsetOfLastCommittedRow() + 1;
for (;
iOldRow < oldHeight && newRowY < newHeight;
iOldRow++)
const auto initializedRowsEnd = oldBuffer._estimateOffsetOfLastCommittedRow() + 1;
for (; oldY < initializedRowsEnd && newY < newHeight; oldY++, newY++)
{
const auto& row = oldBuffer.GetRowByOffset(iOldRow);
// Optimization: Since all these rows are below the last printable char,
// we can reasonably assume that they are filled with just spaces.
// That's convenient, we can just copy the attr row from the old buffer
// into the new one, and resize the row to match. We'll rely on the
// behavior of ATTR_ROW::Resize to trim down when narrower, or extend
// the last attr when wider.
auto& newRow = newBuffer.GetMutableRowByOffset(newRowY);
const auto newWidth = newBuffer.GetLineWidth(newRowY);
newRow.TransferAttributes(row.Attributes(), newWidth);
newRowY++;
auto& oldRow = oldBuffer.GetRowByOffset(oldY);
auto& newRow = newBuffer.GetMutableRowByOffset(newY);
auto& newAttr = newRow.Attributes();
newAttr = oldRow.Attributes();
newAttr.resize_trailing_extent(newWidthU16);
}
// Since we didn't use IncrementCircularBuffer() we need to compute the proper
// _firstRow offset now, in a way that replicates IncrementCircularBuffer().
// We need to do the same for newCursorPos.y for basically the same reason.
if (newY > newHeight)
{
newBuffer._firstRow = newY % newHeight;
// _firstRow maps from API coordinates that always start at 0,0 in the top left corner of the
// terminal's scrollback, to the underlying buffer Y coordinate via `(y + _firstRow) % height`.
// Here, we need to un-map the `newCursorPos.y` from the underlying Y coordinate to the API coordinate
// and so we do `(y - _firstRow) % height`, but we add `+ newHeight` to avoid getting negative results.
newCursorPos.y = (newCursorPos.y - newBuffer._firstRow + newHeight) % newHeight;
}
// Finish copying remaining parameters from the old text buffer to the new one
newBuffer.CopyProperties(oldBuffer);
newBuffer.CopyHyperlinkMaps(oldBuffer);
// If we found where to put the cursor while placing characters into the buffer,
// just put the cursor there. Otherwise we have to advance manually.
if (fFoundCursorPos)
{
newCursor.SetPosition(cNewCursorPos);
}
else
{
// Advance the cursor to the same offset as before
// get the number of newlines and spaces between the old end of text and the old cursor,
// then advance that many newlines and chars
auto iNewlines = cOldCursorPos.y - cOldLastChar.y;
const auto iIncrements = cOldCursorPos.x - cOldLastChar.x;
const auto cNewLastChar = newBuffer.GetLastNonSpaceCharacter();
// If the last row of the new buffer wrapped, there's going to be one less newline needed,
// because the cursor is already on the next line
if (newBuffer.GetRowByOffset(cNewLastChar.y).WasWrapForced())
{
iNewlines = std::max(iNewlines - 1, 0);
}
else
{
// if this buffer didn't wrap, but the old one DID, then the d(columns) of the
// old buffer will be one more than in this buffer, so new need one LESS.
if (oldBuffer.GetRowByOffset(cOldLastChar.y).WasWrapForced())
{
iNewlines = std::max(iNewlines - 1, 0);
}
}
for (auto r = 0; r < iNewlines; r++)
{
newBuffer.NewlineCursor();
}
for (auto c = 0; c < iIncrements - 1; c++)
{
newBuffer.IncrementCursor();
}
}
// Save old cursor size before we delete it
const auto ulSize = oldCursor.GetSize();
// Set size back to real size as it will be taking over the rendering duties.
newCursor.SetSize(ulSize);
assert(newCursorPos.x >= 0 && newCursorPos.x < newWidth);
assert(newCursorPos.y >= 0 && newCursorPos.y < newHeight);
newCursor.SetSize(oldCursor.GetSize());
newCursor.SetPosition(newCursorPos);
newBuffer._marks = oldBuffer._marks;
newBuffer._trimMarksOutsideBuffer();
return S_OK;
}
CATCH_RETURN()
// Method Description:
// - Adds or updates a hyperlink in our hyperlink table
@@ -2916,14 +2908,10 @@ void TextBuffer::AddMark(const ScrollMark& m)
void TextBuffer::_trimMarksOutsideBuffer()
{
const auto height = GetSize().Height();
_marks.erase(std::remove_if(_marks.begin(),
_marks.end(),
[height](const auto& m) {
return (m.start.y < 0) ||
(m.start.y >= height);
}),
_marks.end());
const til::CoordType height = _height;
std::erase_if(_marks, [height](const auto& m) {
return (m.start.y < 0) || (m.start.y >= height);
});
}
std::wstring_view TextBuffer::CurrentCommand() const

View File

@@ -137,6 +137,7 @@ public:
static size_t GraphemeNext(const std::wstring_view& chars, size_t position) noexcept;
static size_t GraphemePrev(const std::wstring_view& chars, size_t position) noexcept;
static size_t FitTextIntoColumns(const std::wstring_view& chars, til::CoordType columnLimit, til::CoordType& columns) noexcept;
til::point NavigateCursor(til::point position, til::CoordType distance) const;
@@ -163,7 +164,7 @@ public:
// Scroll needs access to this to quickly rotate around the buffer.
void IncrementCircularBuffer(const TextAttribute& fillAttributes = {});
til::point GetLastNonSpaceCharacter(std::optional<const Microsoft::Console::Types::Viewport> viewOptional = std::nullopt) const;
til::point GetLastNonSpaceCharacter(const Microsoft::Console::Types::Viewport* viewOptional = nullptr) const;
Cursor& GetCursor() noexcept;
const Cursor& GetCursor() const noexcept;
@@ -194,7 +195,7 @@ public:
void Reset() noexcept;
[[nodiscard]] HRESULT ResizeTraditional(const til::size newSize) noexcept;
void ResizeTraditional(const til::size newSize);
void SetAsActiveBuffer(const bool isActiveBuffer) noexcept;
bool IsActiveBuffer() const noexcept;
@@ -262,10 +263,7 @@ public:
til::CoordType visibleViewportTop{ 0 };
};
static HRESULT Reflow(TextBuffer& oldBuffer,
TextBuffer& newBuffer,
const std::optional<Microsoft::Console::Types::Viewport> lastCharacterViewport,
std::optional<std::reference_wrapper<PositionInformation>> positionInfo);
static void Reflow(TextBuffer& oldBuffer, TextBuffer& newBuffer, const Microsoft::Console::Types::Viewport* lastCharacterViewport = nullptr, PositionInformation* positionInfo = nullptr);
std::vector<til::point_span> SearchText(const std::wstring_view& needle, bool caseInsensitive) const;
std::vector<til::point_span> SearchText(const std::wstring_view& needle, bool caseInsensitive, til::CoordType rowBeg, til::CoordType rowEnd) const;

View File

@@ -46,8 +46,6 @@ namespace
std::vector<TestBuffer> buffers;
};
static constexpr auto true_due_to_exact_wrap_bug{ true };
static const TestCase testCases[] = {
TestCase{
L"No reflow required",
@@ -61,7 +59,7 @@ namespace
{ L"EFG ", false },
{ L" ", false },
},
{ 0, 1 } // cursor on $
{ 0, 1 }, // cursor on $
},
TestBuffer{
{ 5, 5 }, // reduce width by 1
@@ -72,7 +70,7 @@ namespace
{ L"EFG ", false },
{ L" ", false },
},
{ 0, 1 } // cursor on $
{ 0, 1 }, // cursor on $
},
TestBuffer{
{ 4, 5 },
@@ -83,7 +81,7 @@ namespace
{ L"EFG ", false },
{ L" ", false },
},
{ 0, 1 } // cursor on $
{ 0, 1 }, // cursor on $
},
},
},
@@ -99,40 +97,40 @@ namespace
{ L" ", false },
{ L" ", false },
},
{ 0, 1 } // cursor on $
{ 0, 1 }, // cursor on $
},
TestBuffer{
{ 5, 5 }, // reduce width by 1
{
{ L"ABCDE", true },
{ L"F$ ", false }, // [BUG] EXACT WRAP. $ should be alone on next line.
{ L" ", false },
{ L"F ", false },
{ L"$ ", false },
{ L" ", false },
{ L" ", false },
},
{ 1, 1 } // cursor on $
{ 0, 2 }, // cursor on $
},
TestBuffer{
{ 6, 5 }, // grow width back to original
{
{ L"ABCDEF", true_due_to_exact_wrap_bug },
{ L"ABCDEF", false },
{ L"$ ", false },
{ L" ", false },
{ L" ", false },
{ L" ", false },
},
{ 0, 1 } // cursor on $
{ 0, 1 }, // cursor on $
},
TestBuffer{
{ 7, 5 }, // grow width wider than original
{
{ L"ABCDEF$", true_due_to_exact_wrap_bug }, // EXACT WRAP BUG: $ should be alone on next line
{ L" ", false },
{ L"ABCDEF ", false },
{ L"$ ", false },
{ L" ", false },
{ L" ", false },
{ L" ", false },
},
{ 6, 0 } // cursor on $
{ 0, 1 }, // cursor on $
},
},
},
@@ -148,7 +146,7 @@ namespace
{ L" ", false },
{ L" ", false },
},
{ 1, 1 } // cursor on $
{ 1, 1 }, // cursor on $
},
TestBuffer{
{ 5, 5 }, // reduce width by 1
@@ -159,7 +157,7 @@ namespace
{ L" ", false },
{ L" ", false },
},
{ 2, 1 } // cursor on $
{ 2, 1 }, // cursor on $
},
TestBuffer{
{ 6, 5 }, // grow width back to original
@@ -170,7 +168,7 @@ namespace
{ L" ", false },
{ L" ", false },
},
{ 1, 1 } // cursor on $
{ 1, 1 }, // cursor on $
},
TestBuffer{
{ 7, 5 }, // grow width wider than original
@@ -181,7 +179,7 @@ namespace
{ L" ", false },
{ L" ", false },
},
{ 0, 1 } // cursor on $
{ 0, 1 }, // cursor on $
},
},
},
@@ -197,29 +195,29 @@ namespace
{ L"EFG ", false },
{ L" ", false },
},
{ 0, 1 } // cursor on $
{ 0, 1 }, // cursor on $
},
TestBuffer{
{ 7, 5 }, // reduce width by 1
{
{ L"AB $", true },
{ L" CD", true_due_to_exact_wrap_bug },
{ L" ", false },
{ L" CD", false }, // CD ends with a newline -> .wrap = false
{ L"EFG ", false },
{ L" ", false },
{ L" ", false },
},
{ 6, 0 } // cursor on $
{ 6, 0 }, // cursor on $
},
TestBuffer{
{ 8, 5 },
{
{ L"AB $ ", true },
{ L" CD ", false }, // Goes to false because we hit the end of ..CD
{ L"EFG ", false }, // [BUG] EFG moves up due to exact wrap bug above
{ L" CD ", false },
{ L"EFG ", false },
{ L" ", false },
{ L" ", false },
},
{ 6, 0 } // cursor on $
{ 6, 0 }, // cursor on $
},
},
},
@@ -236,19 +234,19 @@ namespace
{ L" ", false },
{ L" ", false },
},
{ 2, 1 } // cursor on $
{ 2, 1 }, // cursor on $
},
TestBuffer{
{ 5, 5 }, // reduce width by 1
{
//--012345--
{ L"カタ ", true }, // KA TA [FORCED SPACER]
{ L"カナ$", true_due_to_exact_wrap_bug }, // KA NA
{ L"カナ$", false }, // KA NA
{ L" ", false },
{ L" ", false },
{ L" ", false },
},
{ 4, 1 } // cursor on $
{ 4, 1 }, // cursor on $
},
TestBuffer{
{ 6, 5 }, // grow width back to original
@@ -260,7 +258,7 @@ namespace
{ L" ", false },
{ L" ", false },
},
{ 2, 1 } // cursor on $
{ 2, 1 }, // cursor on $
},
TestBuffer{
{ 7, 5 }, // grow width wider than original (by one; no visible change!)
@@ -272,7 +270,7 @@ namespace
{ L" ", false },
{ L" ", false },
},
{ 2, 1 } // cursor on $
{ 2, 1 }, // cursor on $
},
TestBuffer{
{ 8, 5 }, // grow width enough to fit second DBCS
@@ -284,7 +282,7 @@ namespace
{ L" ", false },
{ L" ", false },
},
{ 0, 1 } // cursor on $
{ 0, 1 }, // cursor on $
},
},
},
@@ -300,41 +298,29 @@ namespace
{ L"MNOPQR", false },
{ L"STUVWX", false },
},
{ 0, 1 } // cursor on $
{ 0, 1 }, // cursor on $
},
TestBuffer{
{ 5, 5 }, // reduce width by 1
{
{ L"F$ ", false },
{ L"GHIJK", true }, // [BUG] We should see GHIJK\n L\n MNOPQ\n R\n
{ L"LMNOP", true }, // The wrapping here is irregular
{ L"QRSTU", true },
{ L"VWX ", false },
{ L"$ ", false },
{ L"GHIJK", true },
{ L"L ", false },
{ L"MNOPQ", true },
{ L"R ", false },
},
{ 1, 1 } // [BUG] cursor moves to 1,1 instead of sticking with the $
{ 0, 0 },
},
TestBuffer{
{ 6, 5 }, // going back to 6,5, the data lost has been destroyed
{
//{ L"F$ ", false }, // [BUG] this line is erroneously destroyed too!
{ L"GHIJKL", true },
{ L"MNOPQR", true },
{ L"STUVWX", true },
{ L"$ ", false },
{ L"GHIJKL", false },
{ L"MNOPQR", false },
{ L" ", false },
{ L" ", false },
{ L" ", false }, // [BUG] this line is added
},
{ 1, 1 }, // [BUG] cursor does not follow [H], it sticks at 1,1
},
TestBuffer{
{ 7, 5 }, // a number of errors are carried forward from the previous buffer
{
{ L"GHIJKLM", true },
{ L"NOPQRST", true },
{ L"UVWX ", false }, // [BUG] This line loses wrap for some reason
{ L" ", false },
{ L" ", false },
},
{ 0, 1 }, // [BUG] The cursor moves to 0, 1 now, sticking with the [N] from before
{ 0, 0 },
},
},
},
@@ -353,18 +339,18 @@ namespace
{ L" ", false },
{ L" ", false },
},
{ 1, 1 } // cursor *after* $
{ 1, 1 }, // cursor *after* $
},
TestBuffer{
{ 5, 5 }, // reduce width by 1
{
{ L"ABCDE", true },
{ L"F$ ", false }, // [BUG] EXACT WRAP. $ should be alone on next line.
{ L" ", false },
{ L"F ", false },
{ L"$ ", false },
{ L" ", false },
{ L" ", false },
},
{ 2, 1 } // cursor follows space after $ to next line
{ 1, 2 }, // cursor follows space after $ to next line
},
},
},
@@ -380,7 +366,7 @@ namespace
{ L"STUVWX", true },
{ L"YZ0 $ ", false },
},
{ 5, 4 } // cursor *after* $
{ 5, 4 }, // cursor *after* $
},
TestBuffer{
{ 5, 5 }, // reduce width by 1
@@ -391,7 +377,7 @@ namespace
{ L"UVWXY", true },
{ L"Z0 $ ", false },
},
{ 4, 4 } // cursor follows space after $ to newly introduced bottom line
{ 4, 4 }, // cursor follows space after $ to newly introduced bottom line
},
},
},
@@ -402,40 +388,36 @@ namespace
{ 6, 5 },
{
{ L"ABCDEF", false },
// v cursor
{ L"$ ", false },
// ^ cursor
{ L" ", false },
{ L" ", false },
{ L" ", false },
},
{ 5, 1 } // cursor in space far after $
{ 5, 1 }, // The cursor is 5 columns to the right of the $ (last column).
},
TestBuffer{
{ 5, 5 }, // reduce width by 1
{
{ L"ABCDE", true },
{ L"F$ ", true }, // [BUG] This line is marked wrapped, and I do not know why
// v cursor
{ L" ", false },
// ^ cursor
{ L"F ", false },
// The reflow implementation marks a wrapped cursor as a forced row-wrap (= the row is padded with whitespace), so that when
// the buffer is enlarged again, we restore the original cursor position correctly. That's why it says .cursor={5,1} below.
{ L"$ ", true },
{ L" ", false },
{ L" ", false },
},
{ 1, 2 } // cursor stays same linear distance from $
{ 0, 3 }, // $ is now at 0,2 and the cursor used to be 5 columns to the right. -> 0,3
},
TestBuffer{
{ 6, 5 }, // grow back to original size
{
{ L"ABCDEF", true_due_to_exact_wrap_bug },
// v cursor [BUG] cursor does not retain linear distance from $
{ L"ABCDEF", false },
{ L"$ ", false },
// ^ cursor
{ L" ", false },
{ L" ", false },
{ L" ", false },
},
{ 4, 1 } // cursor stays same linear distance from $
{ 5, 1 },
},
},
},
@@ -446,39 +428,37 @@ namespace
{ 6, 5 },
{
{ L"ABCDEF", false },
// v cursor
{ L"$ ", false },
// ^ cursor
{ L"BLAH ", false },
{ L"BLAH ", false },
{ L" ", false },
},
{ 5, 1 } // cursor in space far after $
{ 5, 1 }, // The cursor is 5 columns to the right of the $ (last column).
},
TestBuffer{
{ 5, 5 }, // reduce width by 1
{
{ L"ABCDE", true },
{ L"F$ ", false },
{ L"BLAH ", false },
{ L"BLAH ", true }, // [BUG] this line wraps, no idea why
// v cursor [BUG] cursor erroneously moved to end of all content
{ L"F ", false },
// The reflow implementation pads the row with the cursor with whitespace.
// Search for "REFLOW_JANK_CURSOR_WRAP" to find the corresponding code.
{ L"$ ", true },
{ L" ", false },
// ^ cursor
{ L"BLAH ", false },
{ L"BLAH ", false },
},
{ 0, 4 } },
{ 0, 2 },
},
TestBuffer{
{ 6, 5 }, // grow back to original size
{
{ L"ABCDEF", true },
{ L"F ", false },
{ L"$ ", false },
{ L"BLAH ", false },
// v cursor [BUG] cursor is pulled up to previous line because it was marked wrapped
{ L"BLAH ", false },
// ^ cursor
{ L" ", false },
},
{ 5, 3 } },
{ 5, 1 },
},
},
},
TestCase{
@@ -489,27 +469,24 @@ namespace
{ 6, 5 },
{
{ L"ABCDEF", false },
// v cursor
{ L"$ ", false },
// ^ cursor
{ L" ", false },
{ L" ", false },
{ L" ", false },
},
{ 5, 1 } // cursor in space far after $
{ 5, 1 }, // The cursor is 5 columns to the right of the $ (last column).
},
TestBuffer{
{ 2, 5 }, // reduce width aggressively
{
{ L"CD", true },
{ L"EF", true },
{ L"EF", false },
{ L"$ ", true },
{ L" ", true },
// v cursor
{ L" ", false },
// ^ cursor
},
{ 1, 4 } },
{ 1, 4 },
},
},
},
TestCase{
@@ -519,27 +496,24 @@ namespace
{ 6, 5 },
{
{ L"ABCDEF", true },
// v cursor
{ L"$ ", true },
// ^ cursor
{ L" ", true },
{ L" ", true },
{ L" ", true },
},
{ 5, 1 } // cursor in space far after $
{ 5, 1 }, // cursor in space far after $
},
TestBuffer{
{ 2, 5 }, // reduce width aggressively
{
{ L"EF", true },
{ L"$ ", true },
{ L" ", true },
{ L" ", true },
// v cursor [BUG] cursor does not maintain linear distance from $
{ L" ", false },
// ^ cursor
{ L" ", true },
{ L" ", true },
{ L" ", true },
},
{ 1, 4 } },
{ 1, 0 },
},
},
},
TestCase{
@@ -549,14 +523,12 @@ namespace
{ 6, 5 },
{
{ L"ABCDEF", true },
// v cursor
{ L"$ ", true },
// ^ cursor
{ L" ", true },
{ L" ", true },
{ L" Q", true },
},
{ 5, 1 } // cursor in space far after $
{ 5, 1 }, // cursor in space far after $
},
TestBuffer{
{ 2, 5 }, // reduce width aggressively
@@ -564,12 +536,11 @@ namespace
{ L" ", true },
{ L" ", true },
{ L" ", true },
{ L" Q", true },
// v cursor [BUG] cursor jumps to end of world
{ L" ", false }, // POTENTIAL [BUG] a whole new blank line is added for the cursor
// ^ cursor
{ L" ", true },
{ L" ", true },
},
{ 1, 4 } },
{ 1, 0 },
},
},
},
TestCase{
@@ -579,27 +550,24 @@ namespace
{ 6, 5 },
{
{ L"ABCDEF", false },
// v cursor
{ L"$ ", false },
// ^ cursor
{ L" ", false },
{ L" ", true },
{ L" Q", true },
},
{ 5, 1 } // cursor in space far after $
{ 5, 1 }, // cursor in space far after $
},
TestBuffer{
{ 2, 5 }, // reduce width aggressively
{
{ L" ", true },
{ L" ", true },
{ L" ", true },
{ L" Q", true },
// v cursor [BUG] cursor jumps to different place than fully wrapped case
{ L" ", false },
// ^ cursor
{ L" ", false },
{ L" ", true },
{ L" ", true },
{ L" ", true },
},
{ 0, 4 } },
{ 1, 0 },
},
},
},
TestCase{
@@ -614,24 +582,21 @@ namespace
{ L"$ ", false },
{ L" Q", true },
{ L" ", true },
// v cursor
{ L" ", true },
// ^ cursor
},
{ 5, 4 } // cursor at end of buffer
{ 5, 4 }, // cursor at end of buffer
},
TestBuffer{
{ 2, 5 }, // reduce width aggressively
{
{ L" ", false },
{ L" ", true },
{ L" ", true },
{ L" ", true },
{ L" ", true },
{ L" Q", true },
{ L" ", false },
// v cursor [BUG] cursor loses linear distance from Q; is this important?
{ L" ", false },
// ^ cursor
},
{ 0, 4 } },
{ 1, 0 },
},
},
},
};
@@ -761,7 +726,7 @@ class ReflowTests
static std::unique_ptr<TextBuffer> _textBufferByReflowingTextBuffer(TextBuffer& originalBuffer, const til::size newSize)
{
auto buffer = std::make_unique<TextBuffer>(newSize, TextAttribute{ 0x7 }, 0, false, renderer);
TextBuffer::Reflow(originalBuffer, *buffer, std::nullopt, std::nullopt);
TextBuffer::Reflow(originalBuffer, *buffer);
return buffer;
}

View File

@@ -14,7 +14,7 @@
<ClCompile Include="ReflowTests.cpp" />
<ClCompile Include="TextColorTests.cpp" />
<ClCompile Include="TextAttributeTests.cpp" />
<ClCompile Include="..\precomp.cpp">
<ClCompile Include="precomp.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
@@ -30,7 +30,7 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\precomp.h" />
<ClInclude Include="precomp.h" />
</ItemGroup>
<ItemDefinitionGroup>
<ClCompile>

View File

@@ -7,17 +7,18 @@
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
xmlns:uap17="http://schemas.microsoft.com/appx/manifest/uap/windows10/17"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
xmlns:desktop6="http://schemas.microsoft.com/appx/manifest/desktop/windows10/6"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:virtualization="http://schemas.microsoft.com/appx/manifest/virtualization/windows10"
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
IgnorableNamespaces="uap mp rescap uap3 desktop6 virtualization">
IgnorableNamespaces="uap mp rescap uap3 uap17 desktop6 virtualization">
<Identity
Name="WindowsTerminalCan"
Name="Microsoft.WindowsTerminalCanary"
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
Version="0.0.1.0" />
@@ -33,10 +34,13 @@
<virtualization:ExcludedKey>HKEY_CURRENT_USER\Console\%%Startup</virtualization:ExcludedKey>
</virtualization:ExcludedKeys>
</virtualization:RegistryWriteVirtualization>
<uap17:UpdateWhileInUse>defer</uap17:UpdateWhileInUse>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19041.0" MaxVersionTested="10.0.22621.0" />
<!-- rescap:appLicensing only works on 22000+. Until that's fixed, MinVersion will not let people install it on Windows 10... -->
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.22000.0" MaxVersionTested="10.0.22621.0" />
<TargetDeviceFamily Name="Windows.DesktopServer" MinVersion="10.0.22000.0" MaxVersionTested="10.0.22621.0" />
</Dependencies>
<Resources>
@@ -72,17 +76,17 @@
<desktop:ExecutionAlias Alias="wt.exe" />
</uap3:AppExecutionAlias>
</uap3:Extension>
<uap3:Extension Category="windows.appExtensionHost">
<uap3:AppExtensionHost>
<uap3:Name>com.microsoft.windows.terminal.settings</uap3:Name>
</uap3:AppExtensionHost>
</uap3:Extension>
<uap5:Extension Category="windows.startupTask">
<uap5:StartupTask
TaskId="StartTerminalOnLoginTask"
Enabled="false"
DisplayName="ms-resource:AppNameCan" />
</uap5:Extension>
<uap3:Extension Category="windows.appExtensionHost">
<uap3:AppExtensionHost>
<uap3:Name>com.microsoft.windows.terminal.settings</uap3:Name>
</uap3:AppExtensionHost>
</uap3:Extension>
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.console.host"
Id="OpenConsole-Can"
@@ -90,7 +94,7 @@
Description="Console host built from microsoft/terminal open source repository"
PublicFolder="Public">
<uap3:Properties>
<Clsid>{1F9F2BF5-5BC3-4F17-B0E6-912413F1F451}</Clsid>
<Clsid>{A854D02A-F2FE-44A5-BB24-D03F4CF830D4}</Clsid>
</uap3:Properties>
</uap3:AppExtension>
</uap3:Extension>
@@ -101,7 +105,7 @@
Description="Terminal host built from microsoft/terminal open source repository"
PublicFolder="Public">
<uap3:Properties>
<Clsid>{051F34EE-C1FD-4B19-AF75-9BA54648434C}</Clsid>
<Clsid>{1706609C-A4CE-4C0D-B7D2-C19BF66398A5}</Clsid>
</uap3:Properties>
</uap3:AppExtension>
</uap3:Extension>
@@ -147,5 +151,10 @@
<Capability Name="internetClient" />
<rescap:Capability Name="runFullTrust" />
<rescap:Capability Name="unvirtualizedResources" />
<rescap:Capability Name="appLicensing" />
</Capabilities>
<mp:PhoneIdentity
PhoneProductId="348ff861-8d83-47b2-a740-15f8a096dcae"
PhonePublisherId="00000000-0000-0000-0000-000000000000" />
</Package>

View File

@@ -7,6 +7,7 @@
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
xmlns:uap17="http://schemas.microsoft.com/appx/manifest/uap/windows10/17"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
@@ -14,7 +15,7 @@
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:virtualization="http://schemas.microsoft.com/appx/manifest/virtualization/windows10"
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
IgnorableNamespaces="uap mp rescap uap3 desktop6 virtualization">
IgnorableNamespaces="uap mp rescap uap3 uap17 desktop6 virtualization">
<Identity
Name="WindowsTerminalDev"
@@ -33,10 +34,12 @@
<virtualization:ExcludedKey>HKEY_CURRENT_USER\Console\%%Startup</virtualization:ExcludedKey>
</virtualization:ExcludedKeys>
</virtualization:RegistryWriteVirtualization>
<uap17:UpdateWhileInUse>defer</uap17:UpdateWhileInUse>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19041.0" MaxVersionTested="10.0.22621.0" />
<TargetDeviceFamily Name="Windows.DesktopServer" MinVersion="10.0.19041.0" MaxVersionTested="10.0.22621.0" />
</Dependencies>
<Resources>

View File

@@ -9,13 +9,14 @@
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
xmlns:uap7="http://schemas.microsoft.com/appx/manifest/uap/windows10/7"
xmlns:uap17="http://schemas.microsoft.com/appx/manifest/uap/windows10/17"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
xmlns:desktop6="http://schemas.microsoft.com/appx/manifest/desktop/windows10/6"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:virtualization="http://schemas.microsoft.com/appx/manifest/virtualization/windows10"
IgnorableNamespaces="uap mp rescap uap3 desktop6 virtualization">
IgnorableNamespaces="uap mp rescap uap3 uap17 desktop6 virtualization">
<Identity
Name="Microsoft.WindowsTerminalPreview"
@@ -34,10 +35,12 @@
<virtualization:ExcludedKey>HKEY_CURRENT_USER\Console\%%Startup</virtualization:ExcludedKey>
</virtualization:ExcludedKeys>
</virtualization:RegistryWriteVirtualization>
<uap17:UpdateWhileInUse>defer</uap17:UpdateWhileInUse>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19041.0" MaxVersionTested="10.0.22621.0" />
<TargetDeviceFamily Name="Windows.DesktopServer" MinVersion="10.0.19041.0" MaxVersionTested="10.0.22621.0" />
</Dependencies>
<Resources>

View File

@@ -9,13 +9,14 @@
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
xmlns:uap7="http://schemas.microsoft.com/appx/manifest/uap/windows10/7"
xmlns:uap17="http://schemas.microsoft.com/appx/manifest/uap/windows10/17"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
xmlns:desktop6="http://schemas.microsoft.com/appx/manifest/desktop/windows10/6"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:virtualization="http://schemas.microsoft.com/appx/manifest/virtualization/windows10"
IgnorableNamespaces="uap mp rescap uap3 desktop6 virtualization">
IgnorableNamespaces="uap mp rescap uap3 uap17 desktop6 virtualization">
<Identity
Name="Microsoft.WindowsTerminal"
@@ -34,10 +35,12 @@
<virtualization:ExcludedKey>HKEY_CURRENT_USER\Console\%%Startup</virtualization:ExcludedKey>
</virtualization:ExcludedKeys>
</virtualization:RegistryWriteVirtualization>
<uap17:UpdateWhileInUse>defer</uap17:UpdateWhileInUse>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19041.0" MaxVersionTested="10.0.22621.0" />
<TargetDeviceFamily Name="Windows.DesktopServer" MinVersion="10.0.19041.0" MaxVersionTested="10.0.22621.0" />
</Dependencies>
<Resources>

View File

@@ -74,6 +74,8 @@ namespace SettingsModelLocalTests
TEST_METHOD(TestInheritedCommand);
TEST_METHOD(LoadFragmentsWithMultipleUpdates);
TEST_METHOD(MigrateReloadEnvVars);
private:
static winrt::com_ptr<implementation::CascadiaSettings> createSettings(const std::string_view& userJSON)
{
@@ -2020,4 +2022,40 @@ namespace SettingsModelLocalTests
// GH#12520: Fragments should be able to override the name of builtin profiles.
VERIFY_ARE_EQUAL(L"NewName", loader.userSettings.profiles[0]->Name());
}
void DeserializationTests::MigrateReloadEnvVars()
{
static constexpr std::string_view settings1Json{ R"(
{
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"compatibility.reloadEnvironmentVariables": false,
"profiles": [
{
"name": "profile0",
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"historySize": 1,
"commandline": "cmd.exe"
}
],
"actions": [
{
"name": "foo",
"command": "closePane",
"keys": "ctrl+shift+w"
}
]
})" };
implementation::SettingsLoader loader{ settings1Json, DefaultJson };
loader.MergeInboxIntoUserSettings();
loader.FinalizeLayering();
VERIFY_IS_TRUE(loader.FixupUserSettings(), L"Validate that this will indicate we need to write them back to disk");
const auto settings = winrt::make_self<implementation::CascadiaSettings>(std::move(loader));
Log::Comment(L"Ensure that the profile defaults have the new setting added");
VERIFY_IS_TRUE(settings->ProfileDefaults().HasReloadEnvironmentVariables());
VERIFY_IS_FALSE(settings->ProfileDefaults().ReloadEnvironmentVariables());
}
}

View File

@@ -42,6 +42,9 @@ namespace SettingsModelLocalTests
TEST_METHOD(CascadiaSettings);
TEST_METHOD(LegacyFontSettings);
TEST_METHOD(RoundtripReloadEnvVars);
TEST_METHOD(DontRoundtripNoReloadEnvVars);
private:
// Method Description:
// - deserializes and reserializes a json string representing a settings object model of type T
@@ -513,4 +516,114 @@ namespace SettingsModelLocalTests
VERIFY_ARE_EQUAL(toString(jsonOutput), toString(result));
}
void SerializationTests::RoundtripReloadEnvVars()
{
static constexpr std::string_view oldSettingsJson{ R"(
{
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"compatibility.reloadEnvironmentVariables": false,
"profiles": [
{
"name": "profile0",
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"historySize": 1,
"commandline": "cmd.exe"
}
],
"actions": [
{
"name": "foo",
"command": "closePane",
"keys": "ctrl+shift+w"
}
]
})" };
static constexpr std::string_view newSettingsJson{ R"(
{
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"profiles":
{
"defaults":
{
"compatibility.reloadEnvironmentVariables": false
},
"list":
[
{
"name": "profile0",
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"historySize": 1,
"commandline": "cmd.exe"
}
]
},
"actions": [
{
"name": "foo",
"command": "closePane",
"keys": "ctrl+shift+w"
}
]
})" };
implementation::SettingsLoader oldLoader{ oldSettingsJson, DefaultJson };
oldLoader.MergeInboxIntoUserSettings();
oldLoader.FinalizeLayering();
VERIFY_IS_TRUE(oldLoader.FixupUserSettings(), L"Validate that this will indicate we need to write them back to disk");
const auto oldSettings = winrt::make_self<implementation::CascadiaSettings>(std::move(oldLoader));
const auto oldResult{ oldSettings->ToJson() };
implementation::SettingsLoader newLoader{ newSettingsJson, DefaultJson };
newLoader.MergeInboxIntoUserSettings();
newLoader.FinalizeLayering();
newLoader.FixupUserSettings();
const auto newSettings = winrt::make_self<implementation::CascadiaSettings>(std::move(newLoader));
const auto newResult{ newSettings->ToJson() };
VERIFY_ARE_EQUAL(toString(newResult), toString(oldResult));
}
void SerializationTests::DontRoundtripNoReloadEnvVars()
{
// Kinda like the above test, but confirming that _nothing_ happens if
// we don't have a setting to migrate.
static constexpr std::string_view oldSettingsJson{ R"(
{
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"profiles": [
{
"name": "profile0",
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"historySize": 1,
"commandline": "cmd.exe"
}
],
"actions": [
{
"name": "foo",
"command": "closePane",
"keys": "ctrl+shift+w"
}
]
})" };
implementation::SettingsLoader oldLoader{ oldSettingsJson, DefaultJson };
oldLoader.MergeInboxIntoUserSettings();
oldLoader.FinalizeLayering();
oldLoader.FixupUserSettings();
const auto oldSettings = winrt::make_self<implementation::CascadiaSettings>(std::move(oldLoader));
const auto oldResult{ oldSettings->ToJson() };
Log::Comment(L"Now, create a _new_ settings object from the re-serialization of the first");
implementation::SettingsLoader newLoader{ toString(oldResult), DefaultJson };
newLoader.MergeInboxIntoUserSettings();
newLoader.FinalizeLayering();
newLoader.FixupUserSettings();
const auto newSettings = winrt::make_self<implementation::CascadiaSettings>(std::move(newLoader));
VERIFY_IS_FALSE(newSettings->ProfileDefaults().HasReloadEnvironmentVariables(),
L"Ensure that the new settings object didn't find a reloadEnvironmentVariables");
}
}

View File

@@ -60,7 +60,8 @@ namespace SettingsModelLocalTests
"tabRow":
{
"background": "#FFFF8800",
"unfocusedBackground": "#FF8844"
"unfocusedBackground": "#FF8844",
"iconStyle": "default"
},
"window":
{

View File

@@ -64,6 +64,7 @@ Author(s):
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#include "til.h"
#include <til/winrt.h>
// Common includes for most tests:
#include "../../inc/conattrs.hpp"

View File

@@ -1,64 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{84848BFA-931D-42CE-9ADF-01EE54DE7890}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>PublicTerminalCore</RootNamespace>
<ProjectName>PublicTerminalCore</ProjectName>
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(SolutionDir)src\common.build.pre.props" />
<Import Project="$(SolutionDir)src\common.nugetversions.props" />
<ItemGroup>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="HwndTerminal.cpp" />
<ClCompile Include="HwndTerminalAutomationPeer.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="HwndTerminal.hpp" />
<ClInclude Include="HwndTerminalAutomationPeer.hpp" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)src\terminal\input\lib\terminalinput.vcxproj">
<Project>{1cf55140-ef6a-4736-a403-957e4f7430bb}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)src\cascadia\TerminalCore\lib\TerminalCore-lib.vcxproj">
<Project>{ca5cad1a-abcd-429c-b551-8562ec954746}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)src\types\lib\types.vcxproj">
<Project>{18D09A24-8240-42D6-8CB6-236EEE820263}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)src\renderer\atlas\atlas.vcxproj">
<Project>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)src\renderer\base\lib\base.vcxproj">
<Project>{af0a096a-8b3a-4949-81ef-7df8f0fee91f}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)src\renderer\dx\lib\dx.vcxproj">
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
</ProjectReference>
<ProjectReference Include="..\..\renderer\uia\lib\uia.vcxproj">
<Project>{48d21369-3d7b-4431-9967-24e81292cf63}</Project>
</ProjectReference>
</ItemGroup>
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
</ItemDefinitionGroup>
<Import Project="$(SolutionDir)src\common.build.post.props" />
<Import Project="$(SolutionDir)src\common.nugetversions.targets" />
<!-- LATE LINK LINE OVERRIDES. This project must link named forwarders
instead of APISet forwarders for easier Windows 7 compatibility. -->
<ItemDefinitionGroup>
<Link>
<AdditionalDependencies>delayimp.lib;Uiautomationcore.lib;onecoreuap.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>uiautomationcore.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
</ItemDefinitionGroup>
</Project>

View File

@@ -1,42 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="HwndTerminal.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="HwndTerminalAutomationPeer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="HwndTerminal.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="HwndTerminalAutomationPeer.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -1,4 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"

View File

@@ -1,12 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN // If this is not defined, windows.h includes commdlg.h which defines FindText globally and conflicts with UIAutomation ITextRangeProvider.
#define NOMCX
#define NOHELP
#define NOCOMM
#endif
#include <LibraryIncludes.h>
#include <UIAutomationCore.h>

View File

@@ -15,10 +15,12 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
CommandlineArgs(const winrt::array_view<const winrt::hstring>& args,
winrt::hstring currentDirectory,
const uint32_t showWindowCommand) :
const uint32_t showWindowCommand,
winrt::hstring envString) :
_args{ args.begin(), args.end() },
_cwd{ currentDirectory },
_ShowWindowCommand{ showWindowCommand }
_ShowWindowCommand{ showWindowCommand },
CurrentEnvironment{ envString }
{
}
@@ -27,6 +29,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
void Commandline(const winrt::array_view<const winrt::hstring>& value);
winrt::com_array<winrt::hstring> Commandline();
til::property<winrt::hstring> CurrentEnvironment;
WINRT_PROPERTY(uint32_t, ShowWindowCommand, SW_NORMAL); // SW_NORMAL is 1, 0 is SW_HIDE
private:

View File

@@ -50,7 +50,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
_WindowName{ windowInfo.WindowName() },
_args{ command.Commandline() },
_CurrentDirectory{ command.CurrentDirectory() },
_ShowWindowCommand{ command.ShowWindowCommand() } {};
_ShowWindowCommand{ command.ShowWindowCommand() },
_CurrentEnvironment{ command.CurrentEnvironment() } {};
WindowRequestedArgs(const winrt::hstring& window, const winrt::hstring& content, const Windows::Foundation::IReference<Windows::Foundation::Rect>& bounds) :
_Id{ 0u },
@@ -68,6 +69,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
WINRT_PROPERTY(winrt::hstring, CurrentDirectory);
WINRT_PROPERTY(winrt::hstring, Content);
WINRT_PROPERTY(uint32_t, ShowWindowCommand, SW_NORMAL);
WINRT_PROPERTY(winrt::hstring, CurrentEnvironment);
WINRT_PROPERTY(Windows::Foundation::IReference<Windows::Foundation::Rect>, InitialBounds);
private:

View File

@@ -27,6 +27,7 @@ namespace Microsoft.Terminal.Remoting
String[] Commandline { get; };
String CurrentDirectory { get; };
UInt32 ShowWindowCommand { get; };
String CurrentEnvironment { get; };
String Content { get; };
Windows.Foundation.IReference<Windows.Foundation.Rect> InitialBounds { get; };

View File

@@ -7,11 +7,12 @@ namespace Microsoft.Terminal.Remoting
runtimeclass CommandlineArgs
{
CommandlineArgs();
CommandlineArgs(String[] args, String cwd, UInt32 showWindowCommand);
CommandlineArgs(String[] args, String cwd, UInt32 showWindowCommand, String env);
String[] Commandline { get; set; };
String CurrentDirectory { get; };
UInt32 ShowWindowCommand { get; };
String CurrentEnvironment { get; };
};
runtimeclass RenameRequestArgs

View File

@@ -349,7 +349,10 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// If the name wasn't specified, this will be an empty string.
p->WindowName(args.WindowName());
p->ExecuteCommandline(*winrt::make_self<CommandlineArgs>(args.Commandline(), args.CurrentDirectory(), args.ShowWindowCommand()));
p->ExecuteCommandline(*winrt::make_self<CommandlineArgs>(args.Commandline(),
args.CurrentDirectory(),
args.ShowWindowCommand(),
args.CurrentEnvironment()));
_monarch.AddPeasant(*p);

View File

@@ -52,3 +52,4 @@ TRACELOGGING_DECLARE_PROVIDER(g_hRemotingProvider);
#include "til.h"
#include <cppwinrt_utils.h>
#include <til/winrt.h>

Some files were not shown because too many files have changed in this diff Show More