Prevent Emacs from exiting once the exit procedure has initiated? - emacs

Is there a way to prevent Emacs from exiting once I initiate the exit process?
I occasionally fat finger C-xC-s as C-xC-c. It isn't an awful process to get back up and running but I am curious if there is a way I can stop the exit process so that I can continue uninterrupted with all my files open.
Using GNU Emacs 24.3.1. Running on Cygwin under Window 7.

There is a built-in variable you can set to a function like so:
(setq confirm-kill-emacs 'y-or-n-p)

scottfrazer's answer's the more appropriate, to me, than what follows.
Enable Emacs Lock minor mode (emacs-lock-mode) on any of the buffers, to prevent Emacs from exiting in case you accidentally hit C-xC-c.
From the Emacs Wiki page:
Emacs cannot exit until the buffer is killed or unlocked
Add (emacs-lock-mode) to your .emacs/init.el file so that this lock is enabled in every Emacs session. Adding this will lock the *scratch* buffer which will have to be unlocked in case you really want to exit Emacs.
Another way/hack of doing this is to start a process in Emacs e.g. M-xshell or have an unsaved file associated to a buffer, doing this will prompt you for confirmations when Emacs is exiting.
Yes one more, unset C-xC-c using global-unset-key. And then if you want to exit Emacs M-xkill-emacs.

Using confirm-kill-emacs, as #scottfrazer suggested, is one approach.
More generally, you can use kill-emacs-query-functions to do whatever you want in this regard. (There was no real need for them to add confirm-kill-emacs, but they did.)
You probably do not want to use kill-emacs-hook in this regard (that's what kill-emacs-query-functions is for), but be aware of it, in case you come across it using apropos etc.
One advantage of kill-emacs-query-functions over justconfirm-kill-emacs is that you can require a better confirmation: yes instead of just hitting key y. For example:
(add-hook 'kill-emacs-query-functions
(lambda () (y-or-n-p "Do you really want to exit Emacs? "))
'append)
That is what I do. It is too easy to be hitting keys and accidentally hit C-x C-c y, especially since I have similar keys bound (e.g., C-x c, C-x C-x, C-x C-y).

If you're looking for a shorter answer, I've had this line at the bottom of all my .emacs files since the last century:
(shell)

I've added the following to my emacs configuration to prevent accidental closes. I didn't like having to confirm close emacs for something like a one off commit, but I hate losing my emacs session accidentally while deep in a problem.
This adds a global state flag to emacs describing whether or not it's locked. This flag is set either automatically after emacs is open for 5 minutes, or manually using the lock-emacs command. The lock can later be removed manually by using the unlock-emacs command.
If emacs is locked, and you attempt to close it (presumably accidentally), emacs will instead give you a message saying that emacs has been locked, and cannot be closed. If it's unlocked, close behaves exactly as it does by default.
;; don't close emacs on accident
(setq emacs-locked nil)
(setq confirm-kill-emacs
(lambda (&rest args)
(if emacs-locked
(progn
(message "%s" "Emacs is locked, and cannot be closed.")
nil)
t)
))
(defun lock-emacs-silently ()
(progn
(setq emacs-locked t))
)
(defun lock-emacs ()
"Prevent emacs from being closed."
(interactive)
(progn
(lock-emacs-silently)
(message "%s" "Emacs is now locked."))
)
(defun unlock-emacs ()
"Allow emacs to be closed."
(interactive)
(progn
(setq emacs-locked 'nil)
(message "%s" "Emacs can now be closed."))
)
(run-at-time "5 minutes" nil 'lock-emacs-silently)
(Open to suggestions on how to make the confirm-kill-emacs portion nicer, I'm a lisp novice :) ).
After using this for a couple of years, I ended up going to something much simpler:
;; Unbind the normal close
(global-unset-key (kbd "C-x C-c"))
;; Require C-c 3 times before closing
(global-set-key (kbd "C-x C-c C-c C-c") 'save-buffers-kill-terminal)

Related

emacs terminal mode: how to copy and paste efficiently

I'm having a hard time making this emacs -nw work effectively under the terminal mode (emacs -nw).
Some setup information:
The working server is connected via SSH, and emacs is running on the server. Usually I'm connecting using SSH and "emacs -nw" to work on my files.
The emacs config is picked up from: https://hugoheden.wordpress.com/2009/03/08/copypaste-with-emacs-in-terminal/
;; make mouse selection to be emacs region marking
(require 'mouse)
(xterm-mouse-mode t)
(defun track-mouse (e))
(setq mouse-sel-mode t)
;; enable clipboard in emacs
(setq x-select-enable-clipboard t)
;; enable copy/paste between emacs and other apps (terminal version of emacs)
(unless window-system
(when (getenv "DISPLAY")
;; Callback for when user cuts
(defun xsel-cut-function (text &optional push)
;; Insert text to temp-buffer, and "send" content to xsel stdin
(with-temp-buffer
(insert text)
;; I prefer using the "clipboard" selection (the one the
;; typically is used by c-c/c-v) before the primary selection
;; (that uses mouse-select/middle-button-click)
(call-process-region (point-min) (point-max) "xsel" nil 0 nil "--clipboard" "--input")))
;; Call back for when user pastes
(defun xsel-paste-function()
;; Find out what is current selection by xsel. If it is different
;; from the top of the kill-ring (car kill-ring), then return
;; it. Else, nil is returned, so whatever is in the top of the
;; kill-ring will be used.
(let ((xsel-output (shell-command-to-string "xsel --clipboard --output")))
(unless (string= (car kill-ring) xsel-output)
xsel-output )))
;; Attach callbacks to hooks
(setq interprogram-cut-function 'xsel-cut-function)
(setq interprogram-paste-function 'xsel-paste-function)
;; Idea from
;; http://shreevatsa.wordpress.com/2006/10/22/emacs-copypaste-and-x/
;; http://www.mail-archive.com/help-gnu-emacs#gnu.org/msg03577.html
))
The reason to have:
(require 'mouse)
(xterm-mouse-mode t)
(defun track-mouse (e))
(setq mouse-sel-mode t)
is to enable mouse selection over text such that the text region is highlighted just as "C-x SPC" marking the region. Then I can use "M-x w" to copy and "C-x y" to paste text within emacs and between emacs and other apps.
All look perfect except that any operations related to X are REALLY SLOW! My connection to the remote server is smooth -- the latency is usually under 100ms. But to kill one line of text using "C-x k", it takes ~5 seconds! To paste it, it takes another 5 seconds!
When copy/paste is frequent sometimes, this becomes really annoying. I think this is related to the X sever messaging, but not sure if there is good way to fix this.
Any ideas?
Thanks!
This is not an ideal solution per se, but i figured out a way that I feel better than the previous one.
The idea is to get rid of X which causes heavy latency issues, i.e. keep only the following:
;; enable clipboard in emacs
(setq x-select-enable-clipboard t)
The results are:
copy/paste within Emacs is straightforward and fast.
copy from other apps to Emacs: Ctrl+Shift+v
copy from Emacs to other apps: mouse selection is now on X Selection, so right-click and copy shall copy the text into the Selection. Note that 'M-w" now won't copy anything into Selection or system clipboard.
This is again a compromise rather than a solution, but considering the fact that i copy/paste more often than inter-app operations, this is acceptable at the moment.
Still looking forward to a good solution!
You can accomplish this by using a terminal escape code!
There is a unique category of terminal escape codes called "Operating System Controls" (OSC) and one of these sequences (\033]52) is meant for interacting with the system clipboard. The great thing is that your terminal doesn't care where the code came from so it will work in remote sessions as well.
Most terminal emulators support it (iTerm2, OS X Terminal, and I think all Linux terminals besides GNOME). You can test if your terminal supports this sequence by simply running:
$ printf "\033]52;c;$(printf "Hello, world" | base64)\a"
Then paste from your system clipboard. If it pastes "Hello, world" then your terminal supports it!
I have this function in my init.el so when I call yank-to-clipboard Emacs will yank the value from my kill ring into the system clipboard:
(defun yank-to-clipboard ()
"Use ANSI OSC 52 escape sequence to attempt clipboard copy"
(interactive)
(send-string-to-terminal
(format "\033]52;c;%s\a"
(base64-encode-string
(encode-coding-string
(substring-no-properties
(nth 0 kill-ring)) 'utf-8) t))))
As I type this, I stumbled upon an almost-identical script supported by Chromium community: https://chromium.googlesource.com/apps/libapps/+/master/hterm/etc/osc52.el
For those running Emacs inside Tmux:
Tmux consumes the sequence, so you'll need to pipe the sequence to the Tmux active tty for this to work. I have a solution in my blog post here: https://justinchips.medium.com/have-vim-emacs-tmux-use-system-clipboard-4c9d901eef40
To extend on #justinokamoto's answer for use in tmux, it works great and is truly amazing. I haven't debugged it with e.g. tramp or other fancy emacs settings but to get it to work
Follow https://sunaku.github.io/tmux-yank-osc52.html great instructions, modifying your tmux.conf and ~/bin/yank
Make sure terminal access to your clipboard is enabled on your terminal
Then to pull into emacs you can use a function like:
(Caveat emptor, I am very new to elisp. This writes to a temporary file in /tmp/yank)
(defun custom-terminal-yank (&rest args)
(message "-> CLIP")
;; FOR EVIL MODE: UNCOMMENT SO FIRST YANKS TO KILL RING
;; need to yank first, with all those args
;; ;; https://emacs.stackexchange.com/questions/19215/how-to-write-a-transparent-pass-through-function-wrapper
;; (interactive (advice-eval-interactive-spec
;; (cadr (interactive-form #'evil-yank))))
;; (apply #'evil-yank args)
;; https://stackoverflow.com/questions/27764059/emacs-terminal-mode-how-to-copy-and-paste-efficiently
;; https://sunaku.github.io/tmux-yank-osc52.html
(f-write-text (nth 0 kill-ring) 'utf-8 "/tmp/yank")
(send-string-to-terminal (shell-command-to-string "~/bin/yank /tmp/yank"))
)
If anyone else uses evil mode as well (just to make things complicated) you can uncomment those lines and use something like
(define-key evil-visual-state-map "Y" 'jonah-terminal-yank)
So that normal "y" is for normal yanking in visual mode, but "Y" is for cross-clipboard yanking

How can I load changes of .el file at startup in Emacs?

I have installed Emacs under Windows 7 and want to use it in my everyday work. Unfortunately Emacs world and other text editors world are completely different and I am getting stuck on every third sequence of keys pressed on keyboard - it's doing something that I don't expect it would do.
I want to make a panic command - when I press ESC ESC ESC it stops doing everything, quitting from minibuffer, stops entering command, unhighlight regexps, etc. It already does what I want, except it killing buffers, the layout of my workspace. So I modified keyboard-escape-quit function in simple.el file (found it by C-h k ESC ESC ESC)
(defun keyboard-escape-quit ()
"Exit the current \"mode\" (in a generalized sense of the word).
This command can exit an interactive command such as `query-replace',
can clear out a prefix argument or a region,
can get out of the minibuffer or other recursive edit,
cancel the use of the current buffer (for special-purpose buffers),
or go back to just one window (by deleting all but the selected window)."
(interactive)
; Stop highlighting regexp
(unhighlight-regexp)
(cond ((eq last-command 'mode-exited) nil)
((region-active-p)
(deactivate-mark))
((> (minibuffer-depth) 0)
(abort-recursive-edit))
(current-prefix-arg
nil)
((> (recursion-depth) 0)
(exit-recursive-edit))
(buffer-quit-function
(funcall buffer-quit-function))
;((not (one-window-p t))
; (delete-other-windows))
((string-match "^ \\*" (buffer-name (current-buffer)))
(bury-buffer))))
I have byte-compiled and loaded this file and it works ok. But I can't figure out why it is not loading at startup.
You cannot modify some special built-in libraries, including simple.el. Emacs never actually loads these special libraries from their source or byte code files. Their byte code is directly included in the Emacs executable at build time, by a process called “dumping”. Emacs loads these libraries from its own binary.
Generally, should not modify any built-in libraries anyway. Your risk breakage, and your customizations are lost when you update Emacs.
Instead, do what you are supposed to do: Add custom functions to your init.el.
Hence, instead of modifying the built-in keyboard-escape-quit, create your own function, e.g. my-emergency-quit, in your init.el, and bind it to a global key, e.g. C-c q, with
(global-set-key (kbd "C-c q") #'my-emergency-quit)
Some final words of advice: I do not think that such a panic command does any good. The first rule of Emacs is: Don't panic. If you are stuck, don't try to quit and kill everything. Rather, try to find out why you are stuck, and how to get “un-stuck” by normal means. You'll learn Emacs better this way, imho.

How to properly configure Ctrl-Tab in Emacs

I converted from Visual Studio to Emacs for most of my development (mainly due to switching programming languages). However, there is one cool feature of Visual Studio that I truly miss: Ctrl-Tab between "buffers".
The ctrl-tab that in Visual Studio is not the same as C-x b in Emacs. So, it's not just a keyboard mapping issue. Here are the features of my ideal Ctrl-Tab:
Hold down ctrl hit tab, you see the next buffer before you let go of ctrl.
There is no need to hit enter.
If this is not the buffer you want, hit tab again until you see the buffer you want.
The moment that ctrl is released, the buffer ring is updated. The next buffer in the ring is the buffer where you first pressed ctrl.
I've seen some Emacs plugins that try to simulate this behavior, but #4 is the most difficult. It seems like Emacs is unable to detect when the ctrl key is released. Instead, the code waits for the user to be in the buffer for a certain time or waits for a buffer to change..and then the buffer is added to the ring. It's different enough to really frustrate me and just never use my beloved ctrl-tab again. For now I just deal with C-x b. ido-mode makes C-x b more tolerable, but I still dream of a day when I can ctrl-tab in emacs.
Has anyone out there found a way to configure Ctrl-Tab in Emacs to work like Visual Studio?
I was searching for exactly the behavior that you describe and came across
the iflipb package: http://www.emacswiki.org/emacs/iflipb and bound it to C-tab, C-S-tab.
Unfortunately it doesn't restart the cycling either after releasing the ctrl key, so in that regard is the same as the my-switch-buffer in the answer above. Any new insights into this issue are highly appreciated.
If you are using GNU Emacs 22.1 or more recent releases, \C-x<Right> fires M-x next-buffer and \C-x<Left> fires M-x previous-buffer. This page on EmacsWiki has a link to C-TAB Windows style buffer cycling. The page also talks about how to bring this behavior on older releases of Emacsen.
This question from yesterday looks very similar to what you want to achieve, except that the question talks about Notepad++ instead of Visual Studio.
I think this is close to what you want. As you mentioned, Emacs doesn't receive events for the control key, so you can't quite get the functionality you want. However, this will not record the buffer switch until you do something other than press C-tab (i.e. scroll, type something, click the mouse, use a command M-x ...):
(global-set-key (kbd "<C-tab>") 'my-switch-buffer)
(defun my-switch-buffer ()
"Switch buffers, but don't record the change until the last one."
(interactive)
(let ((blist (copy-sequence (buffer-list)))
current
(key-for-this (this-command-keys))
(key-for-this-string (format-kbd-macro (this-command-keys)))
done)
(while (not done)
(setq current (car blist))
(setq blist (append (cdr blist) (list current)))
(when (and (not (get-buffer-window current))
(not (minibufferp current)))
(switch-to-buffer current t)
(message "Type %s to continue cycling" key-for-this-string)
(when (setq done (not (equal key-for-this (make-vector 1 (read-event)))))
(switch-to-buffer current)
(clear-this-command-keys t)
(setq unread-command-events (list last-input-event)))))))
I like the cycling and toggling behavior of iflipb too, it's very much like Windows Alt-Tab behavior. However, as previously pointed out, Emacs doesn't make it easy to notice when you release the control key. This makes toggling between the top two buffers imperfect: if you press C-Tab (and release) and then C-Tab (and release), you haven't toggled between the top two. Instead, iflipb just marches further down the buffer list. But if you perform any other Emacs command between the two C-Tab events, then iflipb recognizes that it is starting over in the buffer march, so it does the toggle.
On Windows, AutoHotKey can come to the rescue and send Emacs a keystroke when you release the control key. Here's my script:
#if WinActive("ahk_class Emacs")
^Tab::
Send {Blind}^{Tab}
SetTimer, WaitForCtrlUp, 10
return
WaitForCtrlUp:
if(!GetKeyState("LControl", "P") and !GetKeyState("RControl","P"))
{
if WinActive("ahk_class Emacs")
Send ^c:
SetTimer, WaitForCtrlUp, Off
}
return
Whenever C-Tab is pressed in emacs, the script starts polling the state of the control key. When the key is released, it sends Emacs the C-c : key sequence. I have that key bound to a "null" command, which is enough to get iflipb to notice what's going on.
Here's the relevant .emacs excerpt:
; see http://www.emacswiki.org/emacs/iflipb
(require 'iflipb)
(global-set-key (kbd "<C-tab>") 'iflipb-next-buffer)
(global-set-key
(if (featurep 'xemacs) (kbd "<C-iso-left-tab>") (kbd "<C-S-tab>"))
'iflipb-previous-buffer)
(defun null-command ()
"Do nothing (other than standard command processing such as remembering this was the last command executed)"
(interactive))
(global-set-key "\C-c:" 'null-command)
So, it's kind of hacky, but it does work. Thanks to the posters at http://www.autohotkey.com/board/topic/72433-controltab/, who were trying to solve a similar problem.
Add the following to your .emacs file:
(global-set-key (kbd "<C-tab>") 'next-buffer)

How can I easily reload Emacs lisp code as I am editing it?

As an Emacs beginner, I am working on writing a minor mode. My current (naive) method of programming elisp consists of making a change, closing out Emacs, restarting Emacs, and observing the change. How can I streamline this process? Is there a command to refresh everything?
You might try using M-C-x (eval-defun), which will re-evaluate the top-level form around point. Unlike M-x eval-buffer or C-x C-e (exal-last-sexp), this will reset variables declared with defvar and defcustom to their initial values, which might be what's tripping you up.
Also try out C-u C-M-x which evaluates the definition at point and sets a breakpoint there, so you get dropped into the debugger when you hit that function.
M-x ielm is also very useful as a more feature-rich Lisp REPL when developing Emacs code.
M-x eval-buffer should do it.
What Sean said. In addition, I have (eval-defun) bound to a key, along with a test. The development loop then becomes: 1) edit function, 2) press eval-and-test key, 3) observe results, 4) repeat. This is extremely fast.
During development I write a test, bind it to jmc-test, then use the above key to run it on my just-edited function. I edit more, then press key again, testing it again. When the function works, I zap jmc-test, edit another function, and write another jmc-test function. They're nearly always one line of code, so easy to just bang out.
(defun jmc-eval-and-test ()
(interactive)
(eval-defun nil)
(jmc-test))
(define-key emacs-lisp-mode-map (kbd "<kp-enter>") 'jmc-eval-and-test)
(when t
(defun myfunc (beer yum)
(+ beer yum))
(defun jmc-test () (message "out: %s" (myfunc 1 2))))
When editing "myfunc", if I hit keypad enter, it prints "out: 3".
It all depends on what you're writing and how you've written it. Toggling the mode should get you the new behavior. If you're using [define-minor-mode][1], you can add code in the body of the macro that keys off the mode variable:
(define-minor-mode my-minor-mode
"doc string"
nil
""
nil
(if my-minor-mode
(progn
;; do something when minor mode is on
)
;; do something when minor mode is off
)
But, another way to check it quickly would be to spawn a new Emacs from your existing one:
M-x shell-command emacs&
I just define a function called ldf (short for load-file) in my .emacs file,
like this:
(defun ldf (arg) (interactive "P") (load-file (buffer-file-name)))
As you can see, this little function looks up the filename of the current buffer and then loads the file. Whenever I need to reload the current buffer elisp file, just type "M-x ldf"

How to do use C-x k to kill an Emacs buffer opened in server mode?

I use windows batch file to open files in an already-running instance of Emacs using emacsclientw.exe. However, any file opened that way is opened in server mode, which means that I have to use C-x # to kill it, instead of the usual C-x k. How do I change this behavior?
My solution was to rebind it (well M-w actually) to:
(lambda ()
(interactive)
(if server-buffer-clients
(server-edit)
(kill-this-buffer)))
[edit: having now read the code for server-edit, it might be better to use server-done (depending on what you want). server-edit will switch you to a server-edited buffer (if any still exist) but server-done will simply switch you to the next buffer. You could also use the output of server-done to see if the buffer was actually killed (not the case if the file was open before invoking emacsclient) and then kill it if not. Or use server-kill-buffer as suggested elsewhere.]
Here is what i put in my .emacs to do this :
(add-hook 'server-switch-hook
(lambda ()
(local-set-key (kbd "C-x k") '(lambda ()
(interactive)
(if server-buffer-clients
(server-edit)
(ido-kill-buffer))))))
Like this C-x k work the usual way when i'm not finding a file from emacsclient (which for me is ido-kill-buffer), and if i'm using emacsclient, C-x k does server-edit if the client is waiting, or run ido-kill-buffer otherwise (if i used emacsclient -n).
use:
D:\> emacsclientw -n foo.txt
the -n says "no wait". This is in GNU Emacs 22.2.1 (i386-mingw-nt5.1.2600) of 2008-03-26 on RELEASE (and many prior versions, IIRC).
You know, I hate to suggest workarounds instead of a real solution... but after reading the server code, I am confused as to how emacs even determines that a buffer is a server buffer.
With that in mind, why not open up files like:
emacsclient --eval '(find-file "/path/to/file")'
This way emacs doesn't know that your buffer was opened via emacsclient, which sounds like what you really want.
Edit:
I'm not really happy with this, but it seems to work:
(global-set-key (kbd "C-x k") (lambda () (interactive) (server-kill-buffer (current-buffer))))
Okay, THIS did work for me:
(global-set-key (kbd "C-x k") '(lambda ()
(interactive)
(if server-buffer-clients
(server-done)
(kill-this-buffer))))
(this is the code from IvanAndrus's answer with the explicit changes from edits and comments, and using jrockway's keybinding.)
And, yes -- I am rebinding a standard keybinding. BUT it's a functional replacement NOT something completely different (eg, replacing kill-ring-save with kill-buffer stuff).
BTW, EmacsWiki has a couple of pages on this topic-- KillKey and KillingBuffer -- neither of which shed better light for me than the above (although the first-function on KillKey also used "server-edit"...).
I am not sure if that will work on windows, but on linux, emacs -daemon is just great.
With it, you don't have to run a different program, and your bindings are the same. I guess there are other advantages, but since I could never learn those emacsclient bindings, I never really used it, and can't say.
I don't think -daemon had been released yet, I am using 23.0.60.1 from CVS.