How to run hook depending on file location

2019-04-08 15:00发布

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.

标签: emacs elisp
2条回答
祖国的老花朵
2楼-- · 2019-04-08 15:11

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

查看更多
等我变得足够好
3楼-- · 2019-04-08 15:17

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

查看更多
登录 后发表回答