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

Some problems in Vim8/neovim #87

Closed
Shougo opened this issue Aug 4, 2021 · 21 comments · Fixed by #90
Closed

Some problems in Vim8/neovim #87

Shougo opened this issue Aug 4, 2021 · 21 comments · Fixed by #90

Comments

@Shougo
Copy link
Contributor

Shougo commented Aug 4, 2021

  1. The cursor is flickered when use ddc.vim in Vim8. It seems when the popup window is displayed, the cursor will be hidden. I don't know why.

  2. The mode string in the echoarea is redrawn when the popup window is displayed in both Vim8 and neovim.

Minimal vimrc

if &compatible
  set nocompatible
endif

set runtimepath^=~/work/ddc.vim
set runtimepath^=~/work/ddc-around
set runtimepath^=~/work/ddc-matcher_head
set runtimepath^=~/work/ddc-sorter_rank
set runtimepath+=~/src/denops.vim

filetype plugin indent on
syntax enable

call ddc#custom#patch_global('sources', ['around'])
"call ddc#custom#patch_global('completionMode', 'inline')
"call ddc#custom#patch_global('completionMode', 'manual')
call ddc#custom#patch_global('sourceOptions', {
      \ '_': {
      \   'ignoreCase': v:true,
      \   'matchers': ['matcher_head'],
      \   'sorters': ['sorter_rank'],
      \ },
      \ 'around': {'mark': 'A'},
      \ })
call ddc#enable()
@Shougo
Copy link
Contributor Author

Shougo commented Aug 4, 2021

Both problems are not occurred in deoplete.

@lambdalisue
Copy link
Member

Could you make it without using ddc.vim?

@Shougo
Copy link
Contributor Author

Shougo commented Aug 4, 2021

@kuuote can reproduce it without ddc.vim...

@Shougo
Copy link
Contributor Author

Shougo commented Aug 4, 2021

It seems from complete() call in ddc.vim.
Without the function call, it is not reporuced.

@Shougo
Copy link
Contributor Author

Shougo commented Aug 4, 2021

The cursor problem is reduced by below config.

let &t_SI = "\<Esc>[6 q"
let &t_EI = "\<Esc>[0 q"

@Shougo
Copy link
Contributor Author

Shougo commented Aug 4, 2021

Both problems are not occurred in deoplete.

In deoplete, the cursor is not hidden when input.

@Shougo
Copy link
Contributor Author

Shougo commented Aug 4, 2021

Could you make it without using ddc.vim?

In Vim8, denops.vim hide the cursor without popup window.
It can be reproduced without ddc.vim.

@kuuote
Copy link
Member

kuuote commented Aug 4, 2021

@Shougo
Sorry, cause of the problem i was recognized was different to this.
Above problem was caused by redrawing in Vim

@lambdalisue
Copy link
Member

It's more likely issues on ddc.vim so close. Please feel free to re-open or re-create once the issue can reproduced without using ddc.vim

@Shougo
Copy link
Contributor Author

Shougo commented Aug 7, 2021

Really? OK. I will create the minimal example. Please wait.

@Shougo
Copy link
Contributor Author

Shougo commented Aug 7, 2021

denops/completion/app.ts

import { Denops } from "https://deno.land/x/denops_std@v1.0.0/mod.ts#^";
import * as autocmd from "https://deno.land/x/denops_std@v1.0.0/autocmd/mod.ts#^";

export async function main(denops: Denops) {
  denops.dispatcher = {
    async onEvent(_arg1: unknown): Promise<void> {
      denops.call("completion#complete");
    },
  };

  await autocmd.group(denops, "completion", (helper: autocmd.GroupHelper) => {
    helper.remove("*");
    for (
      const event of [
        "TextChangedI",
        "TextChangedP",
      ]
    ) {
      helper.define(
        event as autocmd.AutocmdEvent,
        "*",
        `call denops#notify('${denops.name}', 'onEvent', ["${event}"])`,
      );
    }
  });

  console.log(`${denops.name} has loaded`);
}

autoload/completion.vim

let s:root_dir = fnamemodify(expand('<sfile>'), ':h:h')

function! completion#enable() abort
  autocmd User DenopsReady call denops#plugin#register('completion',
        \ denops#util#join_path(s:root_dir, 'denops', 'completion', 'app.ts'))
endfunction

function! completion#complete() abort
  inoremap <silent> <Plug>_ <C-r>=completion#_complete()<CR>

  set completeopt-=longest
  set completeopt+=menuone
  set completeopt-=menu
  set completeopt+=noselect

  call feedkeys("\<Plug>_", 'i')
  return ''
endfunction

function! completion#_complete() abort
  if getline('.') =~ '\w\+$'
    call complete(1, ['foo', 'bar', 'baz'])
  else
    call complete(1, [])
  endif
  return ''
endfunction

Minimal vimrc

if &compatible
  set nocompatible
endif

set runtimepath+=~/src/denops.vim
set runtimepath+=~/src/denops-completion

call completion#enable()

You can reproduce the problems without ddc.vim.

@Shougo Shougo reopened this Aug 7, 2021
@lambdalisue
Copy link
Member

I cloud reproduce 1. but 2. with above. I'll investigate 1. (but I've no idea at least for now)

  1. The cursor is flickered when use ddc.vim in Vim8. It seems when the popup window is displayed, the cursor will be hidden. I don't know why.

  2. The mode string in the echoarea is redrawn when the popup window is displayed in both Vim8 and neovim.

@lambdalisue
Copy link
Member

lambdalisue commented Aug 7, 2021

Not sure but the following fix cursor issue on my environment.

