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

DynamicPicker: Recalculate column widths for new options #6004

Conversation

the-mikedavis
Copy link
Member

This fixes blank row text in a DynamicPicker which is initially given no options. This can happen for language servers which respond to the workspace symbol request for an empty query with an empty list of symbols, and that behavior is somewhat common since returning all symbols as the spec suggests is very expensive.

For empty options, Picker::new calculated the widths of each column as 0. We can recalculate the column widths when the new options are set to fix this. This refactor is also a good opportunity to formalize setting new options on a picker: besides setting the new options and calculating column widths we also want to reset the cursor and rescore the options.

Fixes #5920

This fixes blank row text in a DynamicPicker which is initially given
no options. This can happen for language servers which respond to
the workspace symbol request for an empty query with an empty list
of symbols, and that behavior is somewhat common since returning all
symbols as the spec suggests is very expensive.

For empty options, `Picker::new` calculated the widths of each column
as 0. We can recalculate the column widths when the new options are
set to fix this. This refactor is also a good opportunity to formalize
setting new options on a picker: besides setting the new options and
calculating column widths we also want to reset the cursor and rescore
the options.
@the-mikedavis the-mikedavis added C-bug Category: This is a bug A-helix-term Area: Helix term improvements S-waiting-on-review Status: Awaiting review from a maintainer. labels Feb 15, 2023
@pascalkuthe
Copy link
Member

pascalkuthe commented Feb 15, 2023

A small note: This is a bit inconsistent with the normal (non dynamic) picker because the table width is updated when filtering now. So if we have one item with a lot of text for one column (and very little text for the others) the coumn width will be adjusted when that item is filtered out in the dynamic picker but not in the normal picker.

I think we should land this as is fix regardless but we might think whether updating the colum widths in the normal picker on filtering might be desirable in the future. This is not that important right now because no menu::Item implementation returns more than one column right now.

This looks good to me and would be good to land before the next release to avoid introducting a regression 👍

@pascalkuthe pascalkuthe added this to the next milestone Feb 15, 2023
@StratilJakub
Copy link

StratilJakub commented Feb 16, 2023

Thanks for this fix!

I was also looking into this yesterday, since I had this issue not only with symbol picker, but also with picker introduced in #4687, which I am trying (works great so far btw.).

I am really out of my depth here, but I have couple of questions to better educate myself... If you have time to answer.
In my fork I explored and tried couple of options before settling on final fix - option 3.

  1. I tried something similar to fix in this PR, but I just plainly copied the width calculation to separate function and called it in force_score. This worked, but it seemed to me it introduced kind of flickering of the results in the picker on each key event. Also if I am not mistaken, the File picker is not recalculating the widths on event, so this does not seem entirely necessary. Btw. should I have any performance considerations. Is recalculating the widths of the columns costly, etc.?
  2. I considered initialising the pickers with WalkBuilder files same as file_picker, but it was too much changes for pretty much first changes I did in this repo with beginner level rust experience. Would it be possible solution to extract the WalkBuilder logic and reuse it also for symbol picker / global search?
  3. In the end in my fork I tried the simplest fix I could think of: invisible fix commit in fork
    I guess it works because of what Pascal described, that right now there is just one column anyway.

Btw. by this change I tried if the global search picker would filter the results with init value from / register, but it does not work. I am wondering why, but that's off-topic.

@the-mikedavis
Copy link
Member Author

force_score can also be called on changes to the prompt which is too often. The picker has to format all of the Items which could be a little expensive if there are many options.

The symbol picker would not use WalkBuilder - it's rendering a list of symbols sent by the language server rather than crawling files. Ideally we should be able to display any list of information in the pickers so I don't think we should include WalkBuilder in the picker code itself.

@rcorre
Copy link
Contributor

rcorre commented Feb 19, 2023

I can confirm this fixes #5920 for both GDScript and c++ for me. Thanks!

