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

Feat: Sticky Context #6118

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

SoraTenshi
Copy link
Contributor

@SoraTenshi SoraTenshi commented Feb 27, 2023

!! If your preferred colorscheme / language is not yet in this PR, please feel free to open a PR on my branch: sticky-context to add those! It helps me quite a lot, as i can't keep track of every single colorscheme / language that helix supports !!

This is supposed to be the "successor PR" of #3944 .

Since @matoous has no time to pick up on it, i have started to continue on it (as i have also previously worked a bit on it!).

This is for now working, but with very rough edges and needs some fine adjustments.

Features, in no particular order:

  • Basic functionality
  • Max viewport height (limits the max. amount of contexts)
  • Use top of viewport instead of cursor pos
  • Do not stick contexts that are less than at least half the height of the viewport
  • Configurable tree-sitter nodes
  • Calculate precise viewport based on recent sticky nodes
  • Sticky context indicator, a la context.vim
  • Render Cursor over contextes
  • Adjusted Line number rendering
  • Configurable line limit for context
  • Collapsing function Arguments to include everything from name to the start of the first { or just "..." - this should be possible via the text api -> i would also strongly believe, that this will make the 'configuration of tree-sitter nodes' obsolete.
  • Add more tree-sitter queries
    • C, C++
    • Elixir
    • Go
    • Typescript ECMAScript
    • Nix
    • Rust
    • Zig
    • JSON
    • TOML
    • Markdown
    • YAML
    • HTML
    • Python (thank you, winged!)
    • Scala (thank you, jpaju!)
    • C# (thank you, vlad-anger!)
    • Odin
  • Add documentation on how to add more context queries
  • Update docs when finalized

----- Bug Smashing: ------

  • Fix bug where nodes jitter
  • Redo the context.end logic, work with parameter captures instead of from func decl to end, there should be a way capture the byte range of all the parameters.
  • Fix the "line shrinking" logic when the cursor gets on a sticky node
  • Improve overall calculation performance
  • Figure out a way to improve calculation performance if cache is empty (currently tanks too much)
  • Somewhere, cache invalidation is still not correct
  • In some situations, unnecessary many nodes are rendered
  • Somewhere there's a crash (can't repr though)

I beg anyone to find another bug as mentioned here, to immediately notify me, even if it's minor, i am happy to investigate it (also; if possible, create a reproducer)