diff --git a/denops/completion/app.ts b/denops/completion/app.ts
index 5c106aa..0e0f977 100644
--- a/denops/completion/app.ts
+++ b/denops/completion/app.ts
@@ -4,7 +4,7 @@ import * as autocmd from "https://deno.land/x/denops_std@v1.0.0/autocmd/mod.ts#^
 export async function main(denops: Denops) {
   denops.dispatcher = {
     async onEvent(_arg1: unknown): Promise<void> {
-      denops.call("completion#complete");
+      await denops.call("completion#complete");
     },
   };
 
@@ -19,7 +19,7 @@ export async function main(denops: Denops) {
       helper.define(
         event as autocmd.AutocmdEvent,
         "*",
-        `call denops#notify('${denops.name}', 'onEvent', ["${event}"])`,
+        `call denops#request('${denops.name}', 'onEvent', ["${event}"])`,
       );
     }
   });

Using denops#notify means that you don't wait onEvent thus I guess onEvent calls pollute something?

@Shougo
Copy link
Contributor Author

Shougo commented Aug 7, 2021

import { Denops } from "https://deno.land/x/denops_std@v1.0.0/mod.ts#^";
import * as autocmd from "https://deno.land/x/denops_std@v1.0.0/autocmd/mod.ts#^";

const wait = async (ms) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, ms)
  });
}

export async function main(denops: Denops) {
  denops.dispatcher = {
    async onEvent(_arg1: unknown): Promise<void> {
      await wait(1000);
      await denops.call("completion#complete");
    },
  };

  await autocmd.group(denops, "completion", (helper: autocmd.GroupHelper) => {
    helper.remove("*");
    for (
      const event of [
        "TextChangedI",
        "TextChangedP",
      ]
    ) {
      helper.define(
        event as autocmd.AutocmdEvent,
        "*",
        `call denops#notify('${denops.name}', 'onEvent', ["${event}"])`,
      );
    }
  });

  console.log(`${denops.name} has loaded`);
}

Please test it.

@Shougo
Copy link
Contributor Author

Shougo commented Aug 7, 2021

let s:root_dir = fnamemodify(expand('<sfile>'), ':h:h')

function! completion#enable() abort
  autocmd User DenopsReady call denops#plugin#register('completion',
        \ denops#util#join_path(s:root_dir, 'denops', 'completion', 'app.ts'))
endfunction

function! completion#complete() abort
  inoremap <silent> <Plug>_ <C-r>=completion#_complete()<CR>

  set completeopt-=longest
  set completeopt+=menuone
  set completeopt-=menu
  set completeopt+=noselect

  call feedkeys("\<Plug>_", 'i')
  return ''
endfunction

function! completion#_complete() abort
  if getline('.') =~ '\w\+$' && getline('.') !~# 'date$'
    call complete(1, map(['foo', 'bar', 'baz'], { _, v -> {'word': v, 'equal': v:true}}))
  else
    call complete(1, [])
  endif
  return ''
endfunction

Please test it and input date date date ... quickly.

@lambdalisue
Copy link
Member

I could reproduce the issue on Vim but Neovim

Vim

I could reproduce "statusline flush" issue when I hit <Esc> to escape from insert mode.

Kapture.2021-08-07.at.15.21.40.mp4

Neovim

I could not reproduce "statuslie flush" issue (but Shougo said it might be a performance difference of the terminal).

Kapture.2021-08-07.at.15.20.41.mp4

@lambdalisue
Copy link
Member

Using denops#notify means that you don't wait onEvent thus I guess onEvent calls pollute something?

Probably this is the reason but ddc.vim use denops#notify on purpose. Using denops#request blocks thus.

@Shougo
Copy link
Contributor Author

Shougo commented Aug 7, 2021

The cursor is flickered when use ddc.vim in Vim8. It seems when the popup window is displayed, the cursor will be hidden. I don't know why.

The problem is fixed when I use denops#request() instead.

But

The mode string in the echoarea is redrawn when the popup window is displayed in both Vim8 and neovim.

Does not fix.

@Shougo
Copy link
Contributor Author

Shougo commented Aug 7, 2021

The cursor is flickered when use ddc.vim in Vim8. It seems when the popup window is displayed, the cursor will be hidden. I don't know why.

It is fixed after de-bounce.

@Shougo Shougo closed this as completed Aug 7, 2021
@Shougo
Copy link
Contributor Author

Shougo commented Aug 7, 2021

The mode string in the echoarea is redrawn when the popup window is displayed in both Vim8 and neovim.

It is also reproduced in deoplete. It is less flicker though.

@lambdalisue lambdalisue linked a pull request Aug 7, 2021 that will close this issue
@lambdalisue
Copy link
Member

lambdalisue commented Aug 7, 2021

📝

This is the debounced version I suggested and solved.

let s:root_dir = fnamemodify(expand('<sfile>'), ':h:h')
let s:complete_timer = v:null

function! completion#enable() abort
  autocmd User DenopsReady call denops#plugin#register('completion',
        \ denops#util#join_path(s:root_dir, 'denops', 'completion', 'app.ts'))
endfunction

function! completion#complete() abort
  " デバウンス
  silent! call timer_stop(s:complete_timer)
  let s:complete_timer = timer_start(10, { -> completion#_complete() })
endfunction

function! completion#_complete() abort
  " 入力モードじゃない可能性もあるので...この辺の条件は知らないです
  if mode() !=# 'i'
    return
  endif
  set completeopt-=longest
  set completeopt+=menuone
  set completeopt-=menu
  set completeopt+=noselect
  if getline('.') =~ '\w\+$' && getline('.') !~# 'date$'
    call complete(1, map(['foo', 'bar', 'baz'], { _, v -> {'word': v, 'equal': v:true}}))
  else
    call complete(1, [])
  endif
endfunction

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants