5

I am involved in python project where tabs are used, however i am not using them in every other code i write, it is vital to use them in that particular project. Projects are located in one directory under specific directories. I.E:

\main_folder
    \project1
    \project2
    \project3
...etc

I have couple functions/hooks on file open and save that untabify and tabify whole buffer i work on.

 ;; My Functions
(defun untabify-buffer ()
            "Untabify current buffer"
        (interactive)
        (untabify (point-min) (point-max)))

(defun tabify-buffer ()
        "Tabify current buffer"
        (interactive)
        (tabify (point-min) (point-max)))

;; HOOKS
; untabify buffer on open
(add-hook 'find-file-hook 'untabify-buffer)
; tabify on save
(add-hook 'before-save-hook 'tabify-buffer)

If i put it in .emacs file it is run on every .py file i open which is not what i want. What i`d like to have is to have these hooks used only in one particular folder with respective subfolders. Tried .dir_locals but it works only for properties not hooks. I can not use hooks in specific modes (i.e. python-mode) as almost all projects are written in python. To be honest i tried writing elisp conditional save but failed.

Michał Klich
  • 611
  • 7
  • 17

2 Answers2

3

A very easy solution is to just add a configuration variable that can be used to disable the hooks. For example:

(defvar tweak-tabs t)
(add-hook 'find-file-hook
          (lambda () (when tweak-tabs (untabify (point-min) (point-max)))))
(add-hook 'before-save-hook
          (lambda () (when tweak-tabs (tabify (point-min) (point-max)))))

Now you can add a .dir-locals.el file in the relevant directories, setting tweak-tabs to nil, disabling this feature there.

(But another problem is that this is a pretty bad way to deal with tabs. For example, after you save a file you do see the tabs in it.)

Eli Barzilay
  • 29,301
  • 3
  • 67
  • 110
  • Thank you. That actually is answer to my question but you raised a good point. After save i`ll have tabs all over the buffer. I did some investigation as i thought to hook functions to kill-buffer or kill-emacs but unfortunately they are run after file is already saved. If it could be possible to actually check what has invoked 'save' on buffer and aply functions only if it was kill-buffer or kill-emacs. Do you have any other suggestions or experience in such case? – Michał Klich Jun 16 '11 at 12:30
  • I'd probably start with `write-file-functions`, and maybe make it create a copy of the buffer, tabify that, save, and return `t`. See also [this page](http://www.emacswiki.org/emacs/UntabifyUponSave), although they don't do that since they want the buffer to stay *un*tabified. – Eli Barzilay Jun 16 '11 at 13:41
2

Just for the record, to answer the literal question in the title (as I reached this question via a web search): one way to add a hook that depends on file location is to make it a function that checks for buffer-file-name. (Idea from this answer.)

For example, for the exact same problem (turn on tabs only in a particular directory, and leave tabs turned off elsewhere), I'm currently doing something like (after having installed the package smart-tabs-mode with M-x package-install):

(smart-tabs-insinuate 'python) ; This screws up all Python files (inserts tabs)
(add-hook 'python-mode-hook    ; So we need to un-screw most of them
          (lambda ()
            (unless (and (stringp buffer-file-name)
                         (string-match "specialproject" buffer-file-name))
              (setq smart-tabs-mode nil)))
          t)                   ; Add this hook to end of the list

(This is a bit inverted, as smart-tabs-insinuate itself modifies python-mode-hook and then we're modifying it back, but it should do as an example.)

ShreevatsaR
  • 38,402
  • 17
  • 102
  • 126