touch main.c; kak main.c)ivoid failed_indent(void) {}<esc>)
void failed_indent(void) {}β
h)
void failed_indent(void) {β}
i<return>)(β = cursor)
void failed_indent(void) {
β}
(β = cursor)
void failed_indent(void) {
β}
This issue is properly described in the discussion of this issue:
alexherbo2/auto-pairs.kak#39
It looks to be the responsability of the filetypes to produce a correct indenting when pressing Return.
Iβm afraid all filetypes are affected to not handle indenting in-between content, assuming new lines are inserted at the end of the line.
...
It is hard, because all filetypes are wrong. I feel like if I fix it in auto-pairs, upstream will never get fixed.
We just need the filetypes to pass from:
int main() { β}
To:
int main() { β}
Then auto-pairs can do what we would do interactively: ReturnβEscapeβO.
...
If you feel courageous, fix all
<language>-new-line-insertedcommands in filetypes.
Is this a valid issue? It seems that the correct behavior would indeed entail what is described.
Yeah I think we should handle this.
There is some nice documentation on how indentation after braces is implemented in doc/autoedit.asciidoc.
Here is a patch that should make this work for C, Rust and Go. There are plenty of other languages that use the same logic - grep for indent after lines? ending with. We probably want to change all of them. Let's make sure this patch works in all reasonable scenarios.
diff --git a/rc/filetype/c-family.kak b/rc/filetype/c-family.kak
index 837c5059..1b430074 100644
--- a/rc/filetype/c-family.kak
+++ b/rc/filetype/c-family.kak
@@ -85,3 +85,3 @@ define-command -hidden c-family-indent-on-newline %< evaluate-commands -draft -i
# indent after an opening brace or parenthesis at end of line
- try %< execute-keys -draft k <a-x> s[{(]\h*$<ret> j <a-gt> >
+ try %< execute-keys -draft <a-x><a-K>[})]\h*$<ret> k <a-x> s[{(]\h*$<ret> j <a-gt> >
# indent after a label
diff --git a/rc/filetype/go.kak b/rc/filetype/go.kak
index 69ce6c27..2214e4f3 100644
--- a/rc/filetype/go.kak
+++ b/rc/filetype/go.kak
@@ -80,3 +80,3 @@ define-command -hidden go-indent-on-new-line %~
# indent after lines ending with { or (
- try %[ execute-keys -draft k<a-x> <a-k> [{(]\h*$ <ret> j<a-gt> ]
+ try %[ execute-keys -draft <a-x><a-K>[})]\h*$<ret> k<a-x> <a-k> [{(]\h*$ <ret> j<a-gt> ]
# cleanup trailing white spaces on the previous line
diff --git a/rc/filetype/rust.kak b/rc/filetype/rust.kak
index 24d36f88..1d0918c0 100644
--- a/rc/filetype/rust.kak
+++ b/rc/filetype/rust.kak
@@ -107,3 +107,3 @@ define-command -hidden rust-indent-on-new-line %~
# indent after lines ending with { or (
- try %[ execute-keys -draft k <a-x> <a-k> [{(]\h*$ <ret> j <a-gt> ]
+ try %[ execute-keys -draft <a-x><a-K>[})]\h*$<ret> k <a-x> <a-k> [{(]\h*$ <ret> j <a-gt> ]
# indent after lines ending with [{(].+ and move first parameter to own line
Awesome, thanks for pointing me to that! I'll go ahead and start some work on a PR, unless prohibited
There is a scenario where that patch doesn't work reasonably @krobelus. If you have an opening brace but a closing parenthesis ({)), it will behave as though ) is closing the block, which it is not. Example:
(β = cursor)
void foo(void) {β)
... on <ret> becomes ...
void foo(void) {
β)
... which should be ...
void foo(void) {
β)
A potential way around this is to do the check for the opening brace or parenthesis first and then check for a corresponding brace later, probably by using a capture group and a command to map { -> } and ( -> ).
A call to the tr shell command would work like this: tr '{(' '})'. We may be able to use a kakoune %sh{echo '<c-r>1'|tr '{(' '})'} call to get the matching bracket, or something to that effect. I'll have to do a bit more digging to see if this is a viable route. And even then, it may make the execute-keys -draft ... command too lengthy and convoluted for this requirement (from doc/autoedit.asciidoc):
... the normal Kakoune editing command are expected to be expressive enough so that relatively complex indentation can be written concisely.
In short: I'll work on implementing solutions similar to what @krobelus shared above, while also do some digging into the viability of a smarter solution I described briefly above. If it's easy to implement and doesn't go against any guidelines, I'll add those changes.
Yeah there's a problem in the regex I suggested - other lines that end in [)}] but don't close a block are deindented.
Why not only deindent lines that only have whitespace and a single closing parenthesis - ^\h*[})]\h*$.
This fixes:
fn a() -> i32 {βb()
}
I think a situation like void foo() {β) } rarely happens, void foo() { (β) } which is much more common, works fine.
I believe we can get away without handling cases like the former where the wrong closing character is used.
There's another inconsistency: inserting a new line here preserves the previous line indent. We should probably deindent.
int main() {
foo();β}
I agree that the specific situation I mentioned isn't worth handling. Thanks for pointing out those other 2!
Yeah there's a problem in the regex I suggested - other lines that end in
[)}]but don't close a block are deindented.
Why not only deindent lines that only have whitespace and a single closing parenthesis -^\h*[})]\h*$.
This breaks this case:
void foo() { (β) }
However, it can easily be remedied by altering the regexp to this: ^\h*[})]+\h*$.
There's another inconsistency: inserting a new line here preserves the previous line indent. We should probably deindent.
int main() { foo();β}
Thanks for properly bringing this to my attention. I realized that if closing braces are deindented, then we don't need to modify the code for indenting after an opening brace. I just tested those changes and the tests I created are still passing, so it looks like it's a go.
For reference, this is now what it looks like (in c-family.kak):
# ...
# indent after an opening brace or parenthesis at end of line
# try %< execute-keys -draft <a-x> <a-K>^\h*[})]+\h*$<ret> k <a-x> <a-k>[{(]\h*$<ret> j <a-gt> > # not needed any more
try %< execute-keys -draft k <a-x> <a-k>[{(]\h*$<ret> j <a-gt> >
# ...
# deindent after a single line statement end
# ...
# deindent closing brace(s)
try %< execute-keys -draft <a-x> <a-k>^\h*[})]+\h*$<ret> <a-lt> >
I'm going to update the title of this issue to reflect these findings and rewrite the local changes I've already made. I'll then start a WIP pull request for deindenting on newline when line has closing braces.
Fixed by #3620