----- Overview: ------

  • The nodes are rendered by the following rules:
    • The last node, if configured, is always the indicator
    • Prioritize closer nodes more than much further nodes (e.g. functions are more prioritized than e.g. impl of structs
  • of 1 tree-sitter node, always the 1st line is taken, even if the node is let's say 3 lines long.
  • The sticky context may not render at all when the viewport is too small. Yes i tried to keep it as dynamic as possible, but at some point it's getting too small
  • Eventually it would be very beneficial, if me or someone else in the future can make argument on multi-line function declarations collapseable (e.g.
fn render(
	i: i32,
	x: u32,
	y: usize,
	z: Option<void>,
) {

should then be collapsed to:
fn render(...) {

Small gif:
FancyWM_VdrUeBZJGN

closes #396

@SoraTenshi SoraTenshi force-pushed the sticky-context branch 4 times, most recently from 7ce93e9 to f1d26a6 Compare February 27, 2023 22:52
@SoraTenshi
Copy link
Contributor Author

here is a preview of how it looks like at the moment.
With the new changes, a lot of things became much easier than expected.

image

@SoraTenshi
Copy link
Contributor Author

SoraTenshi commented Mar 1, 2023

i think in order to satisfy clippys complaint, i would have to use the #[allow(clippy::too_many_arguments)] macro, i could of course just wrap one of the parameter in a tuple, but what's the point in it.

Maybe someone else got an idea how to get the render_sticky_context function down to a max of 7 Arguments.

@SoraTenshi SoraTenshi marked this pull request as ready for review March 2, 2023 17:29
@poliorcetics
Copy link
Contributor

i think in order to satisfy clippys complaint, i would have to use the #[allow(clippy::too_many_arguments)] macro, i could of course just wrap one of the parameter in a tuple, but what's the point in it.

Maybe someone else got an idea how to get the render_sticky_context function down to a max of 7 Arguments.

Don't worry too much about it, this one lint is helpful most of the time but it can't account for the context of the code, ignoring it is often ok (I'm on my phone so I won't review right now, I can't tell for your use case yet)

@archseer
Copy link
Member

archseer commented Mar 8, 2023

Note: the Neovim plugin this is based on is switching to queries for determining the nodes (nvim-treesitter/nvim-treesitter-context#198). We should do the same (similar to indents where we started with a toml config but now use proper queries)

@SoraTenshi
Copy link
Contributor Author

Note: the Neovim plugin this is based on is switching to queries for determining the nodes (nvim-treesitter/nvim-treesitter-context#198). We should do the same (similar to indents where we started with a toml config but now use proper queries)

Do i understand it correctly, that you'd want seperate injection queries (tree-sitter) for the context?

If so, i think i can do that.

@yerlaser
Copy link
Contributor

yerlaser commented Mar 8, 2023

I would advocate not to depend on tree-sitter on this feature. There are still many languages that don't have TS.
I use such languages and I often miss even simple things, like match pairs because it also depends on TS.
Please be considerate to us, poor people, who have to deal with multiple languages.
A simple word-split is more than enough.

@SoraTenshi
Copy link
Contributor Author

I would advocate not to depend on tree-sitter on this feature. There are still many languages that don't have TS. I use such languages and I often miss even simple things, like match pairs because it also depends on TS. Please be considerate to us, poor people, who have to deal with multiple languages. A simple word-split is more than enough.

in order for this feature to work without tree-sitter, i would have to manually parse scopes, which are VERY inconsistent throughout languages, therefore tree-sitter is, imo, the only way of doing this kind of properly.

You also could - of course - always create tree-sitter grammars as well as add languages to helix

@pascalkuthe
Copy link
Member

I would advocate not to depend on tree-sitter on this feature. There are still many languages that don't have TS. I use such languages and I often miss even simple things, like match pairs because it also depends on TS. Please be considerate to us, poor people, who have to deal with multiple languages. A simple word-split is more than enough.

Helix is primarily a TS based editor and languages, I think supporting plaintext files for some basic editing operations (like pair matching) can make sense but not for features that require semantic information (as this one does). The right fix is to create a TS grammar for those languages instead of adding language specific code into helix. Creating a TS grammar is not that hard and most mainstream languages do have one

@yerlaser
Copy link
Contributor

yerlaser commented Mar 8, 2023

OK. I see your point. Unfortunately, for people like DevOps or SysAdmins it still means opening lots of text files (scripts, configs etc.) in weird languages that will never have a TS.
Another case is markup languages like markdown. As far as I understand, even if a TS existed for it, an object would be the whole text block which is too large of a target to go to.

But, again, it's just my concern and wish. This feature is so needed that I would be happy if it works at least for the supported languages.

@pascalkuthe
Copy link
Member

pascalkuthe commented Mar 8, 2023

Helix has grammars for markup and configuration languages too (like markdown). Any file that has syntax highlighting in helix has a TS grammar. We even have TS grammars for filetypes like git-rebase, ini, wit, passwd, hosts,.. . If you are missing a TS grammar for something it should be easy enough to create one (and you would be surprised how much is already covered).

@erasin
Copy link
Contributor

erasin commented Mar 9, 2023

I tested this pr and it shows a bit strange in golang. I also support the use of tree-sitter queries, nvim-treesitter-context/queries provides a lot of language , we can use it, other languages can be added later.

@SoraTenshi
Copy link
Contributor Author

I tested this pr and it shows a bit strange in golang. I also support the use of tree-sitter queries, nvim-treesitter-context/queries provides a lot of language , we can use it, other languages can be added later.

What exactly looks strange?
Can you provide an example?

@erasin
Copy link
Contributor

erasin commented Mar 9, 2023

I have added the following configuration.

[[language]]
name = "go"
sticky-context-nodes = ["package_clause","type_declaration","method_declaration","function_declaration","for_statement","if_statement", "expression_switch_statement"]

I test with golang base library net/http/request.go.

Some times it is displayed correctly and some times it is not displayed.

@SoraTenshi
Copy link
Contributor Author

SoraTenshi commented Mar 9, 2023

sticky-context-nodes = ["package_clause","type_declaration","method_declaration","function_declaration","for_statement","if_statement", "expression_switch_statement"]

ahh maybe i know why.
I added that if a node occupies more than 1 half of the screen, it may not be sticked.

I will remove that, as it's an old artifact. Thanks for the finding! :)

@erasin
Copy link
Contributor

erasin commented Mar 10, 2023

When I have non-ascii in my code, the capture is incorrect. For example, the following insert method.

test file: https://gist.github.com/erasin/a15c4f250beff8c9f7e4aaeae4a1128c

2023-03-10.13.52.18.mov

I get a panic when using the mouse to scroll end of file. The error was not found in master.

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Char index out of bounds: char index 4184, Rope/RopeSlice char length 4173', /Users/erasin/.cargo/registry/src/github.com-1ecc6299db9ec823/ropey-1.6.0/src/slice.rs:379:41
stack backtrace:
   0:        0x109be68c6 - std::backtrace_rs::backtrace::libunwind::trace::h310cbd77a7d2ae59
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
   1:        0x109be68c6 - std::backtrace_rs::backtrace::trace_unsynchronized::h5768bae568840507
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:        0x109be68c6 - std::sys_common::backtrace::_print_fmt::hd104a205649a2ffb
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/sys_common/backtrace.rs:65:5
   3:        0x109be68c6 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h521420ec33f3769d
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/sys_common/backtrace.rs:44:22
   4:        0x109c08c6a - core::fmt::write::h694a0d7c23f57ada
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/core/src/fmt/mod.rs:1208:17
   5:        0x109bdfb9c - std::io::Write::write_fmt::h1920a3973ad439e5
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/io/mod.rs:1682:15
   6:        0x109be66aa - std::sys_common::backtrace::_print::h75582c4ed1a04abb
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/sys_common/backtrace.rs:47:5
   7:        0x109be66aa - std::sys_common::backtrace::print::hef1aa4dbdc07ee06
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/sys_common/backtrace.rs:34:9
   8:        0x109be88d3 - std::panicking::default_hook::{{closure}}::h529701a1070b4ce0
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/panicking.rs:267:22
   9:        0x109be8628 - std::panicking::default_hook::hfeeab2c667b2d7c2
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/panicking.rs:286:9
  10:        0x1083df5c1 - <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::h9afa8b8b4a6f4294
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/alloc/src/boxed.rs:2032:9
  11:        0x108406e1f - helix_term::application::Application::run::{{closure}}::{{closure}}::h59304607632a2a9a
                               at /Users/erasin/github/helix/helix-term/src/application.rs:1061:13
  12:        0x109be9027 - <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::h23ed9dbfdf16f482
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/alloc/src/boxed.rs:2032:9
  13:        0x109be9027 - std::panicking::rust_panic_with_hook::h1b5245192f90251d
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/panicking.rs:692:13
  14:        0x109be8dd4 - std::panicking::begin_panic_handler::{{closure}}::h3658f3a9566379d4
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/panicking.rs:579:13
  15:        0x109be6d68 - std::sys_common::backtrace::__rust_end_short_backtrace::h9e01645d962f8882
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/sys_common/backtrace.rs:137:18
  16:        0x109be8a9d - rust_begin_unwind
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/panicking.rs:575:5
  17:        0x109c4bee3 - core::panicking::panic_fmt::h0097ad8ec0b07517
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/core/src/panicking.rs:64:14
  18:        0x109c4c365 - core::result::unwrap_failed::h2a0ffdcdbffb9262
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/core/src/result.rs:1791:5
  19:        0x10964bc3a - core::result::Result<T,E>::unwrap::h76fa627ea2ccb7e6
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/core/src/result.rs:1113:23
-  20:        0x10870149f - ropey::slice::RopeSlice::char_to_line::h83b3a9f53cafd361
-                               at /Users/erasin/.cargo/registry/src/github.com-1ecc6299db9ec823/ropey-1.6.0/src/slice.rs:379:9
-  21:        0x1087b4dac - helix_term::ui::editor::EditorView::calculate_sticky_nodes::hd44adebca1ce03c2
-                               at /Users/erasin/github/helix/helix-term/src/ui/editor.rs:857:24
-  22:        0x1087b0298 - helix_term::ui::editor::EditorView::render_view::h801f2329103ac9f0
-                               at /Users/erasin/github/helix/helix-term/src/ui/editor.rs:191:17
-  23:        0x1087b9fa4 - <helix_term::ui::editor::EditorView as helix_term::compositor::Component>::render::h0d6ad5e880ce309a
-                               at /Users/erasin/github/helix/helix-term/src/ui/editor.rs:1604:13
-  24:        0x1087cb16e - helix_term::compositor::Compositor::render::h421b649aa5e8a5c7
-                               at /Users/erasin/github/helix/helix-term/src/compositor.rs:170:13
-  25:        0x108407ee7 - helix_term::application::Application::render::{{closure}}::h9128185baddbd711
-                               at /Users/erasin/github/helix/helix-term/src/application.rs:285:9
-  26:        0x108401061 - helix_term::application::Application::handle_terminal_events::{{closure}}::h452798700217d49a
-                               at /Users/erasin/github/helix/helix-term/src/application.rs:618:26
-  27:        0x1083ffbfe - helix_term::application::Application::event_loop_until_idle::{{closure}}::h8cc9ae38c69ea5ec
-                               at /Users/erasin/github/helix/helix-term/src/application.rs:326:55
-  28:        0x1083fd20c - helix_term::application::Application::event_loop::{{closure}}::hf15c5275827c0534
-                               at /Users/erasin/github/helix/helix-term/src/application.rs:302:57
-  29:        0x10840691d - helix_term::application::Application::run::{{closure}}::h64d788da4e75353b
-                               at /Users/erasin/github/helix/helix-term/src/application.rs:1064:38
-  30:        0x1083f5e1e - hx::main_impl::{{closure}}::h64babcb08100836d
-                               at /Users/erasin/github/helix/helix-term/src/main.rs:156:53
  31:        0x1083d659e - tokio::runtime::park::CachedParkThread::block_on::{{closure}}::h04680cd7055be189
                               at /Users/erasin/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.26.0/src/runtime/park.rs:283:63
  32:        0x1083d6403 - tokio::runtime::coop::with_budget::h3450751a913955ea
                               at /Users/erasin/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.26.0/src/runtime/coop.rs:107:5
  33:        0x1083d6403 - tokio::runtime::coop::budget::hfece1804ad294c58
                               at /Users/erasin/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.26.0/src/runtime/coop.rs:73:5
  34:        0x1083d6403 - tokio::runtime::park::CachedParkThread::block_on::h50891113bf07b160
                               at /Users/erasin/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.26.0/src/runtime/park.rs:283:31
  35:        0x1083ed336 - tokio::runtime::context::BlockingRegionGuard::block_on::h97a7cfd8b0f5191b
                               at /Users/erasin/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.26.0/src/runtime/context.rs:315:13
  36:        0x1083b9bd5 - tokio::runtime::scheduler::multi_thread::MultiThread::block_on::h6a41409b5c3a1748
                               at /Users/erasin/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.26.0/src/runtime/scheduler/multi_thread/mod.rs:66:9
  37:        0x108417cfb - tokio::runtime::runtime::Runtime::block_on::h72dfd34556937174
                               at /Users/erasin/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.26.0/src/runtime/runtime.rs:304:45
  38:        0x10840905e - hx::main_impl::h594c06858aac3bd2
                               at /Users/erasin/github/helix/helix-term/src/main.rs:158:5
  39:        0x108408f01 - hx::main::hbd7e18d2aacb3ddc
                               at /Users/erasin/github/helix/helix-term/src/main.rs:38:21
  40:        0x108409f7e - core::ops::function::FnOnce::call_once::h81bdc8e78b625ab3
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/core/src/ops/function.rs:507:5
  41:        0x1083df8a1 - std::sys_common::backtrace::__rust_begin_short_backtrace::h582282e1d3fcd9fa
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/sys_common/backtrace.rs:121:18
  42:        0x1083e5d64 - std::rt::lang_start::{{closure}}::h8919f335f7d65c4f
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/rt.rs:166:18
  43:        0x109bd9a24 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h2302f1d25ef2ca9b
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/core/src/ops/function.rs:606:13
  44:        0x109bd9a24 - std::panicking::try::do_call::h6695e32a593de2cc
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/panicking.rs:483:40
  45:        0x109bd9a24 - std::panicking::try::hd4a93095627721a9
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/panicking.rs:447:19
  46:        0x109bd9a24 - std::panic::catch_unwind::he41b3dba63feca94
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/panic.rs:137:14
  47:        0x109bd9a24 - std::rt::lang_start_internal::{{closure}}::hbf45583011495a61
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/rt.rs:148:48
  48:        0x109bd9a24 - std::panicking::try::do_call::ha3e6b3edab7da449
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/panicking.rs:483:40
  49:        0x109bd9a24 - std::panicking::try::hd4e0f354bf7022b9
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/panicking.rs:447:19
  50:        0x109bd9a24 - std::panic::catch_unwind::h1035b163871a4269
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/panic.rs:137:14
  51:        0x109bd9a24 - std::rt::lang_start_internal::hd56d2fa7efb2dd60
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/rt.rs:148:20
  52:        0x1083e5d37 - std::rt::lang_start::h2981ed93936c2adf
                               at /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/std/src/rt.rs:165:17
  53:        0x1084090e8 - _main
  54:     0x7ff816549310 - <unknown>

@archseer
Copy link
Member

Do i understand it correctly, that you'd want seperate injection queries (tree-sitter) for the context?

Yes, we should reuse the nvim-treesitter format for these queries too:

https://github.com/nvim-treesitter/nvim-treesitter-context/blob/master/queries/go/context.scm
https://github.com/nvim-treesitter/nvim-treesitter-context/blob/master/queries/rust/context.scm

This ways they are shareable across editors.

@archseer
Copy link
Member

@yerlaser We leverage tree-sitter because it makes the implementation of various features easier and more performant. We'll sometimes implement fallbacks though, for example matchbrackets is getting one: #4288

@SoraTenshi
Copy link
Contributor Author

SoraTenshi commented Mar 10, 2023

Do i understand it correctly, that you'd want seperate injection queries (tree-sitter) for the context?

Yes, we should reuse the nvim-treesitter format for these queries too:

nvim-treesitter/nvim-treesitter-context@master/queries/go/context.scm nvim-treesitter/nvim-treesitter-context@master/queries/rust/context.scm

This ways they are shareable across editors.

Ok, have started working on it, and will continue these days.

@SoraTenshi SoraTenshi marked this pull request as draft March 10, 2023 21:43
Comment on lines 936 to 945
.take(max_nodes_amount)
.rev()
.enumerate()
.take_while(|(i, _)| *i + 1 != visual_cursor_pos as usize) // also only nodes that don't overlap with the visual cursor position
.map(|(i, node)| {
let mut new_node = node;
new_node.visual_line = i as u16;
new_node
})
.collect();
Copy link
Contributor

Choose a reason for hiding this comment

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

This will take max_node_amount and then remove elements again if they overlap, is that intended ?

The version below avoids one Vec allocation but I'm not convinced it would be faster, how big are you expecting context to be most of the time ?

context.reverse();
if context.len() > max_node_amount {
    // only take the nodes until 1 / 3 of the viewport is reached or the maximum amount of sticky nodes
    context.drain(max_node_amount..);
}
let mut idx = 0;
let mut overlap_reached = 1 == visual_cursor_pos;
context.retain_mut(|node| {
    if overlap_reached { return false; }
    overlap_reached = idx + 1 == visual_cursor_pos;
    node.visual_line = idx;
    idx += 1;
    true
});

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i would say that it will mostly sit around 3~5 nodes.
So i think performance there is not really that big of a deal, i would much rather avoid more of the text.x_to_y calls, as they're rather heavy. O(log n)

@SoraTenshi
Copy link
Contributor Author

@poliorcetics i appreciate that you already di a new review, but I wasn't finished ^^`

@daedroza
Copy link
Contributor

I'm able to crash helix after cherry-picking your patch. Without it, not happening. More surprised to find it after couple of days.

To reproduce: Sync with latest HEAD, cherry-pick your patch. Now, go to commands.rs -> func global_search.

Check the FileImpl struct, it's used inside PickerColumn::new("path"), inside it, type "item.", LSP will give pop-up with possible contents, use ctrl+n to navigate, helix crashes. Sometimes it doesn't happen when list returned by LSP is small.

thread 'main' panicked at helix-core/src/transaction.rs:483:9:
Positions [(76455, Before)] are out of range for changeset len 0!
stack backtrace:
   0:     0x5588a0492941 - std::backtrace_rs::backtrace::libunwind::trace::h67a838aed1f4d6ec
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
   1:     0x5588a0492941 - std::backtrace_rs::backtrace::trace_unsynchronized::h1d1786bb1962baf8
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:     0x5588a0492941 - std::sys_common::backtrace::_print_fmt::h5a0b1f807a002d23
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/sys_common/backtrace.rs:67:5
   3:     0x5588a0492941 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hf84ab6ad0b91784c
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/sys_common/backtrace.rs:44:22
   4:     0x55889f70a41c - core::fmt::rt::Argument::fmt::h28f463bd1fdabed5
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/core/src/fmt/rt.rs:138:9
   5:     0x55889f70a41c - core::fmt::write::ha37c23b175e921b3
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/core/src/fmt/mod.rs:1114:21
   6:     0x5588a048e67e - std::io::Write::write_fmt::haa1b000741bcbbe1
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/io/mod.rs:1763:15
   7:     0x5588a0492724 - std::sys_common::backtrace::_print::h1ff1030b04dfb157
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/sys_common/backtrace.rs:47:5
   8:     0x5588a0492724 - std::sys_common::backtrace::print::hb982056c6f29541c
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/sys_common/backtrace.rs:34:9
   9:     0x5588a0494463 - std::panicking::default_hook::{{closure}}::h11f92f82c62fbd68
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/panicking.rs:272:22
  10:     0x5588a04941a1 - std::panicking::default_hook::hb8810fe276772c66
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/panicking.rs:292:9
  11:     0x5588a0494aa4 - <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::h87b887549356728a
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/alloc/src/boxed.rs:2021:9
  12:     0x5588a0494aa4 - std::panicking::rust_panic_with_hook::hd2f0efd2fec86cb0
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/panicking.rs:735:13
  13:     0x5588a049484e - std::panicking::begin_panic_handler::{{closure}}::h3651b7fc4f61d784
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/panicking.rs:609:13
  14:     0x5588a0492e16 - std::sys_common::backtrace::__rust_end_short_backtrace::hbc468e4b98c7ae04
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/sys_common/backtrace.rs:170:18
  15:     0x5588a04945f2 - rust_begin_unwind
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/panicking.rs:597:5
  16:     0x55889f60b075 - core::panicking::panic_fmt::h979245e2fdb2fabd
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/core/src/panicking.rs:72:14
  17:     0x55889f96ccd2 - helix_core::transaction::ChangeSet::map_pos::h185a135121695d96
  18:     0x5588a0144d74 - helix_view::document::Document::apply_impl::he3dbc108b089fbf4
  19:     0x5588a0145c4d - helix_view::document::Document::apply_inner::hd5e0207144c735d8
  20:     0x5588a0146d37 - helix_view::document::Document::restore::h198dc87bb508cb11
  21:     0x55889fd85bd4 - helix_term::ui::completion::Completion::new::{{closure}}::h93fe366c0497f9dc
  22:     0x55889fd8717c - <helix_term::ui::menu::Menu<T> as helix_term::compositor::Component>::handle_event::hc4b743199effcda7
  23:     0x55889fd88b2a - <helix_term::ui::popup::Popup<T> as helix_term::compositor::Component>::handle_event::hf864c56a9aaca176
  24:     0x55889fc0f29f - <helix_term::ui::editor::EditorView as helix_term::compositor::Component>::handle_event::hc69b897456c376a7
  25:     0x55889ffd0687 - helix_term::compositor::Compositor::handle_event::h8a114ed2e687c604
  26:     0x5588a020510e - helix_term::application::Application::run::{{closure}}::h81ab288da8aae327
  27:     0x5588a0219ffd - tokio::runtime::park::CachedParkThread::block_on::hc1cfc561026a53d0
  28:     0x5588a028b1c1 - hx::main::hb6cc1e3d50208dab
  29:     0x5588a024e1d3 - std::sys_common::backtrace::__rust_begin_short_backtrace::hda36e2bdb83022c9
  30:     0x5588a024bbed - std::rt::lang_start::{{closure}}::h9bb6a1e29b730ad2
  31:     0x5588a048648f - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::hf9057cfaeeb252e2
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/core/src/ops/function.rs:284:13
  32:     0x5588a048648f - std::panicking::try::do_call::h629e203a624883e4
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/panicking.rs:504:40
  33:     0x5588a048648f - std::panicking::try::h7b61614724d6a4f1
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/panicking.rs:468:19
  34:     0x5588a048648f - std::panic::catch_unwind::h354ac1c0268491d8
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/panic.rs:142:14
  35:     0x5588a048648f - std::rt::lang_start_internal::{{closure}}::h919fee3c5ba8f617
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/rt.rs:148:48
  36:     0x5588a048648f - std::panicking::try::do_call::h54583f67455bff32
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/panicking.rs:504:40
  37:     0x5588a048648f - std::panicking::try::hb0e12c4e01d39dc2
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/panicking.rs:468:19
  38:     0x5588a048648f - std::panic::catch_unwind::h367b6339e3ca9a3b
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/panic.rs:142:14
  39:     0x5588a048648f - std::rt::lang_start_internal::ha5ce8533eaa0fda8
                               at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/rt.rs:148:20
  40:     0x5588a028b815 - main
  41:     0x780867029d90 - __libc_start_call_main
                               at ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
  42:     0x780867029e40 - __libc_start_main_impl
                               at ./csu/../csu/libc-start.c:392:3
  43:     0x55889f687305 - _start
  44:                0x0 - <unknown>

@SoraTenshi SoraTenshi force-pushed the sticky-context branch 2 times, most recently from 18a63ef to 8ad3a03 Compare July 27, 2024 17:34
@SoraTenshi
Copy link
Contributor Author

I'm able to crash helix after cherry-picking your patch. Without it, not happening. More surprised to find it after couple of days.

To reproduce: Sync with latest HEAD, cherry-pick your patch. Now, go to commands.rs -> func global_search.

Check the FileImpl struct, it's used inside PickerColumn::new("path"), inside it, type "item.", LSP will give pop-up with possible contents, use ctrl+n to navigate, helix crashes. Sometimes it doesn't happen when list returned by LSP is small.

snip

based on the backtrace and what you describe i can safely assume this doesn't seem to be an issue of this pr, and it's most likely fixed here: #11266

This has been fixed with the latest rebase.

@SoraTenshi SoraTenshi force-pushed the sticky-context branch 2 times, most recently from 18555e7 to ea3ac71 Compare September 6, 2024 02:20
A lot more work has been put into this and those were 116 commits up to
this point.
I decided to squash all of them so that i will have an easier time
rebasing in the future.
@hadronized
Copy link
Contributor

That looks amazing and I’ve been missing that feature since my move away from context.vim years ago. I hope it can get merged sooner or later!

@SoraTenshi
Copy link
Contributor Author

That looks amazing and I’ve been missing that feature since my move away from context.vim years ago. I hope it can get merged sooner or later!

Thank you!
It still has quite a bit of rough edges, but i am getting to a point that makes me kind of unable to fix all of those rough edges properly.
It still needs quite a bit of testing as well as quite a bit of bug fixing.
At least the performance is pretty good as of right now, unfortunately tree-sitter seems a bit slow on really big files.

@luisdavim
Copy link

How severe and how often are the known issues occurring? Would it be on to merge with the feature toggled off by default and work on them separately?

@SoraTenshi
Copy link
Contributor Author

SoraTenshi commented Oct 31, 2024

How severe and how often are the known issues occurring? Would it be on to merge with the feature toggled off by default and work on them separately?

quite frequently. They're not really severe, but also not perfect.
I have quite a bit of a cache invalidation problem, which will eventually lead me to rewrite some of the caching logic.
basically the bugs are:

  • Sometimes there are duplicate nodes (i guess that's a caching problem)
  • Some of the nodes are incorrectly taken as "valid" even though they are visible in the current screen

On another node, i am not sure how this PR will continue. I suspect that it could make much more sense to make it a plugin instead (once the plugin support is finished)

@luccahuguet
Copy link

How severe and how often are the known issues occurring? Would it be on to merge with the feature toggled off by default and work on them separately?

quite frequently. They're not really severe, but also not perfect. I have quite a bit of a cache invalidation problem, which will eventually lead me to rewrite some of the caching logic. basically the bugs are:

  • Sometimes there are duplicate nodes (i guess that's a caching problem)
  • Some of the nodes are incorrectly taken as "valid" even though they are visible in the current screen

On another node, i am not sure how this PR will continue. I suspect that it could make much more sense to make it a plugin instead (once the plugin support is finished)

I believe this belongs in core. I am eager to hear a maintainer's opinion on this

Thank you for doing this

nikvoid added a commit to nikvoid/helix that referenced this pull request Dec 28, 2024
@robinvd
Copy link
Contributor

robinvd commented Dec 30, 2024

Works quite well! not sure if these have already been reported, but ive noticed two things, im on this branch but with git pull origin master

  • the gutter line number is updated later then the header itself
  • the header will stay one line too long (see screenshot) when going up, you can trigger it with just going up using zk until one above the header

image

EDIT:

  • opening the same buffer in 2 splits at around the same point, and scrolling in one, will results in changes in the other split

rockboynton pushed a commit to rockboynton/helix that referenced this pull request Jan 2, 2025
`patchy` is a tool which makes it easy to declaratively manage personal forks by automatically merging pull requests.

Check it out here: https://github.com/NikitaRevenco/patchy
@daedroza
Copy link
Contributor

daedroza commented Feb 12, 2025

@SoraTenshi : Can you please tell me how to write context queries?
image

The above (class_declaration) @Cotnext incorrectly renders the annotation "@" instead of the class className. Is there a away where I can precisely say the context to render which line?

@SoraTenshi
Copy link
Contributor Author

@SoraTenshi : Can you please tell me how to write context queries? image

The above (class_declaration) @Cotnext incorrectly renders the annotation "@" instead of the class className. Is there a away where I can precisely say the context to render which line?

https://github.com/helix-editor/helix/blob/9a7c4396daba98b9b45e525091de488100f783bb/book/src/guides/context.md

How to generally write context queries is basically re-building the TreeSitter AST that you want to match. Examples can be found in this PR, and helix has great tooling in how this works:
e.g. :tree-sitter-subtree

@marcosps
Copy link

@SoraTenshi : Can you please tell me how to write context queries? image
The above (class_declaration) @Cotnext incorrectly renders the annotation "@" instead of the class className. Is there a away where I can precisely say the context to render which line?

https://github.com/helix-editor/helix/blob/9a7c4396daba98b9b45e525091de488100f783bb/book/src/guides/context.md

How to generally write context queries is basically re-building the TreeSitter AST that you want to match. Examples can be found in this PR, and helix has great tooling in how this works: e.g. :tree-sitter-subtree

I just compiled the source code as instructed by https://docs.helix-editor.com/building-from-source.html, pointed the new runtime, and everything seems correct (it even loads my theme corectly), but I can't see any sticky context. Do I need to enable anything on the config file to see it? (i've checked this PR and I couldn't find anything).

I've used C and Python with clangd and pylsp respectively. Thanks a lot for working on it!

@thomasaarholt
Copy link
Contributor

@marcosps it's mentioned in the book/src/editor.md file changed in this PR. It definitely should have been spelt out in the top post :D

[editor.sticky-context] Section

Option for sticky context, which is a feature that puts bigger blocks of code
e.g. Functions to the top of the viewport

Key Description Default
enable Display context of current line if outside the view false
indicator Display an additional line to indicate what part of the view is the sticky context false
max-lines The maximum number of lines to be shown as sticky context. 0 = 1/3 of the viewports height 0
Example:
[editor.sticky-context]
enable = true
indicator = true
max-lines = 10

@marcosps
Copy link

@marcosps it's mentioned in the book/src/editor.md file changed in this PR. It definitely should have been spelt out in the top post :D

[editor.sticky-context] Section

Option for sticky context, which is a feature that puts bigger blocks of code e.g. Functions to the top of the viewport

Key Description Default
enable Display context of current line if outside the view false
indicator Display an additional line to indicate what part of the view is the sticky context false
max-lines The maximum number of lines to be shown as sticky context. 0 = 1/3 of the viewports height 0
Example:

[editor.sticky-context]
enable = true
indicator = true
max-lines = 10

Thanks a lot @thomasaarholt ! I can confirm that it works most of the time while reading linux kernel source code (sometimes it doesn't show the function/struct), and it also happens to python. But it's better than nothing :)

Thanks a lot @SoraTenshi for working on it! Do you have plans to keep working on it and maybe merge it somehow? :) (I saw some comments stating that maybe it should be a plugin, but the current status of the feature is practically finished)

@SoraTenshi
Copy link
Contributor Author

Thanks a lot @SoraTenshi for working on it! Do you have plans to keep working on it and maybe merge it somehow? :) (I saw some comments stating that maybe it should be a plugin, but the current status of the feature is practically finished)

I am not sure how i will proceed with this pr.
I am not yet sure whether this feature is even subject to be in helix core + working on it for quite some time has me sort of burned out, considering that i personally can live with those bugs, it's right now not a priority to fix.
And if this won't ever happen to be merged in core, it's a bit rough for me justifying working on it much more, however i will keep the current state updated.
Making this feature more polished is also a non trivial task, considering how "smart" i want it to be, there's a lot more unpolished rough edges that you might never see but that i am aware of :)

Considering that, i don't know. I am still very active though and will accept any PR that lands for this PR to become more stable.
So if anyone is willing to continue working on it, most of the code can be found in context.rs.
Also if anyone wants to work on it and has questions, my email is public in which i probably respond in <1 Day :)

@tsujp
Copy link

tsujp commented Feb 19, 2025

working on it for quite some time has me sort of burned out, considering that i personally can live with those bugs

In the past I've pushed myself through early burnout warning signs and feelings and the result is almost always the same: more burnout, maybe the point where I want nothing to do with the thing in question for weeks or months.

I'd highly suggest you take a break while you're only on the "sort of burned out" stage. You've put in a great deal of commendable effort over an extended period of time, allow your mind and your feelings to recover from all the work they've been doing!

:)

@luccahuguet
Copy link

If there are smaller PRs you can make to core that make this one easier to merge, that could be a good strategy, and less tiring

but yeah, what tsujp said above about burnout should come first, I agree

@marcosps
Copy link

Thanks a lot @SoraTenshi for working on it! Do you have plans to keep working on it and maybe merge it somehow? :) (I saw some comments stating that maybe it should be a plugin, but the current status of the feature is practically finished)

I am not sure how i will proceed with this pr. I am not yet sure whether this feature is even subject to be in helix core + working on it for quite some time has me sort of burned out, considering that i personally can live with those bugs, it's right now not a priority to fix. And if this won't ever happen to be merged in core, it's a bit rough for me justifying working on it much more, however i will keep the current state updated. Making this feature more polished is also a non trivial task, considering how "smart" i want it to be, there's a lot more unpolished rough edges that you might never see but that i am aware of :)

Considering that, i don't know. I am still very active though and will accept any PR that lands for this PR to become more stable. So if anyone is willing to continue working on it, most of the code can be found in context.rs. Also if anyone wants to work on it and has questions, my email is public in which i probably respond in <1 Day :)

Of course your health should come first! Thanks a lot for working on it until this point! The feature itself is already working fine for me, so IMHO this could be merged as it is :)

@SoraTenshi
Copy link
Contributor Author

Of course your health should come first! Thanks a lot for working on it until this point! The feature itself is already working fine for me, so IMHO this could be merged as it is :)

Oh to everyone, I didn't mean in a literal sense that this PR got me burned out but more in a sense that the future of it is uncertain hence why I don't want to spend much more time on it. If anyone of the core team would give their approval, I would pick up work again. But I don't wanna see my polishing efforts go to waste just because it may as well be a plugin. (Which I might also would work on considering I am heavily in favor of scheme)
As it is right now, there's absolutely and should absolutely no way of this being merged as is, it's waaaaaay to unpolished for helix' standards.

@marcosps
Copy link

Of course your health should come first! Thanks a lot for working on it until this point! The feature itself is already working fine for me, so IMHO this could be merged as it is :)

