in Emacs, what's the best way for keyboard-escape-quit not destroy other windows? - emacs

EDIT: I understand there is keyboard-quit (which is normally bound to C-g); but I'm more interested to know about how one deals with editing functions that come with Emacs (like in this case). I run into this kind of situations from time to time when I want to change just a little bit of some build-in functions.
In emacs, when you hit M-ESC ESC (or ESC three times), you can get out of a lots of situations like transient-mark, etc. But I habitually hit the escape key (I actually remap this to a single hit of the escape key) more than I intended, and that ends up killing my windows configuration, which is quite annoying. The function keyboard-escape-quit is defined in simple.el:
(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)
(cond ((eq last-command 'mode-exited) nil)
((> (minibuffer-depth) 0)
(abort-recursive-edit))
(current-prefix-arg
nil)
((and transient-mark-mode mark-active)
(deactivate-mark))
((> (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))))
And I can see that I don't want the lines:
((not (one-window-p t))
(delete-other-windows))
But what is the best way to modify this function? I can see only two ways: 1) modify simple.el 2) copy this function to my .emacs file and do the modifications there. Both ways are not really good; ideally I would like to see something on the line of defadvice, but I can't see how I can do it in this case.

You could use around advice and redefine the offending function to do what you want (i.e. one-window-p should always return t):
(defadvice keyboard-escape-quit (around my-keyboard-escape-quit activate)
(let (orig-one-window-p)
(fset 'orig-one-window-p (symbol-function 'one-window-p))
(fset 'one-window-p (lambda (&optional nomini all-frames) t))
(unwind-protect
ad-do-it
(fset 'one-window-p (symbol-function 'orig-one-window-p)))))
This kind of acts like a (let ...) but has to be more complicated because you need to override a function for a limited scope instead of a variable.

I usually find that 'keyboard-quit (C-g) works to get out of all of those situations.
However, if you really want to have a variant of this function, I think that copying to your .emacs file (and renaming, I usually usa a prefix of bp) and making the edits there is probably the best option.
EDIT, in response to edit: In general, whenever I want an edited version of an emacs function, I either write it myself, or copy it to my .emacs, rename it bp-whotever and then do appropriate edits.
The downside of this is that my .emacs is HUGE, and probably extra-crufty with ancient functions that are nolonger used... the upside is that whenever I need to write something new, I've got tons of sample code to look at...

Here's another, simpler piece of advice that takes advantage of the fact that keyboard-escape-quit calls buffer-quit-function before closing windows:
(defadvice keyboard-escape-quit
(around keyboard-escape-quit-dont-close-windows activate)
(let ((buffer-quit-function (lambda () ())))
ad-do-it))
Works with Emacs 25.1. (I originally used #scottfrazer's advice, but it's unhappy in 25.1. Haven't bothered debugging yet.)

A single press of the Escape key, by default, acts as a Meta prefix key; that is, a keybinding which involves the Meta key.
Triple-pressing the Escape key will run keyboard-escape-quit, which is like keyboard-quit but with more of a "do what I mean" behaviour.
This code may help with your use case. You can use this in your Emacs init file:
;;; esc always quits
(define-key minibuffer-local-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-ns-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-completion-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-must-match-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-isearch-map [escape] 'minibuffer-keyboard-quit)
(global-set-key [escape] 'keyboard-quit)

I'm more interested to know about how one deals with editing functions that come with Emacs (like in this case). I run into this kind of situations from time to time when I want to change just a little bit of some build-in functions.
This is exactly the purpose for which I created the library el-patch. You would put this in your init-file:
(el-patch-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)
(cond ((eq last-command 'mode-exited) nil)
((> (minibuffer-depth) 0)
(abort-recursive-edit))
(current-prefix-arg
nil)
((and transient-mark-mode mark-active)
(deactivate-mark))
((> (recursion-depth) 0)
(exit-recursive-edit))
(buffer-quit-function
(funcall buffer-quit-function))
(el-patch-remove
((not (one-window-p t))
(delete-other-windows)))
((string-match "^ \\*" (buffer-name (current-buffer)))
(bury-buffer))))

Here's a new way using cl-lib instead of cl which is now deprecated:
;; Make it so keyboard-escape-quit doesn't delete-other-windows
(defadvice keyboard-escape-quit
(around keyboard-escape-quit-dont-delete-other-windows activate)
(cl-letf (((symbol-function 'delete-other-windows)
(lambda () nil)))
ad-do-it))
You'll need to make sure prior to it you have called:
(require 'cl-lib)

Related

switch buffer settings using python-mode in emacs?

I have been using emacs for a while but not so familiar with lisp programming. Its been just couple of days I started coding Python on emacs. I found python-mode to be quite useful and I want to explore it further. I found a few emacs lips functions on internet, tewaked them a bit to make the interface userfriendly. I am trying to achieve following actions
I usually start emacs with 2 vertical windows, one with python source and other is a shell. I should be able to do following using keyboard bindings
switch between buffers (working)
execute a region (working)
but replaces the source buffer with shell buffer. I want to execute selected region in original shell buffer.
execute a line (working)
but same issue as above. when i pres say , the line should be executed in python shell without replacing any buffers. so copy the line, switch to python shell, execute line, switch back to python source buffer.
I am not able to achieve switching action above. Following is my code from my init.el file
(defun goto-python-shell ()
"Go to the python command window (start it if needed)"
(interactive)
(setq current-python-script-buffer (current-buffer))
(if (boundp 'current-python-shell-buffer)
(switch-to-buffer-other-window current-python-shell-buffer)
(py-shell))
(end-of-buffer)
)
(defun goto-python-source ()
"switch back to source window"
(interactive)
(setq current-python-shell-buffer (current-buffer))
(switch-to-buffer-other-window current-python-script-buffer)
)
(defun py-execute-statement-and-step ()
"select a statement, submit as a region and then step forward"
(interactive)
(beginning-of-line 1)
(let ((beg (point)))
(py-next-statement 1)
; if last statement.
(if (= (point) beg) (end-of-buffer ))
; (switch-to-buffer-other-window current-python-shell-buffer)
(py-execute-region beg (point))
(switch-to-buffer-other-window current-python-script-buffer)
)
)
; some key bindings
(define-key python-mode-map (quote [f9]) 'py-execute-statement-and-step)
;(define-key python-mode-map (quote [f10]) `py-execute-region)
;py-shell-switch-buffers-on-execute
(define-key python-mode-map (quote [f10]) `py-shell-switch-buffers-on-execute)
(define-key python-mode-map (quote [f11]) `py-execute-buffer)
(define-key python-mode-map (quote [f12]) `goto-python-shell)
(define-key py-shell-map (quote [f12]) `goto-python-source)
Please advice.
Also since i am new to python-mode, can someone share nice initializations for using python-mode similar to above?
thanks much for your help.
Regards,
AJ
You should take a look at the first answer to this question and customize the py-shell-switch-buffers-on-execute variable.
This way you won't need all your custom functions to make python-mode work like you want (i.e. keeping the source buffer active)
I think that you are trying to reinvent what is available in Emacs 24 (at least with evaluation stuff). Try Emacs 24. When you are editing a Python source code, you can press C-c C-c to evaluate a buffer and press C-c C-r to evaluate a region. You don't have to explicitly start a Python shell.
I don't think that there is a direct support for evaluate a line and step. You can achieve it by the keystrokes C-SPC C-n C-c C-r. Your focus will remain in the source code and there is no need to switch explicitly between the source code and the shell.
FWIW, I have been using Emacs 24 for a reasonable amount of time on a daily basis and I haven't encountered any stability issues.
following changes are working like a charm. f9 does line by line execute and f10 does region based execution. curser remains in the script window after i disabled py-shell-switch-buffers-on-execute.
(defun py-execute-statement-and-step ()
"select a statement, submit as a region and then step forward"
(interactive)
(beginning-of-line 1)
(let ((beg (point)))
(py-next-statement 1)
; if last statement.
(if (= (point) beg) (end-of-buffer ))
(py-execute-region beg (point))
(next-line)
)
)
(custom-set-variables
'(py-shell-switch-buffers-on-execute nil))
(define-key python-mode-map (quote [f9]) 'py-execute-statement-and-step)
(define-key python-mode-map (quote [f10]) `py-execute-region)

Windows configuration to registers

I'm starting to use quite heavily the commands C-x r w and C-x r j to store windows configuration to registers and recall them at a later point, but I find a bit annoying that the cursor positions are stored as per the time when the window configuration was saved.
Basically I would like that the cursor positions are not stored (or are updated automatically), so that whenever I "jump" to a stored window configuration I get the same view as when I last visited it, not as when I created it.
Any ideas?
Ángel
I also found this very annoying and just coded up a solution. Store the window config using the normal functionality (current-window-configuration or window-configuration-to-register). Then, before applying the saved window config (or register),
Store the points of all open buffers.
Restore the window config.
Apply the stored points to the current windows.
The code below does this. You'll have to hook up restore-window-configuration to the register code yourself though.
(defun buffer-point-map ()
(save-excursion
(mapcar (lambda (buffer) (cons (buffer-name buffer)
(progn (set-buffer buffer) (point))))
(buffer-list))))
(defun apply-buffer-points (buff-point-map)
(mapc (lambda (window) (let* ((buffer (window-buffer window))
(buffer-point (cdr (assoc (buffer-name buffer) buff-point-map))))
(when buffer-point (set-window-point window buffer-point))))
(window-list))
nil)
(defun restore-window-configuration (window-config)
(let ((points (buffer-point-map)))
(set-window-configuration window-config)
(apply-buffer-points points)))
If you take a look into a source code
(defun window-configuration-to-register (register &optional arg)
...
(set-register register (list (current-window-configuration) (point-marker))))
you'll see that it stores a point as the second argument.
Just re-define it like
(defun my-window-configuration-to-register (register &optional arg)
(interactive "cWindow configuration to register: \nP")
(set-register register (list (current-window-configuration) nil)))
and redefine a C-x r w shortcut as well to use my-window-configuration-to-register
(define-key (current-global-map) (kbd "C-x r w") 'my-window-configuration-to-register)
Or define an advice
(defadvice window-configuration-to-register (after window-configuration-to-register-no-point activate)
"Avoid storing current buffer's position in the register. We want to stay on the last used position, not to jump to the saved one"
(set-register register (list (current-window-configuration) nil)))
The only problem is that it brings up an error message when you jump to it. You may redefine jump-to-register to avoid it
I'll add another answer which uses different approach.
Before you jump to another register you may store the current window configuration. This way it will store your latest buffers position just before you jump.
This will not work in all cases, however. For example if you just switch to another buffer or create a buffer with M-x dired or something then it will not store the current window config.
(defvar current-window-conf-register nil)
(defadvice window-configuration-to-register (after window-configuration-to-register-current-reg activate)
(setq current-window-conf-register register))
(defadvice jump-to-register (before jump-to-register-store-window-conf activate)
(if current-window-conf-register (window-configuration-to-register current-window-conf-register))
(setq current-window-conf-register register))
As a indirect answer to your question, you might consider using revive.el instead, which supports saving and restoring window configurations across Emacs restart, but doesn't (I believe) store the point.

In Emacs, can we make one keystroke to do different command?

I want to make one keystroke, say C-F12, to do delete-other-windows or winner-undo. I think it's easy if I already learning Emacs Lisp programming, and set a boolean flag. That is, if previously it run delete-other-window, now it'll run winner-undo.
How do you do that in Emacs Lisp?
Thanks
Try something like this
(setq c-f12-winner-undo t)
(define-key (current-global-map) [C-f12]
(lambda()
(interactive)
(if c-f12-winner-undo
(winner-undo)
(delete-other-windows))
(setq c-f12-winner-undo (not c-f12-winner-undo))))
(defun swdev-toggle-sole-window ()
(interactive)
(if (cdr (window-list))
(delete-other-windows)
(winner-undo)))
(global-set-key (kbd "<C-f12>") 'swdev-toggle-sole-window)
The first line starts the declaration of a function called swdev-toggle-sole-window, taking no argument.
This function is declared as interactive, i.e. it can be called with M-x or through a key binding.
If the window list contains more than one element, i.e. if there is more than one window, …
… then delete other windows …
… else undo the window deletion.
Bind the function to the key C-f12.
Here's a solution using the approach taken by Emacs' recenter-top-bottom function:
(defun delete-other-window-or-winner-undo ()
"call delete-other-window on first invocation and winner-undo on subsequent invocations"
(interactive)
(if (eq this-command last-command)
(winner-undo)
(delete-other-windows)))
(global-set-key (kbd "<C-f12>") 'delete-other-window-or-winner-undo)

Emacs : prevent from closing from window manager button

I very often open a lot of file system explorer windows (either under linux or windows). Then I make a big cleanup and close everything. Often, I also close Emacs by mistake.
I'd like to change the behaviour of the 'X' button to minimize instead of closing (leave closing to C-x C-c only). I'm almost sure it's possible, but I don't know how. Anyone to help?
One possible way to achieve this is to (ab-)use the confirm-kill-emacs mechanism: this is meant to be a function that asks the user for confirmation about killing emacs. However, instead of using an interactive function, you could introduce a special variable that is true only if the kill command has been invoked through C-x C-c, and the confirm function simple returns the value of that variable.
Put the following in your .emacs file:
(defvar killed-from-keyboard nil)
(setq confirm-kill-emacs '(lambda (prompt) killed-from-keyboard))
(defun save-buffers-kill-emacs-from-keyboard (&optional arg)
(interactive)
(condition-case nil
(progn (setq killed-from-keyboard t)
(save-buffers-kill-terminal arg))
((quit error)
(setq killed-from-keyboard nil))))
(global-set-key [(control x) (control c)] 'save-buffers-kill-emacs-from-keyboard)
If you advise the kill-emacs function, then you can get the functionality that you desire. I have code that makes my emacs frame invisible (hidden), but you can iconify it instead with code similar to the following.
(defvar bnb/really-kill-emacs nil)
(defadvice kill-emacs (around bnb/really-exit activate)
"Only kill emacs if a prefix is set"
(if bnb/really-kill-emacs
ad-do-it)
(iconify-frame))
(defun bnb/really-kill-emacs ()
(interactive)
(setq bnb/really-kill-emacs t)
(kill-emacs))
The bnb/really-kill-emacs function is defined so that you can actually kill emacs when necessary.

Suppress emacs auto-fill in a selected region

I use emacs to edit everything. On some of my LateX documents I would like to automatically disable auto-fill mode when I am editing tables and code. Basically, I'd like to have two tags, like:
%%% BEGIN NO FILL
%%% END NO FILL
and nothing between them will be autofilled.
Can anybody think of a way to do this? I would need to figure out whether or not the cursor is inside the region and then have to toggle the mode, and would need to do that every time the cursor moved. Or is there a better way to do it?
If you are using AUCTeX (you should be) then you may want to check out LaTeX-indent-environment-list. Adding an environment to this variable will make it so that (among other things) M-q doesn't refill the paragraph. Unfortunately it doesn't seem work for auto-fill-mode. The following largely untested code added to LaTeX-mode-hook might do what you want.
(setq auto-fill-function
(lambda ()
(unless (> (save-excursion (or (search-backward "%%% BEGIN NO FILL" (point-min) t) 0))
(save-excursion (or (search-backward "%%% END NO FILL" (point-min) t) 0)))
(do-auto-fill))))
It's very stupid and inefficient, but seems to be fast enough on my machine. It doesn't allow nesting, and requires that you manually mark up all sections that you don't want filled. What I am thinking of adding to my .emacs (until I read your question I didn't realize how much this bugged me) is below which keys off of the current environment so there is no need for special markup (though it only looks at the innermost environment (I'm not sure how much of a problem that will cause in practice)). Combining the two is left as an exercise to the interested reader.
;; You can use the following to unset the variables and play around with them
;; (makunbound 'auto-fill-ignore-environments)
;; (makunbound 'auto-fill-ignore-environments-regexp)
(defcustom auto-fill-ignore-environments
(mapcar 'car LaTeX-indent-environment-list)
"List of environments for which `auto-fill-mode' should be
disabled. Used to generate `auto-fill-ignore-environments-regexp'."
:type '(sexp)
)
(defcustom auto-fill-ignore-environments-regexp
(regexp-opt auto-fill-ignore-environments)
"Regexp matching LaTeX environments for which `auto-fill-mode'
should be disabled. If not set, automatically generated from
`auto-fill-ignore-environments'"
:type '(string)
:set-after '(auto-fill-ignore-environments)
)
(add-hook 'LaTeX-mode-hook
(lambda ()
(setq auto-fill-function
(lambda ()
(unless (string-match auto-fill-ignore-environments-regexp
(LaTeX-current-environment))
(do-auto-fill))))))
I have never used defcustom before so I'm sure that part could be improved quite a bit.
Got it. Check this out:
(defun in-no-auto-fill-region ()
(> (save-excursion (or (search-backward "%%% BEGIN NO FILL" (point-min) t) 0))
(save-excursion (or (search-backward "%%% END NO FILL" (point-min) t) 0))
))
(defun previous-line-checking-auto-fill (arg)
(interactive "P")
(previous-line arg)
(if (in-no-auto-fill-region)
(turn-off-auto-fill)
(turn-on-auto-fill)))
(defun next-line-checking-auto-fill (arg)
(interactive "P")
(next-line arg)
(if (in-no-auto-fill-region)
(turn-off-auto-fill)
(turn-on-auto-fill)))
(add-hook 'LaTeX-mode-hook
'(lambda nil
(local-set-key "C-p" 'previous-line-checking-auto-fill)
(local-set-key "C-n" 'next-line-checking-auto-fill)
(auto-fill-mode 1)
))
Alternately, you can turn off auto-fill-mode and use M-q to format paragraphs. I don't love auto-fill's jumpiness so I use this in every mode.
If you want to go the route of advising/redefining all the movement functions, this should help:
(defmacro movement-advice (func)
`(defadvice ,func (after ; run this after the original function is done (and point has moved)
;; Give it a unique name
,(intern (concat (symbol-name func) "-auto-fill-auto-off"))
;; Hopefully this satisfies the arguments of any function we can throw at it
(&rest args)
;; turn it on
activate
)
"Turn auto-fill-mode on or off automatically."
(auto-fill-mode (not (in-no-auto-fill-region)))))
(dolist (func '(next-line
previous-line
forward-paragraph
backward-paragraph
mouse-drag-region
;; Whatever you use
))
(eval `(movement-advice ,func)))