Skip to content
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

Truncate extra_menu_info when completeopt is in popup mode #3682

Merged
merged 13 commits into from
Jun 14, 2020

Conversation

dhleong
Copy link
Contributor

@dhleong dhleong commented May 13, 2020

Fixes #3547

PR Prelude

Thank you for working on YCM! :)

Please complete these steps and check these boxes (by putting an x inside
the brackets) before filing your PR:

  • I have read and understood YCM's CONTRIBUTING document.
  • I have read and understood YCM's CODE_OF_CONDUCT document.
  • I have included tests for the changes in my PR. If not, I have included a
    rationale for why I haven't.
  • I understand my PR may be closed if it becomes obvious I didn't
    actually perform all of these steps.

Why this change is necessary and useful

[Please explain in detail why the changes in this PR are needed.]

Per discussion in #3547 the popup used when 'popup' is included in completeopt does not get to specify a minimum width, so for languages with verbose signatures like Typescript, the extra information (IE: documentation) that should be viewable there gets very squished and hard to read.

By introducing this simple heuristic, created by @puremourning, of allowing the extra_menu_info to have no more than ~1/3rd of the screen's width in length, we are left with ~1/3rd of the screen for the actual completion word, and ~1/3rd for the documentation. Since we are copying the extra_menu_info into the preview window, information loss is minimal.

We could theoretically introduce an option that could disable this truncation behavior, but I think the real solution in that case is probably for the user to not enable the 'popup' completeopt, since the popup is pretty much unusable in cases where this truncation would kick in.


This change is Reviewable

@codecov
Copy link

codecov bot commented May 13, 2020

Codecov Report

Merging #3682 into master will increase coverage by 0.02%.
The diff coverage is 94.44%.

@@            Coverage Diff             @@
##           master    #3682      +/-   ##
==========================================
+ Coverage   89.33%   89.36%   +0.02%     
==========================================
  Files          25       25              
  Lines        3151     3168      +17     
==========================================
+ Hits         2815     2831      +16     
- Misses        336      337       +1     

Copy link
Member

@puremourning puremourning left a comment

Choose a reason for hiding this comment

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

Thanks for doing this!

One thing with mocking the underlying methods in the test is that means we don't get coverage of them. I think we have a thing in the test suite called like MockVimModule or something that allows you to tell it the values of vim settings that it should return. That might be a better way to mock &columns for example.

Reviewable status: 0 of 2 LGTMs obtained (waiting on @dhleong)


python/ycm/client/completion_request.py, line 197 at r1 (raw file):

      if not preview_info.startswith( extra_menu_info ):
        preview_info = extra_menu_info + '\n\n' + preview_info
      extra_menu_info = extra_menu_info[ : ( max_width - 3 ) ] + '...'

thinking about it. do we need to do this ? I mean maybe set extra_menu_info to '' here ?

As you said, we're sticking it in the popup anyway and the truncated version is probably of relatively little use....

Copy link
Member

@puremourning puremourning left a comment

Choose a reason for hiding this comment

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

But otherwise :lgtm: , though it's mostly my code ;)

Reviewed 5 of 5 files at r1.
Reviewable status: 1 of 2 LGTMs obtained (waiting on @dhleong)

Copy link
Contributor Author

@dhleong dhleong left a comment

Choose a reason for hiding this comment

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

Makes sense, will do.

Reviewable status: 1 of 2 LGTMs obtained (waiting on @puremourning)


python/ycm/client/completion_request.py, line 197 at r1 (raw file):

Previously, puremourning (Ben Jackson) wrote…

thinking about it. do we need to do this ? I mean maybe set extra_menu_info to '' here ?

As you said, we're sticking it in the popup anyway and the truncated version is probably of relatively little use....

I thought about that too, but here's two reasons to keep it as-is:

  1. You get to keep some glanceable information, without scrolling to select an item to see everything
  2. It would result in an inconsistent look—some items that fit within the max_width would show up in the "extras" column, while some would not.

Copy link
Collaborator

@bstaletic bstaletic left a comment

Choose a reason for hiding this comment

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

@dhleong Thanks for the pull request!

Reviewed 5 of 5 files at r1.
Reviewable status: 1 of 2 LGTMs obtained (waiting on @dhleong and @puremourning)


doc/youcompleteme.txt, line 2939 at r1 (raw file):

When this option is set to '1', YCM will add the 'preview' string to Vim's
'completeopt' option (see ':h completeopt'). If your 'completeopt' option
already has 'preview' set, there will be no effect. Alternatively, when set to

Instead of doc/youcompleteme.txt you should edit README.md and then use vim-tools to generate the update to the doc/youcompleteme.txt.


python/ycm/vimsupport.py, line 1314 at r1 (raw file):

def UsingPreviewPopup():
  return 'popup' in ToUnicode( vim.options[ 'completeopt' ] ).split( ',' )

.split( ',' ) isn't needed here.

Also return b'popup' in vim.options[ 'completeopt' ] works, so even ToUnicode() can be avoided.


python/ycm/client/completion_request.py, line 197 at r1 (raw file):

Previously, dhleong (Daniel Leong) wrote…

I thought about that too, but here's two reasons to keep it as-is:

  1. You get to keep some glanceable information, without scrolling to select an item to see everything
  2. It would result in an inconsistent look—some items that fit within the max_width would show up in the "extras" column, while some would not.

I agree with @dhleong on this. I believe we should keep a truncated extra_menu_info.

Copy link
Contributor Author

@dhleong dhleong left a comment

Choose a reason for hiding this comment

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

Reviewable status: 0 of 2 LGTMs obtained (and 1 stale) (waiting on @bstaletic and @puremourning)


doc/youcompleteme.txt, line 2939 at r1 (raw file):

Previously, bstaletic (Boris Staletic) wrote…

Instead of doc/youcompleteme.txt you should edit README.md and then use vim-tools to generate the update to the doc/youcompleteme.txt.

Ah, right. I went ahead and updated README.md but am running into this error trying to use ycm-core/vim-tools:

Traceback (most recent call last):
  File "./vimdoctool.py", line 42, in <module>
    logger.addHandler(coloredlogs.ColoredStreamHandler(show_name=True))
AttributeError: module 'coloredlogs' has no attribute 'ColoredStreamHandler'

python/ycm/vimsupport.py, line 1314 at r1 (raw file):

Previously, bstaletic (Boris Staletic) wrote…

.split( ',' ) isn't needed here.

Also return b'popup' in vim.options[ 'completeopt' ] works, so even ToUnicode() can be avoided.

Done.

Allows us to get coverage of DisplayWidth()
Copy link
Contributor Author

@dhleong dhleong left a comment

Choose a reason for hiding this comment

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

I was able to @patch the vim.options value, but I didn't find an obvious way to mock &columns, so I modified _MockVimOptionsEval to pull from that so tests can override such things in a non-destructive way.

I didn't find an easy way to mock the result of strdisplaywidth, since DisplayWidth and DisplayWidthOfString both use GetIntValue. We could bake something into _MockVimFunctionsEval but that seems brittle, and might cause weird test failures for future features.

Reviewable status: 0 of 2 LGTMs obtained (and 1 stale) (waiting on @bstaletic and @puremourning)

@puremourning
Copy link
Member

puremourning commented May 14, 2020

t. I went ahead and updated README.md but am running into this error trying to use ycm-core/vim-tools:

Thanks!

Here's what i usually do:

$ git clone https://github.com/ycm-core/vim-tools && cd vim-tools
$ python3 -m venv env
$ source env/bin/activate
$ pip install -r requirements.txt
$ cd /path/to/YCM
$ /path/to/vim-tools/html2vimdoc.py -f youcompleteme README.md > doc/youcompleteme.txt

@puremourning
Copy link
Member

fantastic contribution, BTW. Really appreciate it :)

@dhleong
Copy link
Contributor Author

dhleong commented May 14, 2020

Aha, that worked!

And thanks :) I can't really take much credit for it, though, since it's basically just your code.

Copy link
Collaborator

@bstaletic bstaletic left a comment

Choose a reason for hiding this comment

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

I didn't find an obvious way to mock &columns

All vim options should be possible to be updated through ycm.tests.test_utils.VIM_OPTIONS. Since this would be a destructive change, there's a wrapper for this ugliness in ycm.tests.conftest module called UserOptions.

You can see how it works in ycm.tests.youcompleteme_test module, in test YouCompleteMe_NoPythonInterpreterFound_test, but it's basically:

def SomeNewTest_test():
  with UserOptions( { '&any':'options', '&you':'want' } ):
    # The body of the test

This should be able to clean up the code significantly. That's why we've never before had t @patch( 'vim.options' ).

Reviewed 4 of 4 files at r2, 1 of 1 files at r3.
Reviewable status: 0 of 2 LGTMs obtained (and 1 stale) (waiting on @dhleong and @puremourning)


python/ycm/tests/test_utils.py, line 186 at r2 (raw file):

def _MockVimOptionsEval( value ):
  result = VIM_MOCK.options.get( value )

Can't we just add &completeopt to VIM_OPTIONS?

@puremourning
Copy link
Member

And thanks :) I can't really take much credit for it, though, since it's basically just your code.

Hah. No i just did the easy bit. you've done the hard part

Copy link
Contributor Author

@dhleong dhleong left a comment

Choose a reason for hiding this comment

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

All vim options should be possible to be updated through ycm.tests.test_utils.VIM_OPTIONS. Since this would be a destructive change, there's a wrapper for this ugliness in ycm.tests.conftest module called UserOptions

Aha, very cool. I figured there'd be some way to do this!

Reviewable status: 0 of 2 LGTMs obtained (and 1 stale) (waiting on @bstaletic and @puremourning)


python/ycm/tests/test_utils.py, line 186 at r2 (raw file):

Previously, bstaletic (Boris Staletic) wrote…

Can't we just add &completeopt to VIM_OPTIONS?

Reverted this change in favor of leaning on UserOptions, and added some code to ensure vim.options reads from VIM_OPTIONS.

Copy link
Collaborator

@bstaletic bstaletic left a comment

Choose a reason for hiding this comment

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

Reviewed 2 of 2 files at r4.
Reviewable status: 0 of 2 LGTMs obtained (and 1 stale) (waiting on @dhleong and @puremourning)


python/ycm/client/completion_request.py, line 197 at r1 (raw file):

Previously, bstaletic (Boris Staletic) wrote…

I agree with @dhleong on this. I believe we should keep a truncated extra_menu_info.

@puremourning Any comments or is this "resolved"?


python/ycm/tests/test_utils.py, line 645 at r4 (raw file):

  VIM_MOCK.error = VimError
  VIM_MOCK.options = MagicMock()
  VIM_MOCK.options.__getitem__.side_effect = _MockVimOptions

Mind explaining why this is needed or useful? How does it help us make sure that vim.options reads from VIM_OPTIONS?

Copy link
Collaborator

@bstaletic bstaletic left a comment

Choose a reason for hiding this comment

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

Reviewable status: 0 of 2 LGTMs obtained (and 1 stale) (waiting on @dhleong and @puremourning)


python/ycm/tests/client/completion_request_test.py, line 220 at r4 (raw file):

  @patch( "ycm.vimsupport.DisplayWidthOfString", len )

Hmm... this leaves DisplayWidthOfString() not covered by the tests.

https://codecov.io/gh/ycm-core/YouCompleteMe/compare/b48e6d49fa3441f507f91a9dae3437ff64f876f6...982715fcd0e36778dfaa07478d8ab6450ae00192/diff

We do have _MockVimCommand, which is made the side effect of VIM_MOCK object. I should be possible to extend it to support strdisplaywidth() vim function.

If I'm reading the code correctly, just making _MockVimCommand() "aware" of strdisplaywidth() would make tests work without @patch and would improve the coverage.

Copy link
Contributor Author

@dhleong dhleong left a comment

Choose a reason for hiding this comment

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

Reviewable status: 0 of 2 LGTMs obtained (and 1 stale) (waiting on @bstaletic and @puremourning)


python/ycm/tests/test_utils.py, line 645 at r4 (raw file):

Previously, bstaletic (Boris Staletic) wrote…

Mind explaining why this is needed or useful? How does it help us make sure that vim.options reads from VIM_OPTIONS?

Without this, getting a key from vim.options doesn't seem to return anything, so the vim.options['completeopt'] check always returns False.


python/ycm/tests/client/completion_request_test.py, line 220 at r4 (raw file):

Previously, bstaletic (Boris Staletic) wrote…

Hmm... this leaves DisplayWidthOfString() not covered by the tests.

https://codecov.io/gh/ycm-core/YouCompleteMe/compare/b48e6d49fa3441f507f91a9dae3437ff64f876f6...982715fcd0e36778dfaa07478d8ab6450ae00192/diff

We do have _MockVimCommand, which is made the side effect of VIM_MOCK object. I should be possible to extend it to support strdisplaywidth() vim function.

If I'm reading the code correctly, just making _MockVimCommand() "aware" of strdisplaywidth() would make tests work without @patch and would improve the coverage.

My concern is that I've patched it to be implemented as len, but that's not actually the case: emoji, for example, could be two chars but render as 1. This implementation is fine for these tests, but if any functions in the future use DisplayWidthOfString, it could be misleading?

Copy link
Member

@puremourning puremourning left a comment

Choose a reason for hiding this comment

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

:lgtm: with one concern

Thanks for the effort. I can live with the one method not covered.

Reviewed 2 of 4 files at r2, 1 of 1 files at r3, 2 of 2 files at r4.
Reviewable status: 1 of 2 LGTMs obtained (waiting on @bstaletic and @dhleong)


python/ycm/vimsupport.py, line 1314 at r4 (raw file):

def UsingPreviewPopup():
  return b'popup' in vim.options[ 'completeopt' ]

Why did this change ? If a future option is added called nopopup, this won't work:


python/ycm/client/completion_request.py, line 197 at r1 (raw file):

Previously, bstaletic (Boris Staletic) wrote…

@puremourning Any comments or is this "resolved"?

yep, reasons make sense.

Copy link
Contributor Author

@dhleong dhleong left a comment

Choose a reason for hiding this comment

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

Reviewable status: 1 of 2 LGTMs obtained (waiting on @bstaletic)


python/ycm/vimsupport.py, line 1314 at r4 (raw file):

Previously, puremourning (Ben Jackson) wrote…

Why did this change ? If a future option is added called nopopup, this won't work:

Hmm interesting point. It was a suggestion from @bstaletic to simplify the code. Looks like there's also a popuphidden option; should we handle that in some way?

Copy link
Collaborator

@bstaletic bstaletic left a comment

Choose a reason for hiding this comment

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

@dhleong Thanks for the pull request.

I usually don't mind imperfect coverage. Here I'm more concerned about having one or two tests that work differently than the rest, since Ben and I will be the ones maintaining this code for an indefinite amount of time.

Reviewable status: 1 of 2 LGTMs obtained (waiting on @dhleong and @puremourning)


python/ycm/vimsupport.py, line 1314 at r4 (raw file):

Previously, dhleong (Daniel Leong) wrote…

Hmm interesting point. It was a suggestion from @bstaletic to simplify the code. Looks like there's also a popuphidden option; should we handle that in some way?

Just revert the change that I requested. I wasn't thinking of these other possibilities.


python/ycm/tests/client/completion_request_test.py, line 220 at r4 (raw file):

Previously, dhleong (Daniel Leong) wrote…

My concern is that I've patched it to be implemented as len, but that's not actually the case: emoji, for example, could be two chars but render as 1. This implementation is fine for these tests, but if any functions in the future use DisplayWidthOfString, it could be misleading?

You can use @patch( 'thing', return_value = 42 ).

Copy link
Contributor Author

@dhleong dhleong left a comment

Choose a reason for hiding this comment

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

@bstaletic Totally understand, and happy to work together to find a solution that seems maintainable to you.

Reviewable status: 0 of 2 LGTMs obtained (and 1 stale) (waiting on @bstaletic and @puremourning)


python/ycm/vimsupport.py, line 1314 at r4 (raw file):

Previously, bstaletic (Boris Staletic) wrote…

