Hi, is there some reasonably easy way to make autoindentation use the previous non-empty line when calculating what indentation to use, instead of always using the previous line?
For example:
int main() {
printf("hello, world");
// Some empty lines follow:
}
When the cursor is on the last line, with the closing brace }, and I press O to insert above that line, I would want the code to be indented as the comment above, not using the 0-space indentation of the empty lines.
It seems like Kakoune uses file-type specific hooks to handle auto-indentation, so I guess it would be a lot of work to change this for all file types?
I would love an answer to this, too. It’s been an ongoing irritation for me. (I typically experience it when opening a new line with o or O.)
The responsible code appears to be in the c-family-indent-on-newline hook function, in c-family.kak (version from my installation copied below).
It would take me a lot of time to work out how this works, but I expect it is the k and K commands that go up to the previous line to get the indent of that line. a-& is the builtin command to copy the indent from one line to another.
I found c-family-indent-on-newline could be overridden like this in my kakrc file:
Then I copy the definition of c-family-indent-on-newline from c-family.kak and change the name to my-c-family-indent-on-newline.
I tried replacing one of the K’s with <a-?>[^\h\n]<ret>, so now I have
> catch %<
# else indent new lines with the same level as the previous one
#execute-keys -draft K <a-&>
execute-keys -draft <a-?>[^\h\n]<ret> <a-&>
>
It doesn’t work perfectly, though. Probably a similar change would need to be made throughout the rest of the function.
Original version:
define-command -hidden c-family-indent-on-newline %< evaluate-commands -draft -itersel %<
execute-keys <semicolon>
try %<
# if previous line is part of a comment, do nothing
execute-keys -draft <a-?>/\*<ret> <a-K>^\h*[^/*\h]<ret>
> catch %<
# else if previous line closed a paren (possibly followed by words and a comment),
# copy indent of the opening paren line
execute-keys -draft kx 1s(\))(\h+\w+)*\h*(\;\h*)?(?://[^\n]+)?\n\z<ret> m<a-semicolon>J <a-S> 1<a-&>
> catch %<
# else indent new lines with the same level as the previous one
execute-keys -draft K <a-&>
>
# remove previous empty lines resulting from the automatic indent
try %< execute-keys -draft k x <a-k>^\h+$<ret> Hd >
# indent after an opening brace or parenthesis at end of line
try %< execute-keys -draft k x <a-k>[{(]\h*$<ret> j <a-gt> >
# indent after a label
try %< execute-keys -draft k x s[a-zA-Z0-9_-]+:\h*$<ret> j <a-gt> >
# indent after a statement not followed by an opening brace
try %< execute-keys -draft k x s\)\h*(?://[^\n]+)?\n\z<ret> \
<a-semicolon>mB <a-k>\A\b(if|for|while)\b<ret> <a-semicolon>j <a-gt> >
try %< execute-keys -draft k x s \belse\b\h*(?://[^\n]+)?\n\z<ret> \
j <a-gt> >
# deindent after a single line statement end
try %< execute-keys -draft K x <a-k>\;\h*(//[^\n]+)?$<ret> \
K x s\)(\h+\w+)*\h*(//[^\n]+)?\n([^\n]*\n){2}\z<ret> \
MB <a-k>\A\b(if|for|while)\b<ret> <a-S>1<a-&> >
try %< execute-keys -draft K x <a-k>\;\h*(//[^\n]+)?$<ret> \
K x s \belse\b\h*(?://[^\n]+)?\n([^\n]*\n){2}\z<ret> \
<a-S>1<a-&> >
# deindent closing brace(s) when after cursor
try %< execute-keys -draft x <a-k> ^\h*[})] <ret> gh / [})] <esc> m <a-S> 1<a-&> >
# align to the opening parenthesis or opening brace (whichever is first)
# on a previous line if its followed by text on the same line
try %< evaluate-commands -draft %<
# Go to opening parenthesis and opening brace, then select the most nested one
try %< execute-keys [c [({],[)}] <ret> >
# Validate selection and get first and last char
execute-keys <a-k>\A[{(](\h*\S+)+\n<ret> <a-K>"(([^"]*"){2})*<ret> <a-K>'(([^']*'){2})*<ret> <a-:><a-semicolon>L <a-S>
# Remove possibly incorrect indent from new line which was copied from previous line
try %< execute-keys -draft , <a-h> s\h+<ret> d >
# Now indent and align that new line with the opening parenthesis/brace
execute-keys 1<a-&> &
> >
> >