Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run hook depending on file location

Tags:

emacs

elisp

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.

like image 393
Michał Klich Avatar asked Oct 11 '22 18:10

Michał Klich


2 Answers

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.)

like image 191
Eli Barzilay Avatar answered Oct 13 '22 07:10

Eli Barzilay


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.)

like image 20
ShreevatsaR Avatar answered Oct 13 '22 09:10

ShreevatsaR