-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Fix YAML auto indent #6768
Fix YAML auto indent #6768
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not an expert on ident queries but this seems good to me Really awesome that you added a bunch of tests. This doesn't just test the YAML queries but also adds some more testing for the indent system in general which could use more 👍
177bf71
to
f4a043d
Compare
Yeah this actually took me a few days of just digging around in the indent code to figure out how it even works and where the captures are supposed to go, and what they are supposed to cover. I was convinced there was some kind of bug and added a whole bunch of debug prints, and then figured out the hard way how it works. It seems needlessly complex, but I don't say that with a high level of confidence. Maybe I should go over the docs now that I'm not completely clueless about how it works. |
@pascalkuthe sorry, I added some more tests for inserting above, and also for flow style strings. |
Actually I just discovered another broken case: lists of maps |
Ok, I'm thinking actually there will need to be a code change to fix this. Consider this really simple case, where the - top:|
baz: foo
bax: foox I think I have an ok enough understanding now of the indent system to say with reasonable confidence that this set of indent queries should cover what we want. (block_scalar) @indent @extend
(block_mapping_pair) @indent
(block_sequence_item) @indent The last two cover the two indent cases we want: one level for the list, and one for the mapping pair. The problem is the current code will intentionally combine all helix/helix-core/src/indent.rs Line 682 in 8839eb0
So we end up with - top:
|
baz: foo
bax: foox I assume this was meant to cover giving the ability to have multiple overlapping patterns without them stepping on each other's toes. But in this case, the sequence and the mapping pair simultaneously both happen on the same line, and both introduce a new level of indentation. I think maybe what we need is a capture group that will always add a new indent level, even if multiple of them happen on the same line. Maybe it could be called |
The indent code is not really my forte but sounds reasonable to me cc @Triton171 since he did a lot of work on indent queries |
I agree that this needs a new capture type since currently indent can only ever increase by 1 from one line to the next. And you're right, this behavior is needed since in most languages e.g. multiple nested blocks starting on the same line only increase indent by 1. The indent code can probably also be simplified a bit: For example, we could remove the |
Thanks @Triton171 , glad to see I'm on the right track. I have some feedback for the docs, I just have to write it up and/or might just update it myself, since I will need to add the new capture type to the docs anyway. |
cd54baa
to
827c581
Compare
Ok, I think I got the code changes done. I added the new
At this point, I think I just need to update the docs. |
827c581
to
6e53293
Compare
Let's get @Triton171's review here too (Edit: Ah sorry, just read the rest of the thread!) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I jkticed that one-line?
checks if a capture is contained on a single line after the new line break is inerted. I think that makes sense but just to make sure: Is that intentuonal? If yes then that should probably be documented
Great comments Pascal, thanks for the review! |
Also, yes, it's intentional that foo: #[|bar]# and you hit return, it would only query the current state of the text, determine that it's one line, and not indent as it should. Actually, this would be a good regression test. I will document this for sure. |
Most of this looks good to me, it's also very nice to get some integration testing for the indent code. There's 2 things which I'm unsure about: (1): Changing the indent position to the character before the line feed is probably not always what we want. For example it breaks indentation in this C code: int main() {
if (cond)
do_smth(); // Pressing `o` here would add a line with 2 indent levels (1 too many)
} This is a fundamental difference between languages where trailing whitespace should be considered to be part of a node and languages where this is not the case. Instead of changing the position of indent computation, we can instead use (2): I would expect the For example, if we encounter (from innermost to outermost node)
Is there some reason why we need this more complex behavior? It seems like it makes the indentation logic significantly harder to reason about, because now the order in which captures are encountered matters, even if they all apply to the same line. |
@Triton171 Thanks for the review!
Shoot you're right. It's actually worse than this: it doesn't indent at all. Nor does it indent when inserting a new line from the function declaration. I'll look into the
Hm, I actually tried this at first, just changing the Do you have any suggestions? And also, out of genuine ignorance, is having indent and outdent captures on the same line a thing that happens? |
@Triton171 you were right, simply adding |
I think a single additional (signed) field should also be enough, since |
628b689
to
f28077d
Compare
Ok this has to be the weirdest thing I've ever seen in Rust. I changed f28077d#diff-44db3a32fdd620ed51f6953534c6ed5df3d2966010cc86aaf13448e9bbb65f07R264 But this inexplicably causes indentation to break in some cases. The only places this function is used is within calculating the indent level here: helix/helix-core/src/indent.rs Line 658 in 29638ba
We can see the reference returned is not used. But that ... should be fine, shouldn't it? How on Earth is this changing the result? Anyway, I added the two new fields for tracking always captures, and added unit tests to verify the associativity. The tests are uglier than I would like because of the above, but they work now. I opted for two separate fields because in my mind it's a bit more confusing to have one field be a count and one be a signed delta. |
d0d4b9b
to
252aaa0
Compare
@Triton171 if you get some time, I would appreciate a review. ❤️ I think these implementation details will affect the docs, so I want to wait on code review before I spend time updating docs. |
252aaa0
to
ff74147
Compare
Sorry for taking some time with the review, I had a busy few days. Apart from the 2 small things I pointed out above, all of this looks very good. Once those are resolved and the docs are updated, this can be merged in my opinion.
I agree, and it also has the advantage that we can always use
I looked at the diff in which you reverted that change and I don't understand either how this can change the behavior of indent queries. Since it only makes the testing code slightly cleaner, I guess it's not really worth the time to debug why this happens. |
Thanks so much for the review @Triton171 ! I'll go ahead and work on the docs then. |
ff74147
to
219033f
Compare
Just checking in, I am still going to finish this, it's just been a busy couple weeks |
a52b9ce
to
e4dc151
Compare
Ok, I've finished going over the docs. I added a bunch of examples that should hopefully help newcomers understand how everything works. These are details I found myself sorely missing when I was trying to put together how to make indent queries. I think this pretty much wraps up the PR. It is fully ready for review. |
e4dc151
to
ff23aea
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks reall great. The docs are really nice!
YAML indents queries are tweaked to fix auto indent behavior. A new capture type `indent.always` is introduced to address use cases where combining indent captures on a single line is desired. Fixes helix-editor#6661
ff23aea
to
f16369c
Compare
Ah, thanks, I fixed it. |
This makes use of the new
extend
capture to correct YAML indentation.Fixes #6661