-
Notifications
You must be signed in to change notification settings - Fork 7.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds emphasis to Select-String default formatter #8963
Adds emphasis to Select-String default formatter #8963
Conversation
I would suggest that you check to see if the host supports virtual terminal sequences, and if so, use a VT sequence instead of asterisks. Using any character is a bit problematic because you may have that character in the text your searching. That could confuse the user. FWIW, this is how grep "highlights" matched text: The tricky part is figuring out what color (or effect e.g. reverse) to use for matched text. And whatever you pick, you probably need to make it configurable. |
Thanks @rkeithhill for the guidance 😊 This is a student at HackIllinois. @rjmholt and I are working with the students here and are reviewing PRs that they send. All comments are welcome 😊 |
FYI I find this VT sequence resource very handy: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also think that highlighting with some form of colour is a more worthwhile approach, as the matched string itself could easily contain asterisks or really any number of other characters that we might try to emphasize it with.
src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs
Outdated
Show resolved
Hide resolved
I made the matched text red on terminals that support VT sequences and retained the asterisks on terminals that don't support VT sequences. |
@derek-xia can you add a screenshot so everyone can see? |
src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs
Outdated
Show resolved
Hide resolved
test/powershell/Modules/Microsoft.PowerShell.Utility/Select-String.Tests.ps1
Outdated
Show resolved
Hide resolved
test/powershell/Modules/Microsoft.PowerShell.Utility/Select-String.Tests.ps1
Outdated
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs
Outdated
Show resolved
Hide resolved
@@ -1518,6 +1600,9 @@ private bool DoMatchWorker(string operandString, MatchInfo matchInfo, out MatchI | |||
int patternIndex = 0; | |||
matchResult = null; | |||
|
|||
var indexes = new List<int>(); | |||
var lengths = new List<int>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder why we need this if already have the same in matchResult.Matches?
Note that in both cases we have disordered list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm creating new lists in all cases, although I could use matchResult.Matches in most cases and allocate and use these lists only when the SimpleMatch parameter is enabled. If the SimpleMatch parameter is enabled, then the current behavior is that Matches does not contain any Match objects. Without any Match objects, I would need to pass in these lists to implement the colored text when SimpleMatch is enabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should avoid creating or populating lists in the (possibly common) case where Emphasize
is not specified or where VT100 isn't available. We don't want a performance hit in cases where there's no benefit.
That might look something like:
List<int> indexes;
List<int> lengths;
if (Emphasize)
{
indexes = new List<int>();
lengths = new List<int>();
}
...
if (Emphasize)
{
foreach (Match match in matches)
{
indexes.Add(match.Index);
lengths.Add(match.Length);
}
}
// etc.
...
matchResult = Emphasize
? new MatchInfo(indexes, lenghts)
: new MatchInfo();
matchResult.IgnoreCase = !CaseSensitive;
Line = operandString;
// etc.
...
@@ -71,6 +71,33 @@ Describe "Select-String" -Tags "CI" { | |||
$testinputone | Select-String -Pattern "goodbye" -NotMatch | Should -Be "hello", "hello" | |||
} | |||
|
|||
it "Should return an array of matching strings with the first match highlighted when Emphasize is used" { | |||
if ($IsWindows) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't Windows support VT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah rather than doing $IsWindows
you can do:
$Host.UI.SupportsVirtualTerminal
Which returns a bool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first version of Windows 10 (1507) did not support VT. Probably not many folks still using that version but $Host.UI.SupportsVirtualTerminal
works just as well. And you may be running in a different host than conhost.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But those hosts would just not display the color, right?
Would also be best to consider https://no-color.org/
Does it highlight capture group like in #2905? |
test/powershell/Modules/Microsoft.PowerShell.Utility/Select-String.Tests.ps1
Outdated
Show resolved
Hide resolved
test/powershell/Modules/Microsoft.PowerShell.Utility/Select-String.Tests.ps1
Outdated
Show resolved
Hide resolved
@joeyaiello mentioned on Twitter that might be worth considering just making this behaviour the default. Perhaps that might be worth doing? If there are concerns with stability / how different conhosts would work with this we can always stick it behind an experimental feature flag. @TylerLeonhardt, what do you think? |
@vexx32, I think @felixfbecker brought up a very good point - this is more of a formatting concern. Looking at the formatting code, it seems that formatting $_.ToString(((get-location).path)) where All it's doing is calling the $_.Emphasize(((get-location).path)) Does that sound alright @vexx32 @felixfbecker? |
Or maybe call it |
Considering that we would like to receive color input for any output type, this should not be in every single cmdlet, it should be out. |
I don't think this change should not be made in Select-String. You can check out this gist that adds coloring of the matchinfo output as a custom format. https://gist.github.com/powercode/4833804efd23045387bd5d5249d76f7b There already exists an issue for improving the formatting of MatchInfo, but this is a bit of "*nix" thinking where flags on a command modify the output. Make it a view in the formatting system instead. |
I feel like we're all agreeing here. Just want to summarise:
My only question is: should there be a switch for this on the cmdlet? |
If I recall correctly, changes to formatting are not considered "breaking." Emphasis characters are kind of hard to argue for, really. There's no guarantee such characters won't already be somewhere in or around the matched string, unfortunately. Might still be worth doing, I suppose, but honestly I feel simply omitting the formatting where it's not supported is likely to be most effective. I don't think there need be a switch for it. Maybe define one formatview for emphasized and one for non-emphasized? |
I like the coloring but I am not a fan of turning PowerShell into an artist. We do not embed a code formatter, but simply publish AST API. The same with coloring. Perhaps it is not formatting system api but conhost api. $PSColoring = $true # Globally
Get-Date | Format-List -Coloring # Locally |
@iSazonov I agree with you in principle, but I think this kind of match emphasis brings PowerShell up to speed with If we can get this into the formatter, then we can remove or refactor it later with no obligation not to break things. So making the suggested change in the immediate gets us what we want, without committing us to anything down the road (except a public API on The kind of change you're talking about will require committee approval and would be a whole heap of work. It's wanted, but we can have something small in the meantime too. |
Maybe worth writing up an RFC for this? |
We already have the "small" - it is Jason's PSMore. Implementing vNext formatting system based on classes simplify adding new feature such as coloring (new interface?). So I think right way is implementing PSMore project first. (Before Coloring RFC) |
Advanced output formatting is and has always been part of PowerShell - if your shell is object based, and you also want to provide a strong interactive experience, you need a good formatting system, that supports tables, nested data, grouping, truncation, and coloring too. But all of this is separate from the data and API. It shouldn't be exposed in a parameter switch, nor in the returned strings. I like the idea of respecting the user's choice regarding not wanting color output. However I feel like PowerShell has the opportunity here to handle that on a shell level? E.g. it could define a well-known global variable |
@iSazonov... Do you mean https://github.com/lzybkr/PSMore Not sure what the status is on that project... (cc @lzybkr) I want to also remind everyone here that some folks that submit PRs do not know everything about PowerShell and we should treat that as a learning experience to teach folks about PowerShell-specific concepts. |
I think the jury is still out on how do handle colors. I have started on an implementation for better coloring of select-string, but deferred it until we know what to do with colors. That opens up a can of worms, with theming etc. (which may be very important for the color-blind). |
9e6b1e1
to
f9145bd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Looks like the last issue is that the test needs to be fixed |
there was a missing brace so I quickly added it :) lets see what CI says but this should be good to go. |
@@ -127,6 +127,7 @@ Describe "Select-String" -Tags "CI" { | |||
|
|||
It "Should return ParameterBindingException when -Raw and -Quiet are used together" { | |||
{ $testinputone | Select-String -Pattern "hello" -Raw -Quiet -ErrorAction Stop } | Should -Throw -ExceptionType ([System.Management.Automation.ParameterBindingException]) | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This brace seems out of place? I think this whole file should be reformatted so the intention is correct making it easier to understand the braces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe that would be better done in a quick follow-up PR so we can keep track of the diffs and so accidental changes are made?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reformat can be a single commit. Then the fix of the brace a separate commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That test isn't touched in this PR. My last commit just undid an accidental deletion of a brace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@TylerLeonhardt perhaps you can just add a commit after reformatting the tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's wrong with the formatting exactly? I don't see anything wrong with the changes in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not this PR specifically, but if you view the whole file, the indentation is all over the place. Makes it hard to review the code. I still can't tell how that missing brace fixed the code since the indentation isn't consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The indentation issue is because about half the file is indented with tabs instead of spaces. Github renders a tab as 8 spaces, whereas most editors commonly only render it with 4 spaces (though this is configurable).
I think VS Code has a convert tabs to spaces option in its command palette to get rid of the tabs, and then you can do a quick skim over the file to fix any remaining issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I see. For this repo, we've standardized on spaces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
@SteveL-MSFT please rereview |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@TylerLeonhardt I realize my feedback is in the existing code and not part of this specific PR. So if you want to fix it as part of this PR, that's fine, or if you want to submit a new PR that's fine too.
test/powershell/Modules/Microsoft.PowerShell.Utility/Select-String.Tests.ps1
Outdated
Show resolved
Hide resolved
test/powershell/Modules/Microsoft.PowerShell.Utility/Select-String.Tests.ps1
Outdated
Show resolved
Hide resolved
test/powershell/Modules/Microsoft.PowerShell.Utility/Select-String.Tests.ps1
Outdated
Show resolved
Hide resolved
/// Surrounds the matched text with virtual terminal sequences to invert it's color. Used in ToEmphasizedString. | ||
/// </summary> | ||
/// <returns>The matched line with matched text inverted.</returns> | ||
private string EmphasizeLine() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good candidate to be static.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it uses _matchIndexes
? Or do you mean refactor it to be static that takes in _matchIndexes
and _matchLengths
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can pass _matchIndexes
by parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. Just like a whole bunch of other PowerShell code that is similarly caught up by mutated object state implicitly passed in to methods.
But I believe that pre-existed here and this contribution shouldn't be held back on the basis of code debt incurred before PowerShell was open-sourced. This PR has been open long enough and has been a good, responsive, constrained contribution and I think we really need to just accept or reject it, rather than turning it into a Ship of Theseus.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think this one's gone on long enough and is a definite nice-to-have in PSv7 😁
We can always make other smaller changes later. 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR is delayed because it is in new area for PowerShell. However, the code should be clean.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this isn't a public API, we can always refactor internal code. I would suggest a separate PR if it's a concern or @iSazonov you can always add a commit to this PR if you feel strongly about this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I can :-) Do you ok that we have over 70 opened PR? :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iSazonov I'll ask the team to start driving down the number of open PRs
@derek-xia Thank you for your contribution! |
AT LAST! Well done @derek-xia 🎉 |
🎉 Handy links: |
I'm just gonna leave this here... https://twitter.com/fatherjack/status/1199807445037723648?s=19 😁
|
PR Summary
Adds the -Emphasize parameter for Select-String and makes it work with -AllMatches and -SimpleMatch.
The -Emphasize parameter highlights the matched text using the negative escape sequence. Issue #2905.
Started at HackIllinois.
PR Context
Makes it easier to distinguish what users are looking for when using the Select-String cmdlet. Helps resolve issue #2905.
PR Checklist
.h
,.cpp
,.cs
,.ps1
and.psm1
files have the correct copyright headerWIP:
or[ WIP ]
to the beginning of the title (theWIP
bot will keep its status check atPending
while the prefix is present) and remove the prefix when the PR is ready.[feature]
to your commit messages if the change is significant or affects feature tests