2

On loading a f90 file, emacs changes to F90 mode, which changes some emacs behaviours.

When I press <tab> emacs inserts two spaces at the left margin. Now when I use the backspace key it deletes those two spaces one at a time.

Is there a modification I can make which will allow me to delete tabs with a single keystroke in F90 mode?

4
  • 1
    A <tab> is not a valid character as white space in Fortran and therefore the emacs behavior is correct in my opinion (though the 2 spaces is a matter of taste).
    – albert
    Feb 24, 2021 at 8:54
  • Yes, I understand the whitespace issue is real. However, what I expected from a solution is not to replace the <space> with a <tab> but merely to rebind delete to remove two space when they are to the left of point when delete is pressed. That would work for me, but unfortunately I don't know how to rebind keys. I might have to ask a different question. Feb 24, 2021 at 11:23
  • well I don't know emacs, but how would it distinguish between a <tab> converted to <spaces> and just entered <spaces> when hitting the <del> key? (the later might give a very strange effect as well)
    – albert
    Feb 24, 2021 at 11:26
  • I don't know, but I think think it could be programmed with some elisp which does it, that's why I'm asking; to find out if there somebody who knows how. Feb 24, 2021 at 11:37

1 Answer 1

3

Yes, what you want is a "hungry" or "greedy" delete/backspace. f90-mode doesn't come with such a thing, but cc-mode does. It includes two inter-related families of functions c-electric-delete* and c-hungry-delete-*. Specifically take a look at c-hungry-delete-backwards via Emacs's built in function help (C-h f c-hungry-delete-backwards). From there you can view its implementation; it's relatively small, and will give you a good start at implementing your own "hungry delete".

Edit: Someone's done the work for you, see https://github.com/nflath/hungry-delete

Edit: a naive function to delete two spaces could look something like this. In your ~/.emacs.d/init.el you would add:

;; define a toy function to delete two spaces at once 
;; if the preceding two characters are indeed spaces
(defun nega/two-space-delete ()
  (interactive)
  (if (and (eq ?\  (char-before))
           (eq ?\  (char-before (- (point) 1))))
      (delete-backward-char 2)
    (delete-backward-char 1)))

;; after f90-mode is loaded, remap instances of (delete-backward-char) to 
;; instead use our previously defined toy function
(eval-after-load 'f90-mode
  '(define-key f90-mode-map [remap delete-backward-char] #'nega/two-space-delete))

In your comment you stated

An elisp function which knows the tab-size in spaces and deletes the same number of spaces would solve the problem

This would be the idea solution, but that's not how f90-mode works. Unlike many other modes, it has more than one indent level. In fact it has seven.

  • f90-do-indent -- Extra indentation within do blocks (default 3).
  • f90-if-indent -- Extra indentation within if/select/where/forall blocks (default 3).
  • f90-type-indent -- Extra indentation within type/enum/interface/block-data blocks (default 3).
  • f90-program-indent -- Extra indentation within program/module/subroutine/function blocks (default 2).
  • f90-associate-indent -- Extra indentation within associate blocks (default 2).
  • f90-critical-indent -- Extra indentation within critical/block blocks (default 2).
  • f90-continuation-indent -- Extra indentation applied to continuation lines (default 5).

This complicates writing a comprehensive function that "deletes backwards one indentation level". A "greedy backwards delete" that deletes whitespace back to the beginning of the line, followed by a stroke of the TAB key to set you at the correct indent level would serve you well.

4
  • 1
    Again, github.com/nflath/hungry-delete may be too greedy for your particular use case, but is easy enough to modify for your use. Just reduce the set of "whitespace".
    – nega
    Feb 24, 2021 at 21:17
  • Yes, thank you. I hesitated to say so for not wanting to be unappreciative. The greedy delete, I believe, will delete all whitespace it finds, not only the previous single tab. An elisp function which knows the tab-size in spaces and deletes the same number of spaces would solve the problem. Unfortunately, I am an emacs novice currently unable to write such a thing myself. Feb 25, 2021 at 21:54
  • I didn't get into in in my answer, as it's ultimately not germane to the answer, but your concept of "tab" is not the same as Emacs. Understanding the difference between "tabs" and indentation will aid in further understand Emacs concepts, and in the asking and answering of questions in the future.
    – nega
    Feb 26, 2021 at 3:56
  • understood. Thank you, I had no idea what I was asking would require such a comprehensive solution. It seemed so simple. Perhaps that is why it doesn't do what I expected as it is? Thank you for your help. Feb 26, 2021 at 11:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.