@rcorre
Copy link
Contributor

rcorre commented Mar 3, 2023

EDIT: The crash below is unrelated to this PR, I opened #6183

I've been running this for two weeks and it works great! I did recently hit a crash that seems like it might be related:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Line index out of bounds: line index 2447, Rope/RopeSlice line count 2', /home/rcorre/.cargo/registry/src/git.luolix.top-1ecc6299db9ec823/ropey-1.6.0/src/rope.rs:764:41
stack backtrace:
   0:     0x55cdc46538ce - std::backtrace_rs::backtrace::libunwind::trace::h8f4e76b8218b8540
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
   1:     0x55cdc46538ce - std::backtrace_rs::backtrace::trace_unsynchronized::hcdb6a06d2fd94ab3
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:     0x55cdc46538ce - std::sys_common::backtrace::_print_fmt::h6986e85b14c0a3c2
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/sys_common/backtrace.rs:65:5
   3:     0x55cdc46538ce - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hf09049473c7eb0d5
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/sys_common/backtrace.rs:44:22
   4:     0x55cdc3c96c3e - core::fmt::write::h7b08166a7a14a28e
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/fmt/mod.rs:1208:17
   5:     0x55cdc464d975 - std::io::Write::write_fmt::hdb3e773b5b1c54df
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/io/mod.rs:1682:15
   6:     0x55cdc46536a5 - std::sys_common::backtrace::_print::h1ceaebbb26a3fab3
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/sys_common/backtrace.rs:47:5
   7:     0x55cdc46536a5 - std::sys_common::backtrace::print::hb5aa1269b1b9bc74
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/sys_common/backtrace.rs:34:9
   8:     0x55cdc465538f - std::panicking::default_hook::{{closure}}::hbaa8ce6d79af00fb
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/panicking.rs:267:22
   9:     0x55cdc4655104 - std::panicking::default_hook::hcd65d80b40db7fc0
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/panicking.rs:286:9
  10:     0x55cdc4655a34 - <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::ha4979ddfbbe58f68
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/alloc/src/boxed.rs:2032:9
  11:     0x55cdc4655a34 - std::panicking::rust_panic_with_hook::hbb6ac4823ece4d03
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/panicking.rs:692:13
  12:     0x55cdc46557c6 - std::panicking::begin_panic_handler::{{closure}}::h325f7839ba4584c6
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/panicking.rs:579:13
  13:     0x55cdc4653dfc - std::sys_common::backtrace::__rust_end_short_backtrace::hacaef3341973bb56
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/sys_common/backtrace.rs:137:18
  14:     0x55cdc4655502 - rust_begin_unwind
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/panicking.rs:575:5
  15:     0x55cdc3bfae53 - core::panicking::panic_fmt::hef6845e1540bf16b
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/panicking.rs:64:14
  16:     0x55cdc3bfb2e3 - core::result::unwrap_failed::h1f98fd83f4600fae
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/result.rs:1791:5
  17:     0x55cdc4184b59 - <helix_term::ui::picker::FilePicker<T> as helix_term::compositor::Component>::render::hd1406ac8ad88ea8d
  18:     0x55cdc44959c3 - helix_term::application::Application::render::{{closure}}::h33a15c26d08f463c
  19:     0x55cdc4490d30 - helix_term::application::Application::run::{{closure}}::hd63e40f057d8bba9
  20:     0x55cdc44ad57d - tokio::runtime::park::CachedParkThread::block_on::h434028d4201394df
  21:     0x55cdc44ebd81 - tokio::runtime::runtime::Runtime::block_on::h05d528a7b6129759
  22:     0x55cdc45164a1 - hx::main::he97254461597aec0
  23:     0x55cdc44be1f3 - std::sys_common::backtrace::__rust_begin_short_backtrace::h9f546a3dfbf57ddf
