SiteMap Search ElispArea HowTo Glossary RecentChanges News Problems Suggestions

UntabifyUponSave

Last edit

Summary: Added note about write-file-hooks having to return nil in emacs v24

Added:

> Edit: I've been using Joost's 'nothing-fancy' hook as above, but as of v24, this seems to block files being saved. I believe this is because the hook should return nil to signify that it hasn't performed the write itself ... hence
> ;; if indent-tabs-mode is off, untabify before saving
> (add-hook 'write-file-hooks
> (lambda () (if (not indent-tabs-mode)
> (untabify (point-min) (point-max)))
> nil ))
> --TimMeadowcroft


How can I make emacs save all my files with spaces instead of tabs, without manually having to run untabify?

What about this?

    (add-hook 'write-file-hooks (lambda () (untabify (point-min) (point-max))))

Problem: You probably do not want to put it on write-file-hooks. Think of Makefiles…

Better Solution:

  1. Use write-content-hooks instead, and make them local to the buffer
  2. Return nil to make the write-content-hooks work correctly.

For example:

 (defun ska-untabify ()
   "My untabify function as discussed and described at
 http://www.jwz.org/doc/tabs-vs-spaces.html
 and improved by Claus Brunzema:
 - return nil to get `write-contents-hooks' to work correctly
   (see documentation there)
 - `make-local-hook' instead of `make-local-variable'
 - when instead of if
 Use some lines along the following for getting this to work in the
 modes you want it to:
 
 \(add-hook 'some-mode-hook  
           '(lambda () 
               (make-local-hook 'write-contents-hooks) 
                (add-hook 'write-contents-hooks 'ska-untabify nil t)))"
   (save-excursion
     (goto-char (point-min))
     (when (search-forward "\t" nil t)
       (untabify (1- (point)) (point-max)))
     nil))

StefanKamphausen

This caused me some severe headaches. I believe TabsAreEvil, but this kind of approach can seriously screw with other peoples formatting, especially if they have a different default-tab-width setting to you. I attached it to my c-mode write hook. I have now taken a different approach, using font highlighting to catch the little buggers in the bits i edit. – TimOCallaghan – See EightyColumnRule and ShowWhiteSpace.

This still creates problems if you use one emacs session to edit different types of files. I have the following in my .emacs file:

 (defun c++-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 'c++-mode-hook
           '(lambda ()
              (make-local-hook 'write-contents-hooks)
              (add-hook 'write-contents-hooks 'c++-mode-untabify)))

The problem is that after I open a C++ file, all subsequent file writes will call c++-mode-untabify. The add-hook 'c++-mode-hook bit does not create hook that only gets called when saving C++ buffers, or only for the current buffer. Instead, the c++ mode hooks are run when first loading C++ mode, and this hook adds c++-mode-untabify to the write-contents-hooks that are executed for all buffers. So if I load a C++ file and then in the same session open a tab-delimited text file, I can’t edit and save the text file without having c++-mode-untabify run on the buffer.

Does anyone know how set a write contents hook that only applies to a given buffer or file type, or how to clear write-contents-hooks when changing to buffers using other major-modes? --DanielMcPherson?

Edit: I see now. make-local-hook is obsolete as of 21.1. Instead, add-hook now takes an optional argument for making a hook buffer-local. The add-hook part should be: (add-hook ‘c++-mode-hook ‘(lambda () (add-hook ‘write-contents-hooks ‘c++-mode-untabify nil t)))

Alternately, c++-mode-untabify could check the current mode:

 (defun c++-mode-untabify ()
   (if (string= (substring mode-name 0 3) "C++")
       (save-excursion
         (delete-trailing-whitespace)
         (untabify (point-min) (point-max)))))

Thanks to Boojum on StackOverflow? for this answer. See http://stackoverflow.com/questions/318553/getting-emacs-to-untabify-when-saving-files. --DanielMcPherson?

I just have the following in my init file, which does nothing fancy at all and works exactly as you’d want it to:

 ;; no tabs by default. modes that really need tabs should enable
 ;; indent-tabs-mode explicitly. makefile-mode already does that, for
 ;; example.
 (setq-default indent-tabs-mode nil)
 ;; if indent-tabs-mode is off, untabify before saving
 (add-hook 'write-file-hooks 
          (lambda () (if (not indent-tabs-mode)
                         (untabify (point-min) (point-max)))))

--JoostDiepenmaat

Edit: I’ve been using Joost’s ‘nothing-fancy’ hook as above, but as of v24, this seems to block files being saved. I believe this is because the hook should return nil to signify that it hasn’t performed the write itself … hence

 ;; if indent-tabs-mode is off, untabify before saving
 (add-hook 'write-file-hooks 
          (lambda () (if (not indent-tabs-mode)
                         (untabify (point-min) (point-max)))
                      nil ))

--TimMeadowcroft


CategoryIndentation