Emacs: load-file .emacs when saved - emacs

I'm new to emacs and lisp.
I wanted to auto-load the dot file when it was saved. Meaning, when I save my .emacs file, it would automatically call load-file on it (thus letting me know right away if I messed up).
But I can't seen to be able to find a comprehensive tutorial on hooks in emacs.
This is what I've come up with:
(defun load-init-after-save ()
"After saving this file, load it"
(if (eq bname this) ('load-file this) (nil))
)
(add-hook 'after-save-hook 'load-init-after-save)
Of course, this is incorrect: bname and this are just placeholders. And I don't want this function to run on all saves, just when the .emacs file is saved.
Does anyone know how to do this? Is there a better, easier way?

The following code loads your .emacs or ~/.emacs.d/init.el file after save:
(defun my-load-user-init-file-after-save ()
(when (string= (file-truename user-init-file)
(file-truename (buffer-file-name)))
(let ((debug-on-error t))
(load (buffer-file-name)))))
(add-hook 'after-save-hook #'my-load-user-init-file-after-save)
Since your intended use is error-checking, the code also enables the debugger while loading the init file, so that you get a nice backtrace in case of errors.
For error checking of your init file you may also find Flycheck useful. It checks your init file on the fly with the byte compiler, highlights any errors and warnings in the buffer, and—optionally—gives you a list of all errors and warnings.
Disclaimer: I'm the maintainer of this library.

Way 1
One way of doing is to install auto-compile-mode from MELPA, and enable it:
(defun my-emacs-lisp-hook ()
(auto-compile-mode 1))
(add-hook 'emacs-lisp-mode-hook 'my-emacs-lisp-hook)
Now each time you save an Elisp file that's byte-compiled, it will be
re-compiled. Compilation will usually catch some bad errors.
To compile any Elisp file, select it in dired (C-x d)
and press B (dired-do-byte-compile).
Way 2
Use this custom code I wrote.
(defun test-emacs ()
(interactive)
(require 'async)
(async-start
(lambda () (shell-command-to-string "emacs --batch --eval \"(condition-case e (progn (load \\\"~/.emacs\\\") (message \\\"-OK-\\\")) (error (message \\\"ERROR!\\\") (signal (car e) (cdr e))))\""))
`(lambda (output)
(if (string-match "-OK-" output)
(when ,(called-interactively-p 'any)
(message "All is well"))
(switch-to-buffer-other-window "*startup error*")
(delete-region (point-min) (point-max))
(insert output)
(search-backward "ERROR!")))))
(defun auto-test-emacs ()
(when (eq major-mode 'emacs-lisp-mode))
(test-emacs))
(add-hook 'after-save-hook 'auto-test-emacs)
This will start a new Emacs instance in the background each time you
save a file. If something goes wrong, it will complain.
The second approach uses async.
If you really want to do this just for .emacs user this:
(defun auto-test-emacs ()
(when (and (eq major-mode 'emacs-lisp-mode)
(equal (file-truename user-init-file)
(expand-file-name
buffer-file-truename)))
(test-emacs)))

Related

Forbid buffer content to save to old file when buffer file name is changed

I have follow use case annoying me a lot.
Open file foo.rb in emacs buffer.
rename foo.rb to bar.rb use external tool.(e.g. rename from terminal)
Select foo.rb buffer in Emacs, edit it, when C-x s to save, this buffer
save as old file name (foo.rb), not expected bar.rb.
Is there any emacs config to prevent this??
What i expect is some like:
open file foo.rb in Emacs buffer.
rename foo.rb to bar.rb use external tool
edit foo.rb buffer, when save, told me: file is removed, or prompt,
save as a new file name.
Here's the beginning of a solution. The devil's in the details; there are probably a lot of corner cases that this code doesn't deal with.
(defvar do-not-save-list ())
(defun do-not-save-add-to-list (event)
(when (eq 'renamed (cadr event))
(add-to-list 'do-not-save-list
(caddr event))))
(defun do-not-save-add-watcher ()
(setq do-not-save-list (remove (buffer-file-name) do-not-save-list))
(file-notify-add-watch (buffer-file-name)
'(change)
#'do-not-save-add-to-list))
(add-hook 'find-file-hook #'do-not-save-add-watcher)
(defun do-not-save-check ()
(let ((filename (buffer-file-name)))
(when (member filename do-not-save-list)
(message "not saving %s" filename)
t ;; returns non-nil to prevent write
)))
(add-hook 'write-file-functions #'do-not-save-check)
(defun do-not-save-kill-hook ()
(setq do-not-save-list (remove (buffer-file-name) do-not-save-list)))
(add-hook 'kill-buffer-hook #'do-not-save-kill-hook)

use .dir-locals.el to pick major mode [duplicate]

I have defined a .dir-locals.el file with the following content:
((python-mode . ((cr/virtualenv-name . "saas"))))
In my .emacs I have the following function to retrieve this value and provide a virtualenv path:
(defun cr/virtualenv ()
(cond (cr/virtualenv-name (format "%s/%s" virtualenv-base cr/virtualenv-name))
((getenv "EMACS_VIRTUAL_ENV") (getenv "EMACS_VIRTUAL_ENV"))
(t "~/.emacs.d/python")))
Finally, in my python-mode-hook list, I have this hook function:
(add-hook 'python-mode-hook 'cr/python-mode-shell-setup)
(defun cr/python-mode-shell-setup ()
(message "virtualenv-name is %s" cr/virtualenv-name)
(let ((python-base (cr/virtualenv)))
(cond ((and (fboundp 'ipython-shell-hook) (file-executable-p (concat python-base "/bin/ipython")))
(setq python-python-command (concat python-base "/bin/ipython"))
(setq py-python-command (concat python-base "/bin/ipython"))
(setq py-python-command-args '( "-colors" "NoColor")))
(t
(setq python-python-command (concat python-base "/bin/python"))
(setq py-python-command (concat python-base "/bin/python"))
(setq py-python-command-args nil)))))
When I open a new python file, the message logged by cr/python-mode-shell-setup indicates that cr/virtualenv-name is nil. However, when I C-h v the name, I get "saas" instead.
Obviously there's a load order issue here; is there a way to have my mode hook statements respond to directory-local variables?
This happens because normal-mode calls (set-auto-mode) and (hack-local-variables) in that order.
However hack-local-variables-hook is run after the local variables have been processed, which enables some solutions:
The first is to make Emacs run a new "local variables hook" for each major mode:
(add-hook 'hack-local-variables-hook 'run-local-vars-mode-hook)
(defun run-local-vars-mode-hook ()
"Run a hook for the major-mode after the local variables have been processed."
(run-hooks (intern (concat (symbol-name major-mode) "-local-vars-hook"))))
(add-hook 'python-mode-local-vars-hook 'cr/python-mode-shell-setup)
(Your original function can be used unmodified, with that approach.)
A second option is to utilise the optional LOCAL argument to add-hook that makes the specified function buffer-local. With this approach you could write your hook as follows:
(add-hook 'python-mode-hook 'cr/python-mode-shell-setup)
(defun cr/python-mode-shell-setup ()
(add-hook 'hack-local-variables-hook
(lambda () (message "virtualenv-name is %s" cr/virtualenv-name)
(let ((python-base (cr/virtualenv)))
(cond ((and (fboundp 'ipython-shell-hook) (file-executable-p (concat python-base "/bin/ipython")))
(setq python-python-command (concat python-base "/bin/ipython"))
(setq py-python-command (concat python-base "/bin/ipython"))
(setq py-python-command-args '( "-colors" "NoColor")))
(t
(setq python-python-command (concat python-base "/bin/python"))
(setq py-python-command (concat python-base "/bin/python"))
(setq py-python-command-args nil)))))
nil t)) ; buffer-local hack-local-variables-hook
i.e. python-mode-hook runs first and registers the anonymous function with hack-local-variables-hook for the current buffer only; and that function is then called after the local variables have been processed.
Lindydancer's comment prompts a third approach. It's not nearly as clean as the other two, but proved interesting regardless. I didn't like the idea of causing (hack-local-variables) to be called twice, but I see that if you set the local-enable-local-variables buffer-locally, it prevents (hack-local-variables) from doing anything, so you could do this:
(defun cr/python-mode-shell-setup ()
(report-errors "File local-variables error: %s"
(hack-local-variables)))
(set (make-local-variable 'local-enable-local-variables) nil)
(let ((python-base (cr/virtualenv)))
...))
Obviously that modifies the normal sequence of execution a little, so side effects may be possible. I was worried that if the same major mode is set by a local variable comment in the file, this might cause infinite recursion, but that doesn't actually appear to be a problem.
Local variable header comments (e.g. -*- mode: foo -*-) are handled by (set-auto-mode), so those are fine; but a mode: foo Local Variables: comment seems like it would be an issue as it is handled by (hack-local-variables), and so if the mode is set that way I thought it would cause recursion.
In practice I was able to trigger the problem by using a simple function as a 'mode' which did nothing more than try to run its hooks; however testing with a 'proper' mode did not exhibit the problem, so it's probably safe in reality. I didn't look into this further (as the other two solutions are much cleaner than this), but I would guess the delayed mode hooks mechanism probably explains it?

In emacs, how do I save without running save hooks?

I have various things set up in my 'before-save-hook. For example, I run 'delete-trailing-whitespace. This is what I want in almost all occasions.
But sometimes, I'm working on files that are shared with other people, and the file already has a bunch of trailing whitespace. If I save the file, I'll get a big diff that's pretty confusing, as my change is buried in dozens or hundreds of meaningless changes. Yes, everyone could just tell their diff tool to not show whitespace changes, but that's something that everyone has to do every time they look at the diff. I'd rather not even have the whitespace change.
Is there anything I can do to save the file without the whitespace changes, short of starting a new instance of Emacs with no init.el file, or with a modified init.el that doesn't have the hook?
Here is how I save without triggering delete-trailing-whitespace:
C-x C-q C-x C-s C-x C-q: read-only, save, revert read-only
A simpler solution I came up with is that my fundamental-mode has no hooks installed, because I want it to be as plain as possible. Thus if I want to save a file without running hooks, I temporarily switch to fundamental-mode.
Based on a comment discussion with #Stefan, here are two possible (untested) solutions:
Use let:
(defun save-buffer-without-dtw ()
(interactive)
(let ((b (current-buffer))) ; memorize the buffer
(with-temp-buffer ; new temp buffer to bind the global value of before-save-hook
(let ((before-save-hook (remove 'delete-trailing-whitespace before-save-hook)))
(with-current-buffer b ; go back to the current buffer, before-save-hook is now buffer-local
(let ((before-save-hook (remove 'delete-trailing-whitespace before-save-hook)))
(save-buffer)))))))
Use unwind-protect:
(defun save-buffer-without-dtw ()
(interactive)
(let ((restore-global
(memq 'delete-trailing-whitespace (default-value before-save-hook)))
(restore-local
(and (local-variable-p 'before-save-hook)
(memq 'delete-trailing-whitespace before-save-hook))))
(unwind-protect
(progn
(when restore-global
(remove-hook 'before-save-hook 'delete-trailing-whitespace))
(when restore-local
(remove-hook 'before-save-hook 'delete-trailing-whitespace t))
(save-buffer))
(when restore-global
(add-hook 'before-save-hook 'delete-trailing-whitespace))
(when restore-local
(add-hook 'before-save-hook 'delete-trailing-whitespace nil t)))))
The problem with the second solution is that the order of functions in the before-save-hook may change.
Here's another solution:
(defvar my-inhibit-dtw nil)
(defun my-delete-trailing-whitespace ()
(unless my-inhibit-dtw (delete-trailing-whitespace)))
(add-hook 'before-save-hook 'my-delete-trailing-whitespace)
and then
(defun my-inhibit-dtw ()
(interactive)
(set (make-local-variable 'my-inhibit-dtw) t))
so you can M-x my-inhibit-dtw RET in the buffers where you don't want to trim whitespace.
I wrote a command inspired by Nicholas Douma's solution.
(defun olav-save-buffer-as-is ()
"Save file \"as is\", that is in read-only-mode."
(interactive)
(if buffer-read-only
(save-buffer)
(read-only-mode 1)
(save-buffer)
(read-only-mode 0)))
What we need to do is remove 'delete-trailing-whitespace from before-save-hook, save the buffer, then add it back.
This code will do that, but only remove and add it if it's there to begin with.
;; save the buffer, removing and readding the 'delete-trailing-whitespace function
;; to 'before-save-hook if it's there
(defun save-buffer-no-delete-trailing-whitespace ()
(interactive)
(let ((normally-should-delete-trailing-whitespace (memq 'delete-trailing-whitespace before-save-hook)))
(when normally-should-delete-trailing-whitespace
(remove-hook 'before-save-hook 'delete-trailing-whitespace))
(save-buffer)
(when normally-should-delete-trailing-whitespace
(add-hook 'before-save-hook 'delete-trailing-whitespace))))
(global-set-key (kbd "C-c C-s") 'save-buffer-no-delete-trailing-whitespace)
It also binds the command to (kbd C-c C-s), for convenience.

How to automatically do org-mobile-push org-mobile pull in emacs

Since I am using org-mode to track my todo list in emacs, I like the iPhone app: MobileOrg, with it, I can access my todo list all day.
But here's the problem:
I have to manually org-mobile-push my changes from local file to mobile phone through dropbox, and org-mobile-pull the changes made by phone back.
How to make that automatically? Like adding some recipes in dotemacs file.
Add these two lines to dot emacs file:
(add-hook 'after-init-hook 'org-mobile-pull)
(add-hook 'kill-emacs-hook 'org-mobile-push)
With them, it automatically pulls the changes on emacs startup, and pushes the changes before emacs exits.
-- Update
If you never exit your Emacs, this solution might not work for you. So, another solution using idle timer
;; moble sync
(defvar org-mobile-sync-timer nil)
(defvar org-mobile-sync-idle-secs (* 60 10))
(defun org-mobile-sync ()
(interactive)
(org-mobile-pull)
(org-mobile-push))
(defun org-mobile-sync-enable ()
"enable mobile org idle sync"
(interactive)
(setq org-mobile-sync-timer
(run-with-idle-timer org-mobile-sync-idle-secs t
'org-mobile-sync)));
(defun org-mobile-sync-disable ()
"disable mobile org idle sync"
(interactive)
(cancel-timer org-mobile-sync-timer))
(org-mobile-sync-enable)
I just found out it is same as below answer, so, if you prefer the idle timer solution, please upvote tkf's answer.
I have something like this in my Emacs setting to do push and pull when I am away from computer.
(defvar my-org-mobile-sync-timer nil)
(defvar my-org-mobile-sync-secs (* 60 20))
(defun my-org-mobile-sync-pull-and-push ()
(org-mobile-pull)
(org-mobile-push)
(when (fboundp 'sauron-add-event)
(sauron-add-event 'my 3 "Called org-mobile-pull and org-mobile-push")))
(defun my-org-mobile-sync-start ()
"Start automated `org-mobile-push'"
(interactive)
(setq my-org-mobile-sync-timer
(run-with-idle-timer my-org-mobile-sync-secs t
'my-org-mobile-sync-pull-and-push)))
(defun my-org-mobile-sync-stop ()
"Stop automated `org-mobile-push'"
(interactive)
(cancel-timer my-org-mobile-sync-timer))
(my-org-mobile-sync-start)
Alternative is to put the following in cron job
(I found this here https://github.com/matburt/mobileorg-android/wiki/Scripting/):
emacs --batch --load ~/.emacs --eval "(org-mobile-pull)" --eval "(org-mobile-push)"
This code is taken from http://kenmankoff.com/2012/08/17/emacs-org-mode-and-mobileorg-auto-sync/, with a couple of details changed. You need to configure the variables in the beginning. This code will
Check every 30s whether MobileOrg has synced, and if so
Pull from MobileOrg.
Push to MobileOrg.
This is necessary to update the agenda views in MobileOrg.
With this behavior, you can be away from your computer, update some things in MobileOrg, sync, wait 30 seconds, sync again, and your mobile agenda view will be updated.
Whenever an org file is saved
Check whether the saved org file is supposed to be synced with MobileOrg, and if so
Wait for the user to become idle
Push to MobileOrg
Code for your .emacs file:
(require 'org-mobile)
;; Configure these two variables
(setq org-mobile-inbox-for-pull "~/Dropbox/org/mobile.org"
org-mobile-directory "~/Dropbox/MobileOrg")
(require 'gnus-async)
;; Define a timer variable
(defvar org-mobile-push-timer nil
"Timer that `org-mobile-push-timer' used to reschedule itself, or nil.")
;; Push to mobile when the idle timer runs out
(defun org-mobile-push-with-delay (secs)
(when org-mobile-push-timer
(cancel-timer org-mobile-push-timer))
(setq org-mobile-push-timer
(run-with-idle-timer
(* 1 secs) nil 'org-mobile-push)))
;; After saving files, start an idle timer after which we are going to push
(add-hook 'after-save-hook
(lambda ()
(if (or (eq major-mode 'org-mode) (eq major-mode 'org-agenda-mode))
(dolist (file (org-mobile-files-alist))
(if (string= (expand-file-name (car file)) (buffer-file-name))
(org-mobile-push-with-delay 10))))))
;; watch mobileorg.org for changes, and then call org-mobile-pull
(defun org-mobile-install-monitor (file secs)
(run-with-timer
0 secs
(lambda (f p)
(unless (< p (second (time-since (elt (file-attributes f) 5))))
(org-mobile-pull)
(org-mobile-push)))
file secs))
(defvar monitor-timer (org-mobile-install-monitor (concat org-mobile-directory "/mobileorg.org") 30)
"Check if file changed every 30 s.")
you can also push right after saving a note, like this:
(add-hook
'after-save-hook
(lambda ()
(if (string= buffer-file-name "<path to my notes.org>")
(org-mobile-push)
)
))
I use this elisp code from gist on my init.el and it works pretty well, except it doesn't have org-mobile-pull built in.
As a side solution, similar to Sandeep C's
;; for Emacs 24.3.1 insert next line
(require 'cl)
;; automatically org-mobile-push on save of a file
(add-hook
'after-save-hook
(lambda ()
(let (
(org-filenames (mapcar 'file-name-nondirectory (directory-files org-directory))) ; list of org file names (not paths)
(filename (file-name-nondirectory buffer-file-name)) ; list of the buffers filename (not path)
)
(if (find filename org-filenames :test #'string=)
(org-mobile-push)
)
)
)
)
I opted to simply push when saving, so I added this to my emacs init file:
(defun org-mobile-push-on-save ()
"Used in `after-save-hook'."
(when (memq this-command '(save-buffer save-some-buffers))
(org-mobile-push)))
(add-hook 'org-mode-hook
(lambda ()
(add-hook 'after-save-hook 'org-mobile-push-on-save nil 'make-local)))
In a nutshell, it adds an after-save-hook to org-mode buffers.
More info on the code:
https://emacs.stackexchange.com/a/14476/12694
https://stackoverflow.com/a/6141681/45881
For auto-pull, a timer as in other answers is probably a good way.

Using ediff with C-x s (save-some-buffers) in Emacs?

C-x s uses diff to show changes. How can I use ediff instead?
I can see a couple of approaches to doing this. The first is to replace the save-some-buffers-action-alist variable with modified code, which is more straightforward. The second is to advise save-some-buffers and redefine the functions called by those actions, but that's a bit trickier.
I tried it both ways, and I think this is the best option:
;; Use ediff instead of diff in `save-some-buffers'
(eval-after-load "files"
'(progn
(setcdr (assq ?d save-some-buffers-action-alist)
`(,(lambda (buf)
(if (null (buffer-file-name buf))
(message "Not applicable: no file")
(add-hook 'ediff-after-quit-hook-internal
'my-save-some-buffers-with-ediff-quit t)
(save-excursion
(set-buffer buf)
(let ((enable-recursive-minibuffers t))
(ediff-current-file)
(recursive-edit))))
;; Return nil to ask about BUF again.
nil)
,(purecopy "view changes in this buffer")))
(defun my-save-some-buffers-with-ediff-quit ()
"Remove ourselves from the ediff quit hook, and
return to the save-some-buffers minibuffer prompt."
(remove-hook 'ediff-after-quit-hook-internal
'my-save-some-buffers-with-ediff-quit)
(exit-recursive-edit))))
My attempt at using advice is flawed (it breaks the C-r behaviour which also calls view-buffer, which caused me to reconsider using advice for this purpose), but FWIW:
(defadvice save-some-buffers (around my-save-some-buffers-with-ediff)
"Use ediff instead of diff."
(require 'cl)
(flet ((view-buffer (&rest) nil)
(diff-buffer-with-file
(buf)
(add-hook 'ediff-after-quit-hook-internal
'my-save-some-buffers-with-ediff-quit t)
(save-excursion
(set-buffer buf)
(ediff-current-file))))
(let ((enable-recursive-minibuffers t))
ad-do-it)))
(ad-activate 'save-some-buffers)
(defun my-save-some-buffers-with-ediff-quit ()
"Remove ourselves from the ediff quit hook, and
return to the save-some-buffers minibuffer prompt."
(remove-hook 'ediff-after-quit-hook-internal
'my-save-some-buffers-with-ediff-quit)
(exit-recursive-edit))
The variable diff-command is customizable, says the documentation. However, remember that it points to an external program, and not an elisp function. ediff is an elisp function that is in ediff.el. You might have to edit diff.el to (require 'ediff) and then tweak here and there in diff.el to see that you break nothing else.