tags:

views:

35

answers:

2

I found this snippet to add to my .emacs that will, on save, strip out tabs and replace them with spaces (to help my files play nicely with everyone else on the team who uses spaces).

Unfortunately, my lisp and emacs lisp chops are not very strong. It seems to be this snippet will work only for the java major mode - how can I get this to work with espresso-mode?

(defun java-mode-untabify ()
    (save-excursion
      (goto-char (point-min))
      (while (re-search-forward "[ \t]+$" nil t)
        (delete-region (match-beginning 0) (match-end 0)))
      (goto-char (point-min))
      (if (search-forward "\t" nil t)
          (untabify (1- (point)) (point-max))))
    nil)

  (add-hook 'java-mode-hook 
            '(lambda ()
               (make-local-variable 'write-contents-hooks)
               (add-hook 'write-contents-hooks 'java-mode-untabify)))
+1  A: 

I have following code in my .emacs that works for me:

;; untabify some modes
(setq alexott/untabify-modes '(haskell-mode emacs-lisp-mode lisp-mode scheme-mode
                                        erlang-mode clojure-mode))
(defun alexott/untabify-hook ()
  (when (member major-mode alexott/untabify-modes)
     (untabify (point-min) (point-max))))
(add-hook 'before-save-hook 'alexott/untabify-hook)

you can add espresso-mode into list of modes, for which untabify will perfomed, by changing list in alexott/untabify-modes variable following way:

(setq alexott/untabify-modes '(haskell-mode emacs-lisp-mode lisp-mode scheme-mode
                                        erlang-mode clojure-mode espresso-mode))
Alex Ott
Fantastic, this is much simpler than the snippet I'd found. Kudos and thanks!
warfangle
It also could be useful to look to whitespace package - it provide a range of functions for work with different kinds of whitespace characters. Look at settings at whitespace customization group - M-x customize-group whitespace
Alex Ott
A: 

The snippet you have here will work for any text file. There isn't anything Java specific about it besides the fact that it is named java-mode-untabify. The only thing you should need to do is duplicate that add-hook call and change the hook name to espresso-mode-hook, or whatever the correct hook is for espresso-mode. Although I might suggest you change the name of the function to something that reflects the fact that it is not Java specific. Something like cleanup-whitespace-in-buffer, or whatever you like.

(defun cleanup-whitespace-in-buffer () ; <- more appropriate name
    (save-excursion
      (goto-char (point-min))
      (while (re-search-forward "[ \t]+$" nil t)
        (delete-region (match-beginning 0) (match-end 0)))
      (goto-char (point-min))
      (if (search-forward "\t" nil t)
          (untabify (1- (point)) (point-max))))
    nil)

(add-hook 'espresso-mode-hook ; <- you can actually add this to any hook
          '(lambda ()
             (make-local-variable 'write-contents-hooks)
             (add-hook 'write-contents-hooks 'cleanup-whitespace-in-buffer)))

CAVEAT:

I just modified the snippet you posted. I'm not on a machine with Emacs right now, so I haven't tested any of this.

The cleanup-whitespace-in-buffer function simply deletes any trailing whitespace from every line in the file, then converts non-trailing tabs into spaces. The call to add-hook creates an anonymous function (a lambda) that will be called whenever the hook is run. This anonymous function arranges for cleanup-whitespace-in-buffer to be run in a buffer before it is saved.

I really like Alex Ott's answer a lot better since it is much more flexible. It sets up a function that is run whenever ANY buffer is saved. It checks to see if the buffer being saved has a mode that is in the list of specified modes and, if so, untabifies the buffer before saving. It doesn't remove trailing white space, but you could easily change the (untabify (point-min) (point-max)) call into (cleanup-whitespace-in-buffer) if you want that behavior. This allows you to easily add other modes that will have their files preprocessed before saving. It even works if, for some reason, your mode doesn't have a hook associated with it. His method is better than what I suggested. I simply posted this answer in the interests of clarifying how your snippet works since you said you feel a little week in Emacs Lisp.

A. Levy
Thanks A, especially for the more in-depth explanation of Alex's answer! If I had more points, I'd vote yours up along with his :)
warfangle
In my config file I simply have another save hook, that performs deletion of trailing whitespaces with delete-trailing-whitespace command
Alex Ott
Glad to be of service Warfangle. For future reference, unless you have used up all your votes for the day, you can vote up more than one answer to a question.
A. Levy