-
-
Notifications
You must be signed in to change notification settings - Fork 5.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
julia-mode: Indentation fixes #15156
Conversation
">" "<" ">=" "<=" "==" "===" "!=" "!==" "<:" "≠" "≤" "≥" | ||
".>" ".<" ".>=" ".<=" ".==" ".!=" | ||
"&&" "||" "?")) | ||
(regexp-opt '(" #" " \n" "#" "\n")))) |
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.
Are these missing many operators from the list here
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.
Oh yes, I see there's some that are missing. I used this table because I saw this comment and wasn't sure how to interpret it for the purposes of julia-mode.
By the way, do you think it's necessary to treat assignment operators differently? I was trying to preserve the original behavior with them, but I wasn't sure if that was important.
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.
What exactly is the special behavior?
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.
Sorry, I should have explained. The current behavior is to increase the indent level if the previous line ends in a "=". In this PR I kept that behavior but extended it to all assignment operators. For example,
a =
b =
1
For other operators, I increase the indent after the first one, but keep the indentation the same after that. For example,
a = 1 +
2 +
3 +
4
My question is is the current behavior important? Is there something wrong with this for example?
a =
b =
c
It seems strange to worry too much about chained assignments, but then again I don't have much experience with writing julia yet.
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.
Thanks for the explaination, I don't really think the current behavior is particularly important (since other language modes do not do this). You can probably find why it is introduced with git-blame
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.
Ok thanks. I'll look into it more tomorrow
On Fri, Feb 19, 2016 at 10:45 PM Yichao Yu [email protected] wrote:
In contrib/julia-mode.el
#15156 (comment):+(defconst julia-hanging-assignment-regexp
- (concat "^[^#\n]+ "
(regexp-opt '("=" "+=" "-=" "*=" "/=" "//=" "\=" "^=" "÷=" "%=" "|=" "&=" "$=" "<<=" ">>="
".+=" ".-=" ".*=" "./=" ".//=" ".\=" ".^=" ".÷=" ".%="))
(regexp-opt '(" #" " \n" "#" "\n"))))
+(defconst julia-hanging-operator-regexp
- (concat "^[^#\n]+ "
(regexp-opt '("^" ".^" "//" ".//" "_" "/" "%" "&" "\" "._" "./" ".%" ".\"
"<<" ">>" ">>>" ".<<" ".>>" ".>>>"
"+" "-" "|" "$" ".+" ".-"
":" ".." "|>"
">" "<" ">=" "<=" "==" "===" "!=" "!==" "<:" "≠" "≤" "≥"
".>" ".<" ".>=" ".<=" ".==" ".!="
"&&" "||" "?"))
(regexp-opt '(" #" " \n" "#" "\n"))))
Thanks for the explaination, I don't really think the current behavior is
particularly important (since other language modes do not do this). You can
probably find why it is introduced with git-blame
https://github.com/JuliaLang/julia/blame/master/contrib/julia-mode.el—
Reply to this email directly or view it on GitHub
https://github.com/JuliaLang/julia/pull/15156/files#r53543829.
Added another commit to fix #11559 |
4e7927a
to
9e3074f
Compare
@yuyichao I added all the operators from julia-parser.scm. I hope that doesn't cause any performance issues. I also added a couple of tests for these rules. I'm happy to squash commits if you would like me to. |
Hmmm, is the operator list automatically generated? Local test shows that it is missing some of the operators like |
63eed4e
to
0100288
Compare
Good catch. I missed a couple of vertical bars that needed to be removed from the translation from julia-parser.scm Since I'm digging into the indentation code, I decided to take a crack at addressing some of the other indentation related issues too. For example, I think I found a nice way to improve the performance of indentation within parens to address #9831. That's what the latest commit attempts to do. I see big improvements on my computer (~75%) after increasing the max lookback for parens to 10k for the old version and removing it in the current version. I was thinking about also going after gains in the block indentation procedure, but maybe this pr is getting too ambitious? |
0100288
to
203a3da
Compare
Just to note where I'm seeing the performance bottlenecks after this PR. If I profile indenting the whole lapack.jl file, for example, I get these results for the cpu portion, suggesting that
|
3b039cd
to
7cf74ab
Compare
LGTM. We can merge this after squashing to 1-2 commits. Further improvements can go in other pr's. |
whoops, sorry. I added one more just now. Would you like me to move it out? On Mon, Feb 22, 2016 at 8:59 AM Yichao Yu [email protected] wrote:
|
0e7d3c9
to
9f7277e
Compare
ok, removed the last commit and squashed everything else to 2 commits. I'll start a new pr for the strings and blocks. |
Either removing the new commit or not should be fine. Will merge after getting back to my computer and tested it locally |
I removed it and opened a new pr, so nothing you recently tested should be On Mon, Feb 22, 2016 at 11:10 AM Yichao Yu [email protected] wrote:
|
I actually didn't run the test last time and only checked the indent of operators. Looks like this patch breaks tests? (in particular, indent of parenthesis) yuyichao% emacs -batch -L . -l ert -l julia-mode-tests.el -f ert-run-tests-batch-and-exit
Running 15 tests (2016-02-22 13:06:03-0500)
Indenting region...
Indenting region...done
passed 1/15 julia--test-indent-begin
Indenting region...
Indenting region...done
passed 2/15 julia--test-indent-comment-equal
Indenting region...
Indenting region...done
passed 3/15 julia--test-indent-else
Indenting region...
Indenting region...done
passed 4/15 julia--test-indent-equals
Indenting region...
Indenting region...done
passed 5/15 julia--test-indent-function
Indenting region...
Indenting region...done
passed 6/15 julia--test-indent-if
Indenting region...
Indenting region...done
passed 7/15 julia--test-indent-ignores-blank-lines
Indenting region...
Indenting region...done
passed 8/15 julia--test-indent-leading-paren
Indenting region...
Indenting region...done
Indenting region...
Indenting region...done
passed 9/15 julia--test-indent-module-keyword
Indenting region...
Indenting region...done
passed 10/15 julia--test-indent-nested-if
Indenting region...
Indenting region...done
passed 11/15 julia--test-indent-operator
Indenting region...
Test julia--test-indent-paren backtrace:
julia-indent-line()
indent-according-to-mode()
indent-region(1 18)
(let ((julia-indent-offset 4)) (julia-mode) (insert "\nfoobar(bar,\n
(progn (let ((julia-indent-offset 4)) (julia-mode) (insert "\nfoobar
(unwind-protect (progn (let ((julia-indent-offset 4)) (julia-mode) (
(save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn
(let ((temp-buffer (generate-new-buffer " *temp*"))) (save-current-b
(lambda nil (let ((temp-buffer (generate-new-buffer " *temp*"))) (sa
#[0 "\306\307!r\211q\210\310\311\312\313\314\315!\316\"\317\320%DC
funcall(#[0 "\306\307!r\211q\210\310\311\312\313\314\315!\316\"\31
ert--run-test-internal([cl-struct-ert--test-execution-info [cl-struc
#[0 "r\304 q\210\305 )\306\307\310\311\312\313!\314\"\315\316%DC\2
funcall(#[0 "r\304 q\210\305 )\306\307\310\311\312\313!\314\"\315\
ert-run-test([cl-struct-ert-test julia--test-indent-paren "We should
ert-run-or-rerun-test([cl-struct-ert--stats t [[cl-struct-ert-test j
ert-run-tests(t #[385 "\306\307\"\203D\211\211G\310U\203\211@\20
ert-run-tests-batch(nil)
ert-run-tests-batch-and-exit()
command-line-1(("-L" "." "-l" "ert" "-l" "julia-mode-tests.el" "-f"
command-line()
normal-top-level()
Test julia--test-indent-paren condition:
(wrong-number-of-arguments
(0 . 1)
3)
FAILED 12/15 julia--test-indent-paren
Indenting region...
Test julia--test-indent-paren-space backtrace:
julia-indent-line()
indent-according-to-mode()
indent-region(1 20)
(let ((julia-indent-offset 4)) (julia-mode) (insert "\nfoobar( bar,\
(progn (let ((julia-indent-offset 4)) (julia-mode) (insert "\nfoobar
(unwind-protect (progn (let ((julia-indent-offset 4)) (julia-mode) (
(save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn
(let ((temp-buffer (generate-new-buffer " *temp*"))) (save-current-b
(lambda nil (let ((temp-buffer (generate-new-buffer " *temp*"))) (sa
#[0 "\306\307!r\211q\210\310\311\312\313\314\315!\316\"\317\320%DC
funcall(#[0 "\306\307!r\211q\210\310\311\312\313\314\315!\316\"\31
ert--run-test-internal([cl-struct-ert--test-execution-info [cl-struc
#[0 "r\304 q\210\305 )\306\307\310\311\312\313!\314\"\315\316%DC\2
funcall(#[0 "r\304 q\210\305 )\306\307\310\311\312\313!\314\"\315\
ert-run-test([cl-struct-ert-test julia--test-indent-paren-space "We
ert-run-or-rerun-test([cl-struct-ert--stats t [[cl-struct-ert-test j
ert-run-tests(t #[385 "\306\307\"\203D\211\211G\310U\203\211@\20
ert-run-tests-batch(nil)
ert-run-tests-batch-and-exit()
command-line-1(("-L" "." "-l" "ert" "-l" "julia-mode-tests.el" "-f"
command-line()
normal-top-level()
Test julia--test-indent-paren-space condition:
(wrong-number-of-arguments
(0 . 1)
3)
FAILED 13/15 julia--test-indent-paren-space
Indenting region...
Indenting region...done
passed 14/15 julia--test-indent-toplevel
Indenting region...
Test julia--test-top-level-following-paren-indent backtrace:
julia-indent-line()
indent-according-to-mode()
indent-region(1 30)
(let ((julia-indent-offset 4)) (julia-mode) (insert "y1 = f(x,\n
(progn (let ((julia-indent-offset 4)) (julia-mode) (insert "y1 = f(x
(unwind-protect (progn (let ((julia-indent-offset 4)) (julia-mode) (
(save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn
(let ((temp-buffer (generate-new-buffer " *temp*"))) (save-current-b
(lambda nil (let ((temp-buffer (generate-new-buffer " *temp*"))) (sa
#[0 "\306\307!r\211q\210\310\311\312\313\314\315!\316\"\317\320%DC
funcall(#[0 "\306\307!r\211q\210\310\311\312\313\314\315!\316\"\31
ert--run-test-internal([cl-struct-ert--test-execution-info [cl-struc
#[0 "r\304 q\210\305 )\306\307\310\311\312\313!\314\"\315\316%DC\2
funcall(#[0 "r\304 q\210\305 )\306\307\310\311\312\313!\314\"\315\
ert-run-test([cl-struct-ert-test julia--test-top-level-following-par
ert-run-or-rerun-test([cl-struct-ert--stats t [[cl-struct-ert-test j
ert-run-tests(t #[385 "\306\307\"\203D\211\211G\310U\203\211@\20
ert-run-tests-batch(nil)
ert-run-tests-batch-and-exit()
command-line-1(("-L" "." "-l" "ert" "-l" "julia-mode-tests.el" "-f"
command-line()
normal-top-level()
Test julia--test-top-level-following-paren-indent condition:
(wrong-number-of-arguments
(0 . 1)
3)
FAILED 15/15 julia--test-top-level-following-paren-indent
Ran 15 tests, 12 results as expected, 3 unexpected (2016-02-22 13:06:03-0500)
3 unexpected results:
FAILED julia--test-indent-paren
FAILED julia--test-indent-paren-space
FAILED julia--test-top-level-following-paren-indent |
They pass for me in the buffer and from the command line. By the way that command from the command line needs to be run in the contrib folder of the repo. It looks like you're getting errors, which suggests to me that you're potentially loading the wrong version of julia-mode.el, but I can't really tell from the output. |
I did, I've also tried replacing the file name and run it in a different directory to make sure I'm loading the system version and compare the result and these errors only appears when the version in this PR is used. I also see the regression when editing files. I compile it to elc and I also have
I'm pretty sure I'm using the right version since I can see a difference when I'm using te original version. |
I figured it out. Give me some more time and I'll make it compatible with emacs 24. Sorry I didn't check that. |
24.5 from archlinux repo
NP. thanks for the improvements =) |
Introduce julia-indent-hanging to calculate indentation following any hanging operators as defined in julia-hanging-operator-regexp on the previous line. If a line follows a hanging operator increase the indentation by one increment, unless it is preceded by two hanging operators. julia-hanging-operator-regexp is taken from julia-parser.scm. Added two tests Fixes JuliaLang#15118 Fix indentation after module kw Register "module" as a keyword that starts a block, and add to new var julia-block-start-keywords-no-indent for block keywords that should not increase the indentation level. Fixes JuliaLang#11559
Replace julia-paren-indent with a version that uses the higher level function backward-up-list to find any previous opening parentheses. This function automatically skips balanced expressions like strings, as well as comments. On some test files the time to indent falls by more than 75% with this change, even after increasing the threshold for paren lookback to 10k. Note the threshold is removed in this version.
9f7277e
to
0d4de5a
Compare
@yuyichao I fixed the issue and tested in emacs 24.5. I think it should work for you. |
Tested locally and it looks good. I've also verified that indenting the whole buffer is much faster and it can indent a list with a few hundred lines without giving up. Merging before the CI finishes since the CI is not checking anything about these files, (not even the white space checker since some tests needs end-of-line space). |
julia-mode: Indentation fixes
This is actually still a little confusing since it produces if a &&
b
c
end
|
I don't use julia-mode, but I'd prefer if we settled on indenting line continuations on initial if/for/etc block opener lines one level further than the rest of the block contents. |
I like that suggestion, and it's easy to do |
Note: This needs tests, which I can write, but it would be helpful to have someone check this to make sure they agree with the indentation rules I've put in here.
Introduce julia-indent-hanging to calculate indentation following any hanging operators as defined in julia-hanging-operator-regexp or julia-hanging-assignment-regexp on the previous line. If a line follows a hanging operator increase the indentation by one increment, unless it is preceded by two hanging
operators.
Fixes #15118