From 236ffb6495c63d8fcd1f92542807d6ed2d20a843 Mon Sep 17 00:00:00 2001 From: Derek Xia Date: Tue, 8 Oct 2019 18:11:10 -0500 Subject: [PATCH] Adds emphasis to `Select-String` default formatter (#8963) --- .../commands/utility/MatchString.cs | 166 ++++++++- .../PowerShellCore_format_ps1xml.cs | 2 +- .../Select-String.Tests.ps1 | 349 ++++++++++-------- 3 files changed, 356 insertions(+), 161 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs index 110dea324d3..f1052cbea52 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs @@ -88,6 +88,43 @@ public class MatchInfo /// The text of the matching line. public string Line { get; set; } = string.Empty; + /// + /// Gets or sets a value indicating whether the matched portion of the string is highlighted. + /// + /// Whether the matched portion of the string is highlighted with the negative VT sequence. + private readonly bool _emphasize; + + /// + /// Stores the starting index of each match within the line. + /// + private readonly IReadOnlyList _matchIndexes; + + /// + /// Stores the length of each match within the line. + /// + private readonly IReadOnlyList _matchLengths; + + /// + /// Initializes a new instance of the class with emphasis disabled. + /// + public MatchInfo() + { + this._emphasize = false; + } + + /// + /// Initializes a new instance of the class with emphasized matched text. + /// Used when virtual terminal sequences are supported. + /// + /// Sets the matchIndexes. + /// Sets the matchLengths. + public MatchInfo(IReadOnlyList matchIndexes, IReadOnlyList matchLengths) + { + this._emphasize = true; + this._matchIndexes = matchIndexes; + this._matchLengths = matchLengths; + } + /// /// Gets the base name of the file containing the matching line. /// @@ -214,6 +251,19 @@ public override string ToString() /// Directory to use as the root when calculating the relative path. /// The string representation of the match object. public string ToString(string directory) + { + return ToString(directory, Line); + } + + /// + /// Returns the string representation of the match object with the matched line passed + /// in as and trims the path to be relative to + /// the argument. + /// + /// Directory to use as the root when calculating the relative path. + /// Line that the match occurs in. + /// The string representation of the match object. + private string ToString(string directory, string line) { string displayPath = (directory != null) ? RelativePath(directory) : _path; @@ -221,7 +271,7 @@ public string ToString(string directory) // enable context-tracking. if (Context == null) { - return FormatLine(Line, this.LineNumber, displayPath, EmptyPrefix); + return FormatLine(line, this.LineNumber, displayPath, EmptyPrefix); } // Otherwise, render the full context. @@ -233,7 +283,7 @@ public string ToString(string directory) lines.Add(FormatLine(contextLine, displayLineNumber++, displayPath, ContextPrefix)); } - lines.Add(FormatLine(Line, displayLineNumber++, displayPath, MatchPrefix)); + lines.Add(FormatLine(line, displayLineNumber++, displayPath, MatchPrefix)); foreach (string contextLine in Context.DisplayPostContext) { @@ -243,6 +293,61 @@ public string ToString(string directory) return string.Join(System.Environment.NewLine, lines.ToArray()); } + /// + /// Returns the string representation of the match object same format as ToString() + /// and inverts the color of the matched text if virtual terminal is supported. + /// + /// Directory to use as the root when calculating the relative path. + /// The string representation of the match object with matched text inverted. + public string ToEmphasizedString(string directory) + { + if (!_emphasize) + { + return ToString(directory); + } + + return ToString(directory, EmphasizeLine()); + } + + /// + /// Surrounds the matched text with virtual terminal sequences to invert it's color. Used in ToEmphasizedString. + /// + /// The matched line with matched text inverted. + private string EmphasizeLine() + { + const string InvertColorsVT100 = "\u001b[7m"; + const string ResetVT100 = "\u001b[0m"; + + char[] chars = new char[(_matchIndexes.Count * (InvertColorsVT100.Length + ResetVT100.Length)) + Line.Length]; + int lineIndex = 0; + int charsIndex = 0; + for (int i = 0; i < _matchIndexes.Count; i++) + { + // Adds characters before match + Line.CopyTo(lineIndex, chars, charsIndex, _matchIndexes[i] - lineIndex); + charsIndex += _matchIndexes[i] - lineIndex; + lineIndex = _matchIndexes[i]; + + // Adds opening vt sequence + InvertColorsVT100.CopyTo(0, chars, charsIndex, InvertColorsVT100.Length); + charsIndex += InvertColorsVT100.Length; + + // Adds characters being emphasized + Line.CopyTo(lineIndex, chars, charsIndex, _matchLengths[i]); + lineIndex += _matchLengths[i]; + charsIndex += _matchLengths[i]; + + // Adds closing vt sequence + ResetVT100.CopyTo(0, chars, charsIndex, ResetVT100.Length); + charsIndex += ResetVT100.Length; + } + + // Adds remaining characters in line + Line.CopyTo(lineIndex, chars, charsIndex, Line.Length - lineIndex); + + return new string(chars); + } + /// /// Formats a line for use in ToString. /// @@ -1062,6 +1167,12 @@ public string[] LiteralPath [Parameter] public SwitchParameter List { get; set; } + /// + /// Gets or sets a value indicating if highlighting should be disabled. + /// + [Parameter] + public SwitchParameter NoEmphasis { get; set; } + /// /// Gets or sets files to include. Files matching /// one of these (if specified) are included. @@ -1541,6 +1652,20 @@ private bool DoMatchWorker(string operandString, MatchInfo matchInfo, out MatchI int patternIndex = 0; matchResult = null; + List indexes = null; + List lengths = null; + + bool shouldEmphasize = !NoEmphasis && Host.UI.SupportsVirtualTerminal; + + // If Emphasize is set and VT is supported, + // the lengths and starting indexes of regex matches + // need to be passed in to the matchInfo object. + if (shouldEmphasize) + { + indexes = new List(); + lengths = new List(); + } + if (!SimpleMatch) { while (patternIndex < Pattern.Length) @@ -1557,6 +1682,16 @@ private bool DoMatchWorker(string operandString, MatchInfo matchInfo, out MatchI { matches = new Match[mc.Count]; ((ICollection)mc).CopyTo(matches, 0); + + if (shouldEmphasize) + { + foreach (Match match in matches) + { + indexes.Add(match.Index); + lengths.Add(match.Length); + } + } + gotMatch = true; } } @@ -1567,6 +1702,12 @@ private bool DoMatchWorker(string operandString, MatchInfo matchInfo, out MatchI if (match.Success) { + if (shouldEmphasize) + { + indexes.Add(match.Index); + lengths.Add(match.Length); + } + matches = new Match[] { match }; } } @@ -1587,8 +1728,15 @@ private bool DoMatchWorker(string operandString, MatchInfo matchInfo, out MatchI { string pat = Pattern[patternIndex]; - if (operandString.IndexOf(pat, compareOption) >= 0) + int index = operandString.IndexOf(pat, compareOption); + if (index >= 0) { + if (shouldEmphasize) + { + indexes.Add(index); + lengths.Add(pat.Length); + } + gotMatch = true; break; } @@ -1637,12 +1785,12 @@ private bool DoMatchWorker(string operandString, MatchInfo matchInfo, out MatchI } // otherwise construct and populate a new MatchInfo object - matchResult = new MatchInfo - { - IgnoreCase = !CaseSensitive, - Line = operandString, - Pattern = Pattern[patternIndex] - }; + matchResult = shouldEmphasize + ? new MatchInfo(indexes, lengths) + : new MatchInfo(); + matchResult.IgnoreCase = !CaseSensitive; + matchResult.Line = operandString; + matchResult.Pattern = Pattern[patternIndex]; if (_preContext > 0 || _postContext > 0) { diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs index 03414836b6d..50b68355373 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs @@ -376,7 +376,7 @@ private static IEnumerable ViewsOf_Microsoft_PowerShell_Co yield return new FormatViewDefinition("MatchInfo", CustomControl.Create() .StartEntry() - .AddScriptBlockExpressionBinding(@"$_.ToString(((get-location).path))") + .AddScriptBlockExpressionBinding(@"$_.ToEmphasizedString(((get-location).path))") .EndEntry() .EndControl()); } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Select-String.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Select-String.Tests.ps1 index 861d5b11465..8a73ddfe8b4 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Select-String.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Select-String.Tests.ps1 @@ -1,207 +1,254 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. + Describe "Select-String" -Tags "CI" { - $nl = [Environment]::NewLine - $currentDirectory = $pwd.Path + BeforeAll { + $nl = [Environment]::NewLine + $currentDirectory = $pwd.Path + } + Context "String actions" { - $testinputone = "hello","Hello","goodbye" - $testinputtwo = "hello","Hello" + $testinputone = "hello","Hello","goodbye" + $testinputtwo = "hello","Hello" - it "Should be called without errors" { - { $testinputone | Select-String -Pattern "hello" } | Should -Not -Throw - } + it "Should be called without errors" { + { $testinputone | Select-String -Pattern "hello" } | Should -Not -Throw + } it "Should return an array data type when multiple matches are found" { $result = $testinputtwo | Select-String -Pattern "hello" - ,$result | Should -BeOfType "System.Array" + ,$result | Should -BeOfType "System.Array" } - it "Should return an object type when one match is found" { - $result = $testinputtwo | Select-String -Pattern "hello" -CaseSensitive - ,$result | Should -BeOfType "System.Object" - } + it "Should return an object type when one match is found" { + $result = $testinputtwo | Select-String -Pattern "hello" -CaseSensitive + ,$result | Should -BeOfType "System.Object" + } - it "Should return matchinfo type" { - $result = $testinputtwo | Select-String -Pattern "hello" -CaseSensitive - ,$result | Should -BeOfType "Microsoft.PowerShell.Commands.MatchInfo" - } + it "Should return matchinfo type" { + $result = $testinputtwo | Select-String -Pattern "hello" -CaseSensitive + ,$result | Should -BeOfType "Microsoft.PowerShell.Commands.MatchInfo" + } - it "Should be called without an error using ca for casesensitive " { - {$testinputone | Select-String -Pattern "hello" -ca } | Should -Not -Throw - } + it "Should be called without an error using ca for casesensitive " { + {$testinputone | Select-String -Pattern "hello" -ca } | Should -Not -Throw + } - it "Should use the ca alias for casesensitive" { - $firstMatch = $testinputtwo | Select-String -Pattern "hello" -CaseSensitive - $secondMatch = $testinputtwo | Select-String -Pattern "hello" -ca + it "Should use the ca alias for casesensitive" { + $firstMatch = $testinputtwo | Select-String -Pattern "hello" -CaseSensitive + $secondMatch = $testinputtwo | Select-String -Pattern "hello" -ca - $equal = @(Compare-Object $firstMatch $secondMatch).Length -eq 0 - $equal | Should -Be True - } + $equal = @(Compare-Object $firstMatch $secondMatch).Length -eq 0 + $equal | Should -Be True + } - it "Should only return the case sensitive match when the casesensitive switch is used" { - $testinputtwo | Select-String -Pattern "hello" -CaseSensitive | Should -Be "hello" - } + it "Should only return the case sensitive match when the casesensitive switch is used" { + $testinputtwo | Select-String -Pattern "hello" -CaseSensitive | Should -Be "hello" + } - it "Should accept a collection of strings from the input object" { - { Select-String -InputObject "some stuff", "other stuff" -Pattern "other" } | Should -Not -Throw - } + it "Should accept a collection of strings from the input object" { + { Select-String -InputObject "some stuff", "other stuff" -Pattern "other" } | Should -Not -Throw + } - it "Should return system.object when the input object switch is used on a collection" { - $result = Select-String -InputObject "some stuff", "other stuff" -pattern "other" - ,$result | Should -BeOfType "System.Object" - } + it "Should return system.object when the input object switch is used on a collection" { + $result = Select-String -InputObject "some stuff", "other stuff" -pattern "other" + ,$result | Should -BeOfType "System.Object" + } - it "Should return null or empty when the input object switch is used on a collection and the pattern does not exist" { - Select-String -InputObject "some stuff", "other stuff" -Pattern "neither" | Should -BeNullOrEmpty - } + it "Should return null or empty when the input object switch is used on a collection and the pattern does not exist" { + Select-String -InputObject "some stuff", "other stuff" -Pattern "neither" | Should -BeNullOrEmpty + } - it "Should return a bool type when the quiet switch is used" { - ,($testinputtwo | Select-String -Quiet "hello" -CaseSensitive) | Should -BeOfType "System.Boolean" - } + it "Should return a bool type when the quiet switch is used" { + ,($testinputtwo | Select-String -Quiet "hello" -CaseSensitive) | Should -BeOfType "System.Boolean" + } + + it "Should be true when select string returns a positive result when the quiet switch is used" { + ($testinputtwo | Select-String -Quiet "hello" -CaseSensitive) | Should -BeTrue + } - it "Should be true when select string returns a positive result when the quiet switch is used" { - ($testinputtwo | Select-String -Quiet "hello" -CaseSensitive) | Should -BeTrue - } + it "Should be empty when select string does not return a result when the quiet switch is used" { + $testinputtwo | Select-String -Quiet "goodbye" | Should -BeNullOrEmpty + } + + it "Should return an array of non matching strings when the switch of NotMatch is used and the string do not match" { + $testinputone | Select-String -Pattern "goodbye" -NotMatch | Should -BeExactly "hello", "Hello" + } - it "Should be empty when select string does not return a result when the quiet switch is used" { - $testinputtwo | Select-String -Quiet "goodbye" | Should -BeNullOrEmpty - } + it "Should output a string with the first match highlighted" { + if ($Host.UI.SupportsVirtualTerminal) + { + $result = $testinputone | Select-String -Pattern "l" | Out-String + $result | Should -Be "`nhe`e[7ml`e[0mlo`nHe`e[7ml`e[0mlo`n`n" + } + else + { + $result = $testinputone | Select-String -Pattern "l" | Out-String + $result | Should -Be "`nhello`nHello`n`n" + } + } + + it "Should output a string with all matches highlighted when AllMatch is used" { + if ($Host.UI.SupportsVirtualTerminal) + { + $result = $testinputone | Select-String -Pattern "l" -AllMatch | Out-String + $result | Should -Be "`nhe`e[7ml`e[0m`e[7ml`e[0mo`nHe`e[7ml`e[0m`e[7ml`e[0mo`n`n" + } + else + { + $result = $testinputone | Select-String -Pattern "l" -AllMatch | Out-String + $result | Should -Be "`nhello`nHello`n`n" + } + } - it "Should return an array of non matching strings when the switch of NotMatch is used and the string do not match" { - $testinputone | Select-String -Pattern "goodbye" -NotMatch | Should -BeExactly "hello", "Hello" - } + it "Should output a string with the first match highlighted when SimpleMatch is used" { + if ($Host.UI.SupportsVirtualTerminal) + { + $result = $testinputone | Select-String -Pattern "l" -SimpleMatch | Out-String + $result | Should -Be "`nhe`e[7ml`e[0mlo`nHe`e[7ml`e[0mlo`n`n" + } + else + { + $result = $testinputone | Select-String -Pattern "l" -SimpleMatch | Out-String + $result | Should -Be "`nhello`nHello`n`n" + } + } - it "Should return the same as NotMatch" { - $firstMatch = $testinputone | Select-String -pattern "goodbye" -NotMatch - $secondMatch = $testinputone | Select-String -pattern "goodbye" -n + it "Should output a string without highlighting when NoEmphasis is used" { + $result = $testinputone | Select-String -Pattern "l" -NoEmphasis | Out-String + $result | Should -Be "`nhello`nHello`n`n" + } - $equal = @(Compare-Object $firstMatch $secondMatch).Length -eq 0 - $equal | Should -BeTrue - } + it "Should return an array of matching strings without virtual terminal sequences" { + $testinputone | Select-String -Pattern "l" | Should -Be "hello", "hello" + } - It "Should return a string type when -Raw is used" { - $result = $testinputtwo | Select-String -Pattern "hello" -CaseSensitive -Raw - $result | Should -BeOfType "System.String" - } + It "Should return a string type when -Raw is used" { + $result = $testinputtwo | Select-String -Pattern "hello" -CaseSensitive -Raw + $result | Should -BeOfType "System.String" + } - 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]) - } + 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]) + } } Context "Filesystem actions" { - $testDirectory = $TestDrive - $testInputFile = Join-Path -Path $testDirectory -ChildPath testfile1.txt - - BeforeEach { - New-Item $testInputFile -Itemtype "file" -Force -Value "This is a text string, and another string${nl}This is the second line${nl}This is the third line${nl}This is the fourth line${nl}No matches" - } + $testDirectory = $TestDrive + $testInputFile = Join-Path -Path $testDirectory -ChildPath testfile1.txt - AfterEach { - Remove-Item $testInputFile -Force - } + BeforeEach { + New-Item $testInputFile -Itemtype "file" -Force -Value "This is a text string, and another string${nl}This is the second line${nl}This is the third line${nl}This is the fourth line${nl}No matches" + } - It "Should return an object when a match is found is the file on only one line" { - $result = Select-String $testInputFile -Pattern "string" - ,$result | Should -BeOfType "System.Object" - } + AfterEach { + Remove-Item $testInputFile -Force + } - It "Should return an array when a match is found is the file on several lines" { - $result = Select-String $testInputFile -Pattern "in" - ,$result | Should -BeOfType "System.Array" - $result[0] | Should -BeOfType "Microsoft.PowerShell.Commands.MatchInfo" - } + It "Should return an object when a match is found is the file on only one line" { + $result = Select-String $testInputFile -Pattern "string" + ,$result | Should -BeOfType "System.Object" + } - It "Should return the name of the file and the string that 'string' is found if there is only one lines that has a match" { - $expected = $testInputFile + ":1:This is a text string, and another string" + It "Should return an array when a match is found is the file on several lines" { + $result = Select-String $testInputFile -Pattern "in" + ,$result | Should -BeOfType "System.Array" + $result[0] | Should -BeOfType "Microsoft.PowerShell.Commands.MatchInfo" + } - Select-String $testInputFile -Pattern "string" | Should -BeExactly $expected - } + It "Should return the name of the file and the string that 'string' is found if there is only one lines that has a match" { + $expected = $testInputFile + ":1:This is a text string, and another string" - It "Should return all strings where 'second' is found in testfile1 if there is only one lines that has a match" { - $expected = $testInputFile + ":2:This is the second line" + Select-String $testInputFile -Pattern "string" | Should -BeExactly $expected + } - Select-String $testInputFile -Pattern "second"| Should -BeExactly $expected - } + It "Should return all strings where 'second' is found in testfile1 if there is only one lines that has a match" { + $expected = $testInputFile + ":2:This is the second line" - It "Should return all strings where 'in' is found in testfile1 pattern switch is not required" { - $expected1 = "This is a text string, and another string" - $expected2 = "This is the second line" - $expected3 = "This is the third line" - $expected4 = "This is the fourth line" + Select-String $testInputFile -Pattern "second"| Should -BeExactly $expected + } - (Select-String in $testInputFile)[0].Line | Should -BeExactly $expected1 - (Select-String in $testInputFile)[1].Line | Should -BeExactly $expected2 - (Select-String in $testInputFile)[2].Line | Should -BeExactly $expected3 - (Select-String in $testInputFile)[3].Line | Should -BeExactly $expected4 - (Select-String in $testInputFile)[4].Line | Should -BeNullOrEmpty - } + It "Should return all strings where 'in' is found in testfile1 pattern switch is not required" { + $expected1 = "This is a text string, and another string" + $expected2 = "This is the second line" + $expected3 = "This is the third line" + $expected4 = "This is the fourth line" + + (Select-String in $testInputFile)[0].Line | Should -BeExactly $expected1 + (Select-String in $testInputFile)[1].Line | Should -BeExactly $expected2 + (Select-String in $testInputFile)[2].Line | Should -BeExactly $expected3 + (Select-String in $testInputFile)[3].Line | Should -BeExactly $expected4 + (Select-String in $testInputFile)[4].Line | Should -BeNullOrEmpty + } - It "Should return empty because 'for' is not found in testfile1 " { - Select-String for $testInputFile | Should -BeNullOrEmpty - } + It "Should return empty because 'for' is not found in testfile1 " { + Select-String for $testInputFile | Should -BeNullOrEmpty + } - It "Should return the third line in testfile1 and the lines above and below it " { - $expectedLine = "testfile1.txt:2:This is the second line" - $expectedLineBefore = "testfile1.txt:3:This is the third line" - $expectedLineAfter = "testfile1.txt:4:This is the fourth line" + It "Should return the third line in testfile1 and the lines above and below it " { + $expectedLine = "testfile1.txt:2:This is the second line" + $expectedLineBefore = "testfile1.txt:3:This is the third line" + $expectedLineAfter = "testfile1.txt:4:This is the fourth line" - Select-String third $testInputFile -Context 1 | Should -Match $expectedLine - Select-String third $testInputFile -Context 1 | Should -Match $expectedLineBefore - Select-String third $testInputFile -Context 1 | Should -Match $expectedLineAfter - } + Select-String third $testInputFile -Context 1 | Should -Match $expectedLine + Select-String third $testInputFile -Context 1 | Should -Match $expectedLineBefore + Select-String third $testInputFile -Context 1 | Should -Match $expectedLineAfter + } - It "Should return the number of matches for 'is' in textfile1 " { - (Select-String is $testInputFile -CaseSensitive).count| Should -Be 4 - } + It "Should return the number of matches for 'is' in textfile1 " { + (Select-String is $testInputFile -CaseSensitive).count| Should -Be 4 + } - It "Should return the third line in testfile1 when a relative path is used" { - $expected = "testfile1.txt:3:This is the third line" + It "Should return the third line in testfile1 when a relative path is used" { + $expected = "testfile1.txt:3:This is the third line" - $relativePath = Join-Path -Path $testDirectory -ChildPath ".." - $relativePath = Join-Path -Path $relativePath -ChildPath $TestDirectory.Name - $relativePath = Join-Path -Path $relativePath -ChildPath testfile1.txt - Select-String third $relativePath | Should -Match $expected - } + $relativePath = Join-Path -Path $testDirectory -ChildPath ".." + $relativePath = Join-Path -Path $relativePath -ChildPath $TestDirectory.Name + $relativePath = Join-Path -Path $relativePath -ChildPath testfile1.txt + Select-String third $relativePath | Should -Match $expected + } - It "Should return the fourth line in testfile1 when a relative path is used" { - $expected = "testfile1.txt:5:No matches" + It "Should return the fourth line in testfile1 when a relative path is used" { + $expected = "testfile1.txt:5:No matches" - Push-Location $testDirectory + Push-Location $testDirectory - Select-String matches (Join-Path -Path $testDirectory -ChildPath testfile1.txt) | Should -Match $expected - Pop-Location - } + Select-String matches (Join-Path -Path $testDirectory -ChildPath testfile1.txt) | Should -Match $expected + Pop-Location + } - It "Should return the fourth line in testfile1 when a regular expression is used" { - $expected = "testfile1.txt:5:No matches" + It "Should return the fourth line in testfile1 when a regular expression is used" { + $expected = "testfile1.txt:5:No matches" - Select-String 'matc*' $testInputFile -CaseSensitive | Should -Match $expected - } + Select-String 'matc*' $testInputFile -CaseSensitive | Should -Match $expected + } - It "Should return the fourth line in testfile1 when a regular expression is used, using the alias for casesensitive" { - $expected = "testfile1.txt:5:No matches" + It "Should return the fourth line in testfile1 when a regular expression is used, using the alias for casesensitive" { + $expected = "testfile1.txt:5:No matches" - Select-String 'matc*' $testInputFile -ca | Should -Match $expected - } + Select-String 'matc*' $testInputFile -ca | Should -Match $expected + } - It "Should return all strings where 'in' is found in testfile1, when -Raw is used." { - $expected1 = "This is a text string, and another string" - $expected2 = "This is the second line" - $expected3 = "This is the third line" - $expected4 = "This is the fourth line" + It "Should return all strings where 'in' is found in testfile1, when -Raw is used." { + $expected1 = "This is a text string, and another string" + $expected2 = "This is the second line" + $expected3 = "This is the third line" + $expected4 = "This is the fourth line" + + (Select-String in $testInputFile -Raw)[0] | Should -BeExactly $expected1 + (Select-String in $testInputFile -Raw)[1] | Should -BeExactly $expected2 + (Select-String in $testInputFile -Raw)[2] | Should -BeExactly $expected3 + (Select-String in $testInputFile -Raw)[3] | Should -BeExactly $expected4 + (Select-String in $testInputFile -Raw)[4] | Should -BeNullOrEmpty + } - (Select-String in $testInputFile -Raw)[0] | Should -BeExactly $expected1 - (Select-String in $testInputFile -Raw)[1] | Should -BeExactly $expected2 - (Select-String in $testInputFile -Raw)[2] | Should -BeExactly $expected3 - (Select-String in $testInputFile -Raw)[3] | Should -BeExactly $expected4 - (Select-String in $testInputFile -Raw)[4] | Should -BeNullOrEmpty - } + It "Should ignore -Context parameter when -Raw is used." { + $expected = "This is the second line" + Select-String second $testInputFile -Raw -Context 2,2 | Should -BeExactly $expected + } + } - It "Should ignore -Context parameter when -Raw is used." { - $expected = "This is the second line" - Select-String second $testInputFile -Raw -Context 2,2 | Should -BeExactly $expected - } + AfterAll { + Push-Location $currentDirectory } - Push-Location $currentDirectory }