Oh to everyone, I didn't mean in a literal sense that this PR got me burned out but more in a sense that the future of it is uncertain hence why I don't want to spend much more time on it. If anyone of the core team would give their approval, I would pick up work again. But I don't wanna see my polishing efforts go to waste just because it may as well be a plugin. (Which I might also would work on considering I am heavily in favor of scheme) As it is right now, there's absolutely and should absolutely no way of this being merged as is, it's waaaaaay to unpolished for helix' standards.

Makes sense. @archseer @pascalkuthe what do you think about it? :)

@marcosps
Copy link

Of course your health should come first! Thanks a lot for working on it until this point! The feature itself is already working fine for me, so IMHO this could be merged as it is :)

Oh to everyone, I didn't mean in a literal sense that this PR got me burned out but more in a sense that the future of it is uncertain hence why I don't want to spend much more time on it. If anyone of the core team would give their approval, I would pick up work again. But I don't wanna see my polishing efforts go to waste just because it may as well be a plugin. (Which I might also would work on considering I am heavily in favor of scheme) As it is right now, there's absolutely and should absolutely no way of this being merged as is, it's waaaaaay to unpolished for helix' standards.

Makes sense. @archseer @pascalkuthe what do you think about it? :)

Maybe @the-mikedavis is interesting on it, or knows somebody that can decide of which direction this should go :)

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-enhancement Category: Improvements
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Show the context of the currently visible buffer contents à la context.vim