Skip to content

Commit

Permalink
Take wrapping into account when expanding wordwise selections
Browse files Browse the repository at this point in the history
Closes #17165
  • Loading branch information
DHowett committed May 1, 2024
1 parent 32fbb16 commit 97c3180
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 36 deletions.
35 changes: 30 additions & 5 deletions src/buffer/out/textBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1440,10 +1440,23 @@ til::point TextBuffer::_GetWordStartForSelection(const til::point target, const
// expand left until we hit the left boundary or a different delimiter class
while (result != bufferSize.Origin() && _GetDelimiterClassAt(result, wordDelimiters) == initialDelimiter)
{
//prevent selection wrapping on whitespace selection
if (isControlChar && result.x == bufferSize.Left())
if (result.x == bufferSize.Left())
{
break;
// Prevent wrapping to the previous line if the selection begins on whitespace
if (isControlChar)
{
break;
}

if (result.y > 0)
{
// Prevent wrapping to the previous line if it was hard-wrapped (e.g. not forced by us to wrap)
const auto& priorRow = GetRowByOffset(result.y - 1);
if (!priorRow.WasWrapForced())
{
break;
}
}
}
bufferSize.DecrementInBounds(result);
}
Expand Down Expand Up @@ -1563,10 +1576,22 @@ til::point TextBuffer::_GetWordEndForSelection(const til::point target, const st
// expand right until we hit the right boundary as a ControlChar or a different delimiter class
while (result != bufferSize.BottomRightInclusive() && _GetDelimiterClassAt(result, wordDelimiters) == initialDelimiter)
{
if (isControlChar && result.x == bufferSize.RightInclusive())
if (result.x == bufferSize.RightInclusive())
{
break;
// Prevent wrapping to the next line if the selection begins on whitespace
if (isControlChar)
{
break;
}

// Prevent wrapping to the next line if this one was hard-wrapped (e.g. not forced by us to wrap)
const auto& row = GetRowByOffset(result.y);
if (!row.WasWrapForced())
{
break;
}
}

bufferSize.IncrementInBoundsCircular(result);
}

Expand Down
85 changes: 54 additions & 31 deletions src/host/ut_host/TextBufferTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2336,16 +2336,31 @@ void TextBufferTests::GetWordBoundaries()
}

_buffer->Reset();
_buffer->ResizeTraditional({ 10, 5 });
_buffer->ResizeTraditional({ 10, 6 });
const std::vector<std::wstring> secondText = { L"this wordiswrapped",
L"notwrapped"

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

notwrapped is not a recognized word. (unrecognized-spelling)
L"spaces wrapped reachEOB" };
//Buffer looks like:
// this wordi
// swrapped
// spaces
// wrappe
// d reachEOB

WriteLinesToBuffer(secondText, *_buffer);

//Buffer looks like:
// 0123456789
// 0|this wordi| < wrapped
// 1|swrapped | < not wrapped
// 2|notwrapped| < not wrapped

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

notwrapped is not a recognized word. (unrecognized-spelling)
// 3|spaces | < wrapped
// 4| wrappe| < wrapped
// 5|d reachEOB| < wrapped

VERIFY_IS_TRUE(_buffer->GetRowByOffset(0).WasWrapForced());
VERIFY_IS_FALSE(_buffer->GetRowByOffset(1).WasWrapForced());
// GH#780 See the comment in WriteLinesToBuffer
// VERIFY_IS_FALSE(_buffer->GetRowByOffset(2).WasWrapForced());
_buffer->GetMutableRowByOffset(2).SetWrapForced(false); // Ugh
VERIFY_IS_TRUE(_buffer->GetRowByOffset(3).WasWrapForced());
VERIFY_IS_TRUE(_buffer->GetRowByOffset(4).WasWrapForced());
VERIFY_IS_TRUE(_buffer->GetRowByOffset(5).WasWrapForced());

testData = {
{ { 0, 0 }, { { 0, 0 }, { 0, 0 } } },
{ { 1, 0 }, { { 0, 0 }, { 0, 0 } } },
Expand All @@ -2358,15 +2373,18 @@ void TextBufferTests::GetWordBoundaries()
{ { 9, 1 }, { { 8, 1 }, { 5, 0 } } },

{ { 0, 2 }, { { 0, 2 }, { 0, 2 } } },
{ { 7, 2 }, { { 6, 2 }, { 0, 2 } } },

{ { 1, 3 }, { { 0, 3 }, { 0, 2 } } },
{ { 4, 3 }, { { 4, 3 }, { 4, 3 } } },
{ { 8, 3 }, { { 4, 3 }, { 4, 3 } } },

{ { 0, 4 }, { { 4, 3 }, { 4, 3 } } },
{ { 1, 4 }, { { 1, 4 }, { 4, 3 } } },
{ { 9, 4 }, { { 2, 4 }, { 2, 4 } } },
{ { 9, 2 }, { { 0, 2 }, { 0, 2 } } },
// v accessibility does not consider wrapping
{ { 0, 3 }, { { 0, 3 }, { 0, 2 } } },
{ { 7, 3 }, { { 6, 3 }, { 0, 2 } } },
// v accessibility does not consider wrapping
{ { 1, 4 }, { { 0, 4 }, { 0, 2 } } },
{ { 4, 4 }, { { 4, 4 }, { 4, 4 } } },
{ { 8, 4 }, { { 4, 4 }, { 4, 4 } } },

{ { 0, 5 }, { { 4, 4 }, { 4, 4 } } },
{ { 1, 5 }, { { 1, 5 }, { 4, 4 } } },
{ { 9, 5 }, { { 2, 5 }, { 2, 5 } } },
};
for (const auto& test : testData)
{
Expand All @@ -2377,12 +2395,14 @@ void TextBufferTests::GetWordBoundaries()
}

//GetWordEnd for Wrapping Text
//Buffer looks like:
// this wordi
// swrapped
// spaces
// wrappe
// d reachEOB
// Buffer:
// 0123456789
// 0|this wordi| < wrapped
// 1|swrapped | < not wrapped
// 2|notwrapped| < not wrapped

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

notwrapped is not a recognized word. (unrecognized-spelling)
// 3|spaces | < wrapped
// 4| wrappe| < wrapped
// 5|d reachEOB| < wrapped
testData = {
// tests for first line of text
{ { 0, 0 }, { { 3, 0 }, { 5, 0 } } },
Expand All @@ -2395,17 +2415,20 @@ void TextBufferTests::GetWordBoundaries()
{ { 7, 1 }, { { 7, 1 }, { 0, 2 } } },
{ { 9, 1 }, { { 9, 1 }, { 0, 2 } } },

{ { 0, 2 }, { { 5, 2 }, { 4, 3 } } },
{ { 7, 2 }, { { 9, 2 }, { 4, 3 } } },
{ { 0, 2 }, { { 9, 2 }, { 4, 4 } } },
{ { 9, 2 }, { { 9, 2 }, { 4, 4 } } },

{ { 0, 3 }, { { 5, 3 }, { 4, 4 } } },
{ { 7, 3 }, { { 9, 3 }, { 4, 4 } } },

{ { 1, 3 }, { { 3, 3 }, { 4, 3 } } },
{ { 4, 3 }, { { 0, 4 }, { 2, 4 } } },
{ { 8, 3 }, { { 0, 4 }, { 2, 4 } } },
{ { 1, 4 }, { { 3, 4 }, { 4, 4 } } },
{ { 4, 4 }, { { 0, 5 }, { 2, 5 } } },
{ { 8, 4 }, { { 0, 5 }, { 2, 5 } } },

{ { 0, 4 }, { { 0, 4 }, { 2, 4 } } },
{ { 1, 4 }, { { 1, 4 }, { 2, 4 } } },
{ { 4, 4 }, { { 9, 4 }, { 0, 5 } } },
{ { 9, 4 }, { { 9, 4 }, { 0, 5 } } },
{ { 0, 5 }, { { 0, 5 }, { 2, 5 } } },
{ { 1, 5 }, { { 1, 5 }, { 2, 5 } } },
{ { 4, 5 }, { { 9, 5 }, { 0, 6 } } },
{ { 9, 5 }, { { 9, 5 }, { 0, 6 } } },
};
// clang-format on

Expand Down

1 comment on commit 97c3180

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@check-spelling-bot Report

🔴 Please review

See the 📜action log or 📝 job summary for details.

Unrecognized words (1)

notwrapped

To accept these unrecognized words as correct, you could run the following commands

... in a clone of the git@github.com:microsoft/terminal.git repository
on the dev/duhowett/word-warping branch (ℹ️ how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/v0.0.22/apply.pl' |
perl - 'https://github.com/microsoft/terminal/actions/runs/8911950895/attempts/1'
Available 📚 dictionaries could cover words (expected and unrecognized) not in the 📘 dictionary

This includes both expected items (2202) from .github/actions/spelling/expect/04cdb9b77d6827c0202f51acd4205b017015bfff.txt
.github/actions/spelling/expect/alphabet.txt
.github/actions/spelling/expect/expect.txt
.github/actions/spelling/expect/web.txt and unrecognized words (1)

Dictionary Entries Covers Uniquely
cspell:cpp/src/lang-jargon.txt 11 1 1
cspell:swift/src/swift.txt 53 1 1
cspell:gaming-terms/dict/gaming-terms.txt 59 1 1
cspell:monkeyc/src/monkeyc_keywords.txt 123 1 1
cspell:cryptocurrencies/cryptocurrencies.txt 125 1 1

Consider adding them (in .github/workflows/spelling2.yml) for uses: check-spelling/check-spelling@v0.0.22 in its with:

      with:
        extra_dictionaries:
          cspell:cpp/src/lang-jargon.txt
          cspell:swift/src/swift.txt
          cspell:gaming-terms/dict/gaming-terms.txt
          cspell:monkeyc/src/monkeyc_keywords.txt
          cspell:cryptocurrencies/cryptocurrencies.txt

To stop checking additional dictionaries, add (in .github/workflows/spelling2.yml) for uses: check-spelling/check-spelling@v0.0.22 in its with:

check_extra_dictionaries: ''
Errors (1)

See the 📜action log or 📝 job summary for details.

❌ Errors Count
❌ ignored-expect-variant 3

See ❌ Event descriptions for more information.

✏️ Contributor please read this

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.

If the listed items are:

  • ... misspelled, then please correct them instead of using the command.
  • ... names, please add them to .github/actions/spelling/allow/names.txt.
  • ... APIs, you can add them to a file in .github/actions/spelling/allow/.
  • ... just things you're using, please add them to an appropriate file in .github/actions/spelling/expect/.
  • ... tokens you only need in one place and shouldn't generally be used, you can add an item in an appropriate file in .github/actions/spelling/patterns/.

See the README.md in each directory for more information.

🔬 You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. 😉

If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

Please sign in to comment.