branch: elpa/crux
commit e42f5558199576628e827a6e3db29eae56f4126a
Author: thdox <th...@free.fr>
Commit: Bozhidar Batsov <bozhi...@batsov.dev>

    Add the Do What I Mean keyboard-quit function.
    
    For this version, credits goes to protesilaos
    https://www.reddit.com/r/emacs/comments/1h1zyhz/comment/lzfhu63.
    Others versions exists, for example in helm or doom packages.
---
 CHANGELOG.md |  1 +
 README.md    |  2 ++
 crux.el      | 25 +++++++++++++++++++++++++
 3 files changed, 28 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index da7fa50522..713a104e99 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
 ## master (unreleased)
 
 * [#101](https://github.com/bbatsov/crux/pull/101): Add 
`crux-find-current-directory-dir-locals-file`.
+* Add `crux-keyboard-quit-dwim`.
 
 ### Bugs fixed
 
diff --git a/README.md b/README.md
index 72808cf82d..e71a9ca6fe 100644
--- a/README.md
+++ b/README.md
@@ -94,6 +94,7 @@ Command                                             | 
Suggested Keybinding(s)
 `crux-downcase-region`                              | <kbd>C-x C-l</kbd> | 
`downcase-region` when `transient-mark-mode` is on and region is active.
 `crux-capitalize-region`                            | <kbd>C-x M-c</kbd> | 
`capitalize-region` when `transient-mark-mode` is on and region is active.
 `crux-other-window-or-switch-buffer`                | <kbd>M-o</kbd>     | 
Select other window, or switch to most recent buffer if only one windows.
+`crux-keyboard-quit-dwim`                           | <kbd>C-g</kbd>     | 
`keyboard-quit` close the minibuffer or completions buffer even without 
focusing it.
 
 Here's how you'd bind some of the commands to keycombos:
 
@@ -104,6 +105,7 @@ Here's how you'd bind some of the commands to keycombos:
 (global-set-key (kbd "s-r") #'crux-recentf-find-file)
 (global-set-key (kbd "C-<backspace>") #'crux-kill-line-backwards)
 (global-set-key [remap kill-whole-line] #'crux-kill-whole-line)
+(global-set-key [remap keyboard-quit] #'crux-keyboard-quit-dwim)
 ```
 
 For `crux-ispell-word-then-abbrev` to be most effective you'll also need to 
add this to your config:
diff --git a/crux.el b/crux.el
index 3b50f08e00..17fa21afd1 100644
--- a/crux.el
+++ b/crux.el
@@ -619,6 +619,31 @@ as the current user."
   (interactive)
   (insert (format-time-string "%c" (current-time))))
 
+;;;###autoload
+(defun crux-keyboard-quit-dwim ()
+  "Do-What-I-Mean behaviour for a general `keyboard-quit'.
+
+The generic `keyboard-quit' does not do the expected thing when
+the minibuffer is open.  Whereas we want it to close the
+minibuffer, even without explicitly focusing it.
+
+The DWIM behaviour of this command is as follows:
+
+- When the region is active, disable it.
+- When a minibuffer is open, but not focused, close the minibuffer.
+- When the Completions buffer is selected, close it.
+- In every other case use the regular `keyboard-quit'."
+  (interactive)
+  (cond
+   ((region-active-p)
+    (keyboard-quit))
+   ((derived-mode-p 'completion-list-mode)
+    (delete-completion-window))
+   ((> (minibuffer-depth) 0)
+    (abort-recursive-edit))
+   (t
+    (keyboard-quit))))
+
 ;;;###autoload
 (defun crux-recentf-find-file (&optional filter)
   "Find a recent file using `completing-read'.

Reply via email to