Just revert the change that I requested. I wasn't thinking of these other possibilities.

Done.


python/ycm/tests/client/completion_request_test.py, line 220 at r4 (raw file):

Previously, bstaletic (Boris Staletic) wrote…

You can use @patch( 'thing', return_value = 42 ).

I'm afraid I don't follow what you're suggesting here. I'm already using @patch to provide a "good enough" implementation of DisplayWidthOfString for these specific cases. We could build out a regex and emulate strdisplaywidth() and provide a @patch-able function in the ycm.tests.test_utils namespace that forces tests to provide their own implementation, eg:

def _MockStrDisplayWidth( s )
  raise Exception("You must @patch ycm.tests.test_utils._MockStrDisplayWidth")

But without the DisplayWidthOfString patch we already get an error Unexpected evaluation: strdisplaywidth so I'm not sure what that gains us.

We could also provide a fake implementation of that function, which would indeed let us avoid @patch, but if anyone needs to write a test in the future that feeds emoji or asian letters into something that depends on DisplayWidthOfString, their results will not match what Vim would do, and it would not be obvious that they need to patch something in ycm.tests.test_utils.

Copy link
Member

@puremourning puremourning left a comment

Choose a reason for hiding this comment

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

:lgtm:

Reviewed 1 of 1 files at r5.
Reviewable status: 1 of 2 LGTMs obtained (waiting on @bstaletic)


python/ycm/tests/client/completion_request_test.py, line 220 at r4 (raw file):

Previously, dhleong (Daniel Leong) wrote…

I'm afraid I don't follow what you're suggesting here. I'm already using @patch to provide a "good enough" implementation of DisplayWidthOfString for these specific cases. We could build out a regex and emulate strdisplaywidth() and provide a @patch-able function in the ycm.tests.test_utils namespace that forces tests to provide their own implementation, eg:

def _MockStrDisplayWidth( s )
  raise Exception("You must @patch ycm.tests.test_utils._MockStrDisplayWidth")

But without the DisplayWidthOfString patch we already get an error Unexpected evaluation: strdisplaywidth so I'm not sure what that gains us.

We could also provide a fake implementation of that function, which would indeed let us avoid @patch, but if anyone needs to write a test in the future that feeds emoji or asian letters into something that depends on DisplayWidthOfString, their results will not match what Vim would do, and it would not be obvious that they need to patch something in ycm.tests.test_utils.

Boris is just saying that you can patch it here to return the specific value required for this test. It's not a big deal len is fine for now.

Copy link
Collaborator

@bstaletic bstaletic left a comment

Choose a reason for hiding this comment

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

Reviewable status: 1 of 2 LGTMs obtained (waiting on @dhleong)


python/ycm/tests/client/completion_request_test.py, line 220 at r4 (raw file):

Previously, puremourning (Ben Jackson) wrote…

Boris is just saying that you can patch it here to return the specific value required for this test. It's not a big deal len is fine for now.

@dhleong Sorry for the delay. I didn't want to talk out of my ass, so I went and implemented the changes I was complaining about. The following patch makes the tests work exactly the same, but is consistent with how we mock other commands.

diff --git a/python/ycm/tests/client/completion_request_test.py b/python/ycm/tests/client/completion_request_test.py
index 522c7e80..3435ef9a 100644
--- a/python/ycm/tests/client/completion_request_test.py
+++ b/python/ycm/tests/client/completion_request_test.py
@@ -217,7 +217,6 @@ class ConvertCompletionResponseToVimDatas_test:
     } )
 
 
-  @patch( "ycm.vimsupport.DisplayWidthOfString", len )
   def TruncateForPopup_test( self, *args ):
     with UserOptions( { '&columns': 60, '&completeopt': b'popup,menuone' } ):
       extra_data = {
@@ -244,7 +243,6 @@ class ConvertCompletionResponseToVimDatas_test:
       } )
 
 
-  @patch( "ycm.vimsupport.DisplayWidthOfString", len )
   def OnlyTruncateForPopupIfNecessary_test( self, *args ):
     with UserOptions( { '&columns': 60, '&completeopt': b'popup,menuone' } ):
       extra_data = {
@@ -270,7 +268,6 @@ class ConvertCompletionResponseToVimDatas_test:
       } )
 
 
