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!)
- (prepare) create nested directory at your workspace
- Open ddu filer (
<space>e
) - Expand a directory (
<space>o
) - Expand a nested directory (
<space>o
) - Create a new file (to redraw tree) (
<space>a
)
Screenshot (if possible)
testfile
is created file, ddu
directory is duplicated.
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.
申し訳ありませんが、これは仕様となります。
従来の実装では 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が値渡しになることで問題が生じるかもです。
今のところ問題はないです