Shougo/ddu-ui-filer

Level 1 items are displayed multiple times when redrawing with nested (expanded 1 level or more deep) items

Closed this issue · 10 comments

Problems summary

Level 1 items are displayed multiple times when redrawing with nested (expanded 1 level or more deep) items and not expanded level 2 items.

If executing redraw with nested expanded items, expandedItems will contains duplicated level 0 items like followings.

- a item with level 0 path as `search`
- a item with level 1 path as `search`

This will execute expandItem multiple times, and level 1 items will be displayed for the number of executions.

Expected

Level 1 items are displayed once.

Environment Information

  • ddu-ui-filer version (SHA1):

331b70ab12de5395e5d64630186020de24277c88

  • denops.vim version (SHA1):

6578820fb79b1ae45e0dd448fd96dd6deb2f7be0

  • deno version(deno -V output):

deno 1.28.3

  • OS:

macOS 12.6.2

  • neovim/Vim :version output:
NVIM v0.8.2
Build type: Release
LuaJIT 2.1.0-beta3
Compiled by brew@Monterey

Features: +acl +iconv +tui

Provide a minimal init.vim/vimrc without plugin managers (Required!)

set runtimepath+=path/to/denops.vim
set runtimepath+=path/to/ddu.vim
set runtimepath+=path/to/ddu-ui-filer
set runtimepath+=path/to/ddu-column-filename
set runtimepath+=path/to/ddu-source-file
set runtimepath+=path/to/ddu-kind-file

nnoremap <silent> <space>e <Cmd>call ddu#start({
      \   'ui': 'filer',
      \   'sync': v:true,
      \   'sources': [{
      \     'name': 'file',
      \     'options': {
      \       'path': getcwd(),
      \       'columns': ['filename'],
      \     },
      \   }],
      \ })<CR>

nnoremap <silent> <space>o <Cmd>call ddu#ui#filer#do_action('expandItem')<CR>
nnoremap <silent> <space>a <Cmd>call ddu#ui#filer#do_action('itemAction', {'name': 'newFile'})<CR>

How to reproduce the problem from neovim/Vim startup (Required!)

  1. (prepare) create nested directory at your workspace
  2. Open ddu filer ( <space>e )
  3. Expand a directory ( <space>o )
  4. Expand a nested directory ( <space>o )
  5. Create a new file (to redraw tree) ( <space>a )

Screenshot (if possible)

testfile is created file, ddu directory is duplicated.

Screen Shot 2023-01-10 at 2 38 44

Upload the log messages by :redir and :message (if errored)

日本語で失礼します。

ddu-ui-filerのredrawから発生する ddu.vimのexpandItems では item.item が同じものを指し、 item.search が異なる複数の items が渡ってきます。

特に生じやすいのが2階層以上expandしていた場合で、 item.item にはlevel 0のitem (上記スクリーンショットだと denops )が入り、 item.search には各path ( denops , denops/ddu )が絶対パスでそれぞれ入ってきます。

この item.item に入る level 0 のitemが、同じデータでもそれぞれの item 間で別のobjectとして扱われており、Setなどでの同一性チェックでは別として扱われていそうです。
一度vim scriptを経由している のでいったんただの値として渡され、denoに戻るときはそれぞれ別objectとして作成されているのかなと)

そのため、expandSet に同じitemを指すobjectが複数個入る等の想定外な挙動が生じていそうです。

勝手に想像した解決案ですが、

  • Setではなく何らかのidによるMap的な管理をし、expandItem実行時に既にexpandedであればスキップする(子要素=searchの展開処理に遷移する)みたいな処理をする
  • expandItemはitemを渡すのではなくtreePathのようなtreeの構造管理の情報を渡し、既存の状態に依存しないようにする

とかでしょうか。

Fixed. Please update.

@Shougo 修正こちら 9001851 ですよね、redraw時に全treeが閉じるようになってしまいました。

ddu.vimの変更もpush済みでしょうか

申し訳ありませんが、これは仕様となります。
従来の実装では redraw 時にツリーを開き直せるようにしていました。これは利便性のためですが、実装が複雑になりこのような問題も発生したので放棄したのです。

@Shougo 了解です。2点質問ですが、

  • シンプルな実装で達成できそうなら取り込まれる可能性はありそうでしょうか(試してみようかと)
  • treeの構造管理としては treePath がrootから一意にtreeを下層まで辿れる情報(filer以外でもprefixなitemをexpandすれば対象までたどり着くもの)で認識大丈夫そうでしょうか

ファイルの作成や削除時にtreeが閉じないようにしたいので、挑戦してみたいです。

シンプルな実装で達成できそうなら取り込まれる可能性はありそうでしょうか(試してみようかと)

シンプルな実装でバグがなければ取り込みます。

treeの構造管理としては treePath がrootから一意にtreeを下層まで辿れる情報(filer以外でもprefixなitemをexpandすれば対象までたどり着くもの)で認識大丈夫そうでしょうか

treePath が見つからなければ自動的に再帰的に検索します。これは ddu.vim 本体の機能です。

ありがとうございます。やってみます。

ちなみに補足ですが、 redraw_tree 以外でも以下のようなvimのfunction経由でitemを渡す処理ではitemが値渡しになることで問題が生じるかもです。

https://github.com/Shougo/ddu.vim/blob/8e8c1458aaf628528ec2138d97802e6eb1ecce99/autoload/ddu.vim#L19-L27

今のところ問題はないです