-  @patch( "ycm.vimsupport.DisplayWidthOfString", len )
   def DontTruncateIfNotPopup_test( self, *args ):
     with UserOptions( { '&columns': 60, '&completeopt': b'preview,menuone' } ):
       extra_data = {
@@ -296,7 +293,6 @@ class ConvertCompletionResponseToVimDatas_test:
       } )
 
 
-  @patch( "ycm.vimsupport.DisplayWidthOfString", len )
   def TruncateForPopupWithoutDuplication_test( self, *args ):
     with UserOptions( { '&columns': 60, '&completeopt': b'popup,menuone' } ):
       extra_data = {
diff --git a/python/ycm/tests/test_utils.py b/python/ycm/tests/test_utils.py
index 85ad9f00..2ba12678 100644
--- a/python/ycm/tests/test_utils.py
+++ b/python/ycm/tests/test_utils.py
@@ -43,6 +43,8 @@ MATCHDELETE_REGEX = re.compile( '^matchdelete\\((?P<id>\\d+)\\)$' )
 OMNIFUNC_REGEX_FORMAT = (
   '^{omnifunc_name}\\((?P<findstart>[01]),[\'"](?P<base>.*)[\'"]\\)$' )
 FNAMEESCAPE_REGEX = re.compile( '^fnameescape\\(\'(?P<filepath>.+)\'\\)$' )
+STRDISPLAYWIDTH_REGEX = re.compile(
+  '^strdisplaywidth\\( ?\'(?P<text>.+)\' ?\\)$' )
 SIGN_LIST_REGEX = re.compile(
   '^silent! sign place buffer=(?P<bufnr>\\d+)$' )
 SIGN_PLACE_REGEX = re.compile(
@@ -290,6 +292,10 @@ def _MockVimEval( value ):
   if value == REDIR[ 'variable' ]:
     return REDIR[ 'output' ]
 
+  match = STRDISPLAYWIDTH_REGEX.search( value )
+  if match:
+    return len( match.group( 'text' ) )
+
   raise VimError( 'Unexpected evaluation: {}'.format( value ) )
 
 

Unless @puremourning has something to say against this, I'd apply this patch.

Copy link
Contributor Author

@dhleong dhleong left a comment

Choose a reason for hiding this comment

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

Reviewable status: 0 of 2 LGTMs obtained (and 1 stale) (waiting on @bstaletic and @puremourning)


python/ycm/tests/client/completion_request_test.py, line 220 at r4 (raw file):

Previously, bstaletic (Boris Staletic) wrote…

@dhleong Sorry for the delay. I didn't want to talk out of my ass, so I went and implemented the changes I was complaining about. The following patch makes the tests work exactly the same, but is consistent with how we mock other commands.

diff --git a/python/ycm/tests/client/completion_request_test.py b/python/ycm/tests/client/completion_request_test.py
index 522c7e80..3435ef9a 100644
--- a/python/ycm/tests/client/completion_request_test.py
+++ b/python/ycm/tests/client/completion_request_test.py
@@ -217,7 +217,6 @@ class ConvertCompletionResponseToVimDatas_test:
     } )
 
 
-  @patch( "ycm.vimsupport.DisplayWidthOfString", len )
   def TruncateForPopup_test( self, *args ):
     with UserOptions( { '&columns': 60, '&completeopt': b'popup,menuone' } ):
       extra_data = {
@@ -244,7 +243,6 @@ class ConvertCompletionResponseToVimDatas_test:
       } )
 
 
-  @patch( "ycm.vimsupport.DisplayWidthOfString", len )
   def OnlyTruncateForPopupIfNecessary_test( self, *args ):
     with UserOptions( { '&columns': 60, '&completeopt': b'popup,menuone' } ):
       extra_data = {
@@ -270,7 +268,6 @@ class ConvertCompletionResponseToVimDatas_test:
       } )
 
 
-  @patch( "ycm.vimsupport.DisplayWidthOfString", len )
   def DontTruncateIfNotPopup_test( self, *args ):
     with UserOptions( { '&columns': 60, '&completeopt': b'preview,menuone' } ):
       extra_data = {
@@ -296,7 +293,6 @@ class ConvertCompletionResponseToVimDatas_test:
       } )
 
 
-  @patch( "ycm.vimsupport.DisplayWidthOfString", len )
   def TruncateForPopupWithoutDuplication_test( self, *args ):
     with UserOptions( { '&columns': 60, '&completeopt': b'popup,menuone' } ):
       extra_data = {
diff --git a/python/ycm/tests/test_utils.py b/python/ycm/tests/test_utils.py
index 85ad9f00..2ba12678 100644
--- a/python/ycm/tests/test_utils.py
+++ b/python/ycm/tests/test_utils.py
@@ -43,6 +43,8 @@ MATCHDELETE_REGEX = re.compile( '^matchdelete\\((?P<id>\\d+)\\)$' )
 OMNIFUNC_REGEX_FORMAT = (
   '^{omnifunc_name}\\((?P<findstart>[01]),[\'"](?P<base>.*)[\'"]\\)$' )
 FNAMEESCAPE_REGEX = re.compile( '^fnameescape\\(\'(?P<filepath>.+)\'\\)$' )
+STRDISPLAYWIDTH_REGEX = re.compile(
+  '^strdisplaywidth\\( ?\'(?P<text>.+)\' ?\\)$' )
 SIGN_LIST_REGEX = re.compile(
   '^silent! sign place buffer=(?P<bufnr>\\d+)$' )
 SIGN_PLACE_REGEX = re.compile(
@@ -290,6 +292,10 @@ def _MockVimEval( value ):
   if value == REDIR[ 'variable' ]:
     return REDIR[ 'output' ]
 
+  match = STRDISPLAYWIDTH_REGEX.search( value )
+  if match:
+    return len( match.group( 'text' ) )
+
   raise VimError( 'Unexpected evaluation: {}'.format( value ) )
 
 

Unless @puremourning has something to say against this, I'd apply this patch.

After being away from this for a while, I see the advantage of doing it this way now. It might still be confusing for the odd case of certain strings that don't have a display width equal to their length, but in the general case this is probably easier to maintain. Patch applied!

Copy link
Collaborator

@bstaletic bstaletic left a comment

Choose a reason for hiding this comment

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

Once again, thanks for the pull request. :lgtm_strong:

Reviewed 2 of 2 files at r6.
Reviewable status: 1 of 2 LGTMs obtained (and 1 stale)

Copy link
Member

@puremourning puremourning left a comment

Choose a reason for hiding this comment

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

:lgtm:

Mucho appreciado. THanks so much 👍

Reviewed 2 of 2 files at r6.
Reviewable status: :shipit: complete! 2 of 2 LGTMs obtained

@mergify
Copy link
Contributor

mergify bot commented May 28, 2020

Thanks for sending a PR!

Copy link
Member

@puremourning puremourning left a comment

Choose a reason for hiding this comment

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

:lgtm:

Reviewed 1 of 1 files at r7.
Reviewable status: :shipit: complete! 2 of 2 LGTMs obtained

@mergify
Copy link
Contributor

mergify bot commented Jun 11, 2020

Thanks for sending a PR!

@puremourning puremourning added the Ship It! Manual override to merge a PR by maintainer label Jun 14, 2020
Copy link
Member

@puremourning puremourning left a comment

Choose a reason for hiding this comment

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

:lgtm:

Reviewed 1 of 1 files at r8.
Reviewable status: :shipit: complete! 2 of 2 LGTMs obtained

@mergify mergify bot merged commit f9906f8 into ycm-core:master Jun 14, 2020
@mergify
Copy link
Contributor

mergify bot commented Jun 14, 2020

Thanks for sending a PR!

1 similar comment
@mergify
Copy link
Contributor

mergify bot commented Jun 14, 2020

Thanks for sending a PR!

@puremourning
Copy link
Member

Finally. Thanks, bot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Ship It! Manual override to merge a PR by maintainer
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Option to abbreviate completion info with completeopt+=popup
3 participants