n  24:     0x55cdc44fe52d - std::rt::lang_start::{{closure}}::h5759d7483a21f898
  25:     0x55cdc4648528 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h2e730c3fa855d1cd
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/ops/function.rs:606:13
  26:     0x55cdc4648528 - std::panicking::try::do_call::h2452817705661d69
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/panicking.rs:483:40
  27:     0x55cdc4648528 - std::panicking::try::had9be61d7261a8f5
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/panicking.rs:447:19
  28:     0x55cdc4648528 - std::panic::catch_unwind::h0e0ee12d5e0e8c35
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/panic.rs:137:14
  29:     0x55cdc4648528 - std::rt::lang_start_internal::{{closure}}::hdfa1f1493a65dae1
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/rt.rs:148:48
  30:     0x55cdc4648528 - std::panicking::try::do_call::h5a2ac6628cbce239
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/panicking.rs:483:40
  31:     0x55cdc4648528 - std::panicking::try::h6b550c44d18ea4fc
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/panicking.rs:447:19
  32:     0x55cdc4648528 - std::panic::catch_unwind::hd574fc8a4fcd921a
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/panic.rs:137:14
  33:     0x55cdc4648528 - std::rt::lang_start_internal::h4189ab0091a05404
                               at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/rt.rs:148:20
  34:     0x55cdc45165a5 - main
  35:     0x7fcdcbcf7790 - <unknown>
  36:     0x7fcdcbcf784a - __libc_start_main
  37:     0x55cdc3c3f715 - _start
  38:                0x0 - <unknown>

It happened while editing https://github.com/godotengine/godot/blob/master/editor/project_converter_3_to_4.cpp, and using the workspace symbol picker to search for find

helix.log

@the-mikedavis
Copy link
Member Author

I'm not totally sure but I think from the backtrace that the panic is unrelated to these changes. I'm guessing that the godot language server is returning an incorrect range for a symbol and when we try to show that in the file preview we panic because we're slicing outside of the document. If you can reproduce the crash reliably, could you also test this against master?

@rcorre
Copy link
Contributor

rcorre commented Mar 3, 2023

Will do. Just to clarify, this is clangd. I'm editing c++ code in godotengine.

@rcorre
Copy link
Contributor

rcorre commented Mar 4, 2023

My bad, this does happen even without the patch. I opened #6183

@archseer archseer merged commit 0c6d25a into helix-editor:master Mar 8, 2023
@the-mikedavis the-mikedavis deleted the md-dynamic-picker-recalculate-column-widths branch March 8, 2023 02:01
sagnibak pushed a commit to sagnibak/helix that referenced this pull request Mar 21, 2023
…r#6004)

This fixes blank row text in a DynamicPicker which is initially given
no options. This can happen for language servers which respond to
the workspace symbol request for an empty query with an empty list
of symbols, and that behavior is somewhat common since returning all
symbols as the spec suggests is very expensive.

For empty options, `Picker::new` calculated the widths of each column
as 0. We can recalculate the column widths when the new options are
set to fix this. This refactor is also a good opportunity to formalize
setting new options on a picker: besides setting the new options and
calculating column widths we also want to reset the cursor and rescore
the options.
wes-adams pushed a commit to wes-adams/helix that referenced this pull request Jul 4, 2023
…r#6004)

This fixes blank row text in a DynamicPicker which is initially given
no options. This can happen for language servers which respond to
the workspace symbol request for an empty query with an empty list
of symbols, and that behavior is somewhat common since returning all
symbols as the spec suggests is very expensive.

For empty options, `Picker::new` calculated the widths of each column
as 0. We can recalculate the column widths when the new options are
set to fix this. This refactor is also a good opportunity to formalize
setting new options on a picker: besides setting the new options and
calculating column widths we also want to reset the cursor and rescore
the options.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-helix-term Area: Helix term improvements C-bug Category: This is a bug S-waiting-on-review Status: Awaiting review from a maintainer.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Left side of workspace symbol picker in gdscript is empty
5 participants