1

Let's say I have the following code:

void foo(){
    ~
}

I have marked point with ~. When I press enter the electric indentation works as normal but it doesn't keep the indentation for the previous line.

void foo(){
// no indentation on this line
    ~
}

How can I set my .emacs file to keep the indentation? Expected result:

void foo(){
--->
--->~
}

Any help is appreciated. Using emacs 26.1

Nathan
  • 13
  • 3
  • Have you tried reproducing this without your init file (`emacs -q`)? –  Apr 09 '19 at 18:37
  • Yes. This does not work though. – Nathan Apr 09 '19 at 18:50
  • I'm confused. Looking at the new-line documentation (C-h f RET newline) one sentence states that the preceding line will be be reindented if in electric-indent-mode. Quote "If ‘electric-indent-mode’ is enabled, this indents the final new line that it adds, and reindents the preceding line. To just insert a newline, use M-x electric-indent-just-newline." – Nathan Apr 09 '19 at 19:41
  • The documentation mentions that it reindents the preceeding line, so my assumption is that in your case the indentation you want to keep is different from what Emacs will indent to once you put content on your line. –  Apr 09 '19 at 20:18
  • Is there a way to test this? When in whitespace mode (M-x whitespace-mode) it seems that the indentation is carried over to the next line. This suggests that the newline character is inserted before the indentation. – Nathan Apr 09 '19 at 20:43
  • You could try pressing `TAB` rather than `RET` to see how the line you're on will indent. –  Apr 09 '19 at 21:44
  • I've explicitly set emacs to insert a literal tab on TAB and set backward-delete-char-untabify-method is set to nil as to ensure backspace doesn't convert my tabs to spaces. So pressing TAB will just insert the tab character - \t - and pressing backspace will delete that tab character. – Nathan Apr 09 '19 at 22:34
  • I think the issue is that Emacs tries to avoid leaving you with trailing whitespace. If your line wasn't empty the indentation wouldn't be removed. Not sure off-hand how to change this (I wouldn't want to, personally). – npostavs Apr 10 '19 at 01:13
  • I'm thinking that a custom newline function would be able to do the job. From within this function standard newline is called and afterwards the function checks for a string of TAB characters followed by two newline characters (looking back from point). If so, the function inserts the same number of TAB characters between the first and second newline characters. An another method could be to simply copy the line and then move point down. I'm not sure if emacs has a command for this. I can check later. – Nathan Apr 10 '19 at 09:41

1 Answers1

1

This is happening because the function electric-indent-post-self-insert-function calls (delete-horizontal-space t) at the end of the line. The only way around this that I see is to copy the code of that function to your dotfile, remove that line, and add/remove the hook post-self-insert-hook. This would be a lot of work, and will probably leave all your files with a bunch of trailing whitespace.

cyberbisson
  • 887
  • 1
  • 6
  • 17
  • Thanks for the suggestion. I have copied the function to my init file, removed the call to `(delete-horizontal-space t)`, renamed the function, removed the original function from `post-self-insert-hook` in replacement for the new function. The re-hooking is wrapped in a function which I would add to the `electric-indent-hook`. So when emacs enters electric indent mode, the function in question is remapped. I have also tried `(with-eval-after-load "electric.el" '(defun electric-indent-post-self-insert-function ()...`. Both methods have not worked. – Nathan Apr 11 '19 at 11:33
  • I have appended to each function a call to `message` but when I press the enter key, non of the messages are displayed. This suggests that the function is not being called, unless the messages are being diverged to a buffer other than the mini buffer. – Nathan Apr 11 '19 at 11:36
  • The best I can do at the moment is bind a key to a function that duplicates the current line. This only works if the syntax of the code is complete eg, ending with a semicolon for C type languages. – Nathan Apr 11 '19 at 13:37
  • I don't see any hooks for `electric-indent-mode`, otherwise that's where I'd suggest adding your hook re-mappings. Sorry my answer wasn't as helpful as I was hoping! – cyberbisson Apr 11 '19 at 17:09
  • I type `C-h v RET electric-indent-mode-hook RET`. The documentation shows up on a *Help* buffer. You should see the hook there. – Nathan Apr 11 '19 at 17:41
  • I'm sorry, I meant more specifically, hooks that run when `electric-indent-mode` is _loaded_ into the buffer. If such a hook existed, you could set the indent-mode hook as I described. Running these settings after electric.el gets loaded isn't going to work because it sets the indent-hook every time a new (applicable) buffer gets loaded. I suppose you could try `c-mode-common-hook`... – cyberbisson Apr 11 '19 at 17:53
  • 1
    That works. Thank a lot. – Nathan Apr 11 '19 at 18:25