-
Notifications
You must be signed in to change notification settings - Fork 90
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
Ruby inline block conversion assumes conversion as hash #30
Comments
It really is difficult. The test for "starts with a word or )" should actually work, it doesn't seem like it's syntactically possible to have a hash there. I've just pushed a branch called Unfortunately, there's still an issue. Given the following example: this { block gets, horribly: broken } If you split while on the this do
block doesnt, get: mangled
end Which is correct. However, if you split with the cursor on this {
get: mangled,
} Which is the broken case. The question here is "where should you be when you're splitting?". For most use cases, the cursor needs to be "inside" the structure you're splitting -- inside the hash's curly braces, inside the string's quotes, etc. For some cases, I try to be a bit more loose. This is useful for ruby method options in particular: method_call one: 'two', three: 'four' It feels much more intuitive to split on If I'm to do this "right", then it would make sense to either require you to be in the area to split in both cases, or allow you to be on the method call in both cases. Both are kind of tricky to do, mostly due to complicated-ish logic. Which one do you think would make more sense? Do you have a different idea? For now, it would help if you switch to this branch and use it for a while, and report any regressions, just so I'm aware of any other limitations of this approach. I'll try to invest some effort next weekend, but it may take a while, I think it's about time to do some restructuring of the code anyway. |
I would think that most of us are inside the block when doing a join or split, so that would be the logical direction here. I'll switch to the branch and see if I run in to problems. |
Looks like everything works as planned. I it even manages to handle a difficult case of: let(:var) { { has: hash, elements: too } } |
Hmm, although this particular case seems wrong to me. It ends up as: let(:var) { {
has: hash,
elements: too,
} } That's probably because it splits the hash inside the block and not the block itself. This is still okay, but if the cursor is on the first let(:var) do
{ has: hash, elements: too, }
end I'll experiment. |
I've pushed some more commits to make hash/option splitting and block splitting work the same: only when in the actual structure. The example you gave above now works as I specified -- splits the block first, then the hash. What do you think about this? I know that a lot of people prefer |
As a side note, I'm going to have to take a second look at string splitting, it doesn't seem to work very well in some edge cases. Not sure if it's related to these changes or it was like that before, but it would be a good idea to debug while I'm at it. |
Yup, the example case I mentioned was split on the first If the code outside of the multiline hash is evaluated and handled, then the script is actually doing more than it should be doing. |
One way to fix this would be simply to merge the block and hash handling callback and take an informed decision based on the case. This shouldn't be too difficult to pull off and might be a good idea in general, due to how coupled these two pieces of logic are. That said, I'm not convinced I should make this change in functionality Consider this example: foo = { one: 'two', three: 'four' } if condition? When I split this line, regardless of where I am in it, I expect that the result is this: if condition?
foo = { one: 'two', three: 'four' }
end Afterwards, I can go down one line to the hash and split that one. What you're proposing is a general behaviour that goes like this: foo = {
one: 'two',
three: 'four'
} if condition? While this is syntactically valid, it's not very idiomatic. Not to mention I think the if-clause at the bottom impairs redability a lot, depending on how large the hash is, but that may be debatable. From what I'm getting, you're saying the plugin should always limit the effect on areas around the cursor, but that's not how it was built to work. It's meant to turn single-line code into multiline code. For a lot of cases, there are more or less clear priorities and the plugin attempts to split along those. The shorthand if-clause is one example of this. The only reason you would ever use it is if your line is short enough that it makes sense. If you want to split the line, it's likely due to it being too long and difficult to read. The suffix if-clause should always be the first to be transformed into a multiline The only reason that locality of the cursor is respected is due to the fact that, in some cases, you may have multiple non-intersecting segments that can be split. In that case, there are multiple reasonable ways to shorten the code and it would be inconvenient for the plugin to allow one, but not the others. Priorities don't help. With nesting, however, I don't think that's the case. First you split the outer part, then you split the inner. That's what I'd see as a logical series of steps towards reformatting the line. Forcing the plugin to always limit itself to the perfect definition around the cursor seems counter-productive. The What do you think? |
Hmm.. you are right that the use case here actually should look at the big picture. The only concern I'm having here is that if we try to make too many assumptions for the user, it's going to backfire, since not everyone wants to use the code the same way. One way of making the behavior controllable by the user, would be to allow visual blocks. That way the user could do |
True, and I think the only way is to stick to mostly idiomatic code and decide edge cases on a case-by-case basis. A few things also have options for code style, like curly braces, spacing between brackets and so on. Hopefully, if people use a coding style that's unsupported, they'd open an issue and I can decide whether it makes sense to support or not. If it's not supported, I guess it'll just have to be handled manually by users. Technically, they could even override the callbacks and write their own splitter/joiner, though this would require some vimscript knowledge.
That's a very interesting idea! If I could allow splitting within a visual block then edge cases would be much easier to handle. Even joining by visual mode might make sense in some weird cases. Unfortunately, I can't see a good implementation of this at the moment :/. Every split/join callback has a lot of power to investigate the buffer as it sees fit. Which is necessary, since there are checks for syntax (comments, strings) and uses of I do see one way of this working. Put the contents in a temporary, hidden buffer, perform a normal splitjoin on that, and then put it back. This may seem dirty, but it might just be crazy enough to work (I think this is how Gundo works, for instance). In any case, it shouldn't be difficult to try, so what the heck. I'll try to devote some time to the experiment these days. |
So, it's been a while. Does the The visual mode stuff seems quite doable, by the way. I just have to figure out a good way to reuse the code. Thanks for the idea :). |
I've been using |
Great, thanks. I've just merged it into master. I'll try to get to your other issue soonish. You can also watch issue #32 if you're interested in the visual mode logic. |
would it be possible to choose to keep the |
I think it's generally recommended not to use {...} for multiline blocks. That being said, recommendation doesn't mean that it shouldn't be possible. |
I understand your point, but I beg to differ:
|
Regardless of whether it's recommended or not, it probably won't be an issue to implement a setting for it. I'll take a look at it one of these days and see if I can add one. |
@fuadsaud I've just pushed a commit that adds a setting, let g:splitjoin_ruby_do_block_split = 0 Take a look at the documentation for more details. |
@AndrewRadev that's utter cool! works perfectly, thank you! |
If one tries to convert a single statement inline block into a multiline block, the conversion assumes the inline block is a hash.
Original:
After :SplitjoinSplit
It's not too easy to detect these, but one good idea would be to test if the {} is preceded with a word, then it's most likely a block. If there is a = or no word, then it's most likely a hash. I bet there are better ways to detect this, but I can't think of them at the moment.
The text was updated successfully, but these errors were encountered: