-
Notifications
You must be signed in to change notification settings - Fork 347
Indentation has been spoiled #782
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
Comments
Sometimes it's 2nd column, not 4th. |
It should stay at column zero. This is a bug.
Are you able to add a test case in `tests/haskell-indentation-tests.el` so
that we make sure this works as expected?
|
Do you know which version have you been using before? I tried to revert some recent commits and I see no change in bahvior. |
@gracjan, I haven't done Haskell for some time, maybe a couple of months, so I cannot tell you. Also, unfortunately I cannot help you with the tests, at least not right now. |
Thanks for help. We will manage somehow.
|
This happens when haskell-indent-mode is enabled. In contrast, when haskell-indentation-mode is enabled, |
So which mode should one use |
@gracjan, One more thing: does it make sense to enable indentation machinery automatically, just like all other language-specific modes do? |
That is the goal, to make haskell-indentation-mode the default and the only. Sadly, none of the indentation modes work as advertised so people learned to live with their limitations. haskell-indentation-mode requires a lot more work to be able to subsume everything else. |
@gracjan, I have to admit that I've tried both the modes without success. Now I'm using I'm not trying to say that your work is bad, I would rather thank you for your work on this project, but I'm using almost exclusively open-source/free software at home and work and this package is most unstable thing I've ever seen. You probably need more people, but unfortunately I cannot help you right now, because I'm already busy and my free time is consumed by another open source effort. |
Sad state of indentation is known and it is our top priority. We need help there as you noticed. Having said that haskell-indent-mode has not been touched for months and all work goes into haskell-indentation-mode. |
@gracjan, OK, enough is enough. Describe me briefly what should I tweak/know to fix this |
OK, I've started reading the code on my own. You have various nasty things there.
I will soon open a pull request with cosmetic corrections. I have not yet analyzed the code and its design because I'm too tired right now. |
Your work is appreciated and needed. Keep the good stuff coming.
|
@gracjan, Why don't you run tests on every commit with Travis CI? How do you run tests at all, I don't see |
@gracjan, your As it currently implemented, you cannot place point in arbitrary context, it's always placed for you at the end of testing text. This is unacceptable. We should be able to specify exact position of point. Better yet, it should be possible to specify several positions for point with corresponding expected "indentations". Better yet, this should be parametrized over variables like Doc-string for First, you should tell me preferable way to run tests. Second, you should tell Travis CI to run tests on every commit. This is a must for project of this size. Fixing of all the stuff will take time. Given all that hacking I fear major changes may be needed to make it work decently. |
What do these variables mean? What DYN stands for? (defvar haskell-indentation-dyn-first-position)
(defvar haskell-indentation-dyn-last-direction)
(defvar haskell-indentation-dyn-last-indentations) |
@gracjan, what about |
I've written more powerful helper to test indentations. It shows that |
Now it's possible to write more dense tests: (ert-deftest haskell-indentation-check-3 ()
"Import statememnt symbol list 1."
(haskell-indentation-check
"
import Control.Concurrent
( forkIO,
killThread )"
'((1 0) 0)
'((2 0) 0)
'((3 0) 0 2)
'((4 0) 4)
'((5 0) 0))) This exposes bug that I described in this issue. For cursor position |
@mrkkrp: lots of comments, let me address one by one.
|
And note about |
@gracjan, I will try to use those 'explainers' to improve my current testing helper. Many more tests will fail with such detailed tests in place. |
@gracjan, should position in current line (column) affect results of |
This is indent LINE function so it should work on whole LINES. Position within line should not matter. (Same with indent REGION: position within region should not matter). |
Well, my question was about About Travis CI testing: sorry, I've missed that you do it in your makefile, I should have checked it better. |
It may be better to use external parsing library which is tested, robust, and neat. We could then define necessary stuff using combinators from that library. This will eliminate bugs and make maintaining of the I need to understand how entire This is what I've found: https://github.com/skeeto/rdp. It may be not powerful enough, though. |
I have been thinking to rewrite the parser. The main problem is handling the layout rule correctly. For example, when an illegal token is encountered, the current layout context should be left, and parsing should resume in the outer context. When using an external parser, these rules should be handled correctly. |
@kuribas, Could you please describe how it currently works? Where is starting point of all that parsing business. What your parser returns, how its result is used to calculate indentation positions? All I can see is quite hairy and mostly not documented, so I'm having hard time understanding this. Every function seems to get dirty right away messing with all possible things. |
@kuribas, you probably don't re-parse entire file every time, so how do you determine which part of file should be parsed? Do you extract string from buffer and then work with that? |
Parsing starts from the first line before point with zero indendation. Parsing is done just by walking over the buffer. Basicly, the read-next-token, etc functions handle the tokenization, and also the layout-rule (using special tokens 'layout-item and 'layout-end). 'layout-end signifies the end of the parse stream. Each parser consumes tokens, and sets the (dynamic) indentation variables, or adds a new (dynamic) scope. At the end of parsing, those indentation variables are used to specify each indentation (for each scope). It can be slow when you have a large function and a slow computer. I plan to rewrite the parser:
|
@kuribas, one more question: does contents of current line (line at which point is placed when user tries to indent his code) affect collection of returned indentation positions, or it's completely defined by context that previous lines provide? |
It does, for keywords like |
@kuribas, this may be not enough... Consider the test-case: (hindent-test "17a A type for a function""
fun :: Int
-> Int"
((1 0) 0)
((2 0) 4)
((3 0) 0 4)) This is from improved tests I'm working on. It works like this:
If second like starts with Is this sort of behavior supported? |
That's not right, indenting after better example:
indentation before x is different than indentation after x:
but:
|
Don't really see what is not right with my example. Of course it should be different. First line is "top-level" statement and indentation should stay at Your |
Well, the current behaviour is more like: (hindent-test "17a A type for a function""
fun :: Int
-> Int"
((1 0) 0)
((1 10) 0 7)
((2 0) 4 7)
((2 7) 0 4)
((3 0) 0 4)) |
The reason is choice, the user may want the |
@kuribas, Yes I know. Initially I wanted to test at the end of lines too. I was surprised that at the end of line collection of indentations is different. Column position shouldn't matter, imho. Choice is OK, in conjunction with all other logic described above. |
@kuribas, I'm also considering more stupid solution, collection of rules that look at previous line and current line (possibly at many previous lines in some cases to get more indentation positions). This can be done in form of domain specific language with macros, for example. This stupid approach may be faster and simpler. Decent parsing of Haskell syntax tree may be overkill for the task at hand. Maybe I'm naive in this thought, though. |
Well, consider: fun :: Maybe
(String, String) |
Yeah, it already simplifies haskell syntax. However I don't want it more stupid than it is, because it should give the correct indentations with respect to haskell syntax, which has some quirks. |
@kuribas, I will try to come up with implementation of my simplified approach. I believe it can work very well (some conceptions should be introduced and relations between them, it may be actually even elegant). At least it can fix bugs that annoy people right now and we could try how good it can be. Then you may replace it with decent parser when it's ready. |
I don't want to discourage you, but making it simpler than it is right now will probably introduce more bugs. If you would like to help with the table based parser, that would be great! |
@kuribas, one more thing. |
Not at this time. |
Here's an idea for of a parser macro (which would compile to a hashtable): (defparser case ()
(keyword "case" expr
(keyword "of" expr
(alt
(end-tokens (indentations current-indent))
(keyword "|" (separated case-alt "|" nil))
(seq "->" (statement-right expr))))))
(defparser statement-right (p)
(alt
(end-tokens
(parse-end left-indent current-indent)))
(seq
(set current-indent)
p)) |
Looks much better. I hope it's possible to write most part of the parser in this clear style, using decent abstractions. |
Please write doc-strings for every function describing in details every layer of your new parser. This way, I and other people in future will be able to understand it and contribute. I am glad to help with this cleaner parser. I won't work at my simplified parser for now. After all, I've other things to do :-) |
Just checked the particular issue that spawned this discussion and it works. So closing this issue. If you wish to continue discussing indentation by all means please open other discussion issue about it. |
@gracjan, For quite a while I wanted to point out that this still does not work. Here is how to reproduce: module Main
()
where Interestingly, if I put |
I haven't experienced it before. Try to copy this sample:
Now try to type the word
import
and press TAB, or press it when you're at the beginning of line -- it goes to 4 column and says "Sole indentation". I remember it behaved differently before -- it would stay at 0 column and say "Sole indentation" -- this behavior is better, I think. Could you please fix that or if it's on purpose please explain me why does it behave this way.The text was updated successfully, but these errors were encountered: