Change cursor to insert state while in minubuffer - emacs

I change my cursor based on state in evil. However I notice that when I type in the minibuffer I'm in normal mode.
I'm trying to make code that change the state from whatever it's in to insert state while I type in the minibuffer and switch back when I exit the minibuffer. Note, I use ivy for minibuffer completion (though I don't think it makes a difference).
(setq evil-insert-state-cursor '((bar . 3) "chartreuse3"))
(defun void-ivy-insert-state (orig-func &rest args)
"Wrapper around ivy, so it goes into insert state."
;; minibuffer is different so I have to manually change the state
(let ((saved-evil-state evil-state))
(evil-insert-state)
(setq cursor-type (elt evil-insert-state-cursor 0))
(set-cursor-color (elt evil-insert-state-cursor 1))
(apply orig-func args)
(evil-change-state saved-evil-state)))
(advice-add 'ivy-read :around #'void-ivy-insert-state)
I expect the cursor to be the right color and the write shape while typing something into the minibuffer. And to return to the appropriate shape of the state I was in before entering the minibuffer.
What actually happens is that the cursor is the right color, but it's the wrong shape. And if I exit the minibuffer with C-g insert state persists. It never returns to the original state. I think C-g aborts the execution of my advice.

I achieved the desired behavior with this code.
(add-hook 'minibuffer-setup-hook (lambda () (evil-insert-state)))
(add-hook 'minibuffer-exit-hook (lambda () (evil-normal-state)))
(define-key evil-insert-state-map [escape] (lambda () (interactive)
(evil-normal-state)
(minibuffer-keyboard-quit)))
The only annoying side effect is that whenever ESC is pressed No recursive edit is in progress is printed to the output.
The version below is the one I use in my code. Instead of returning to normal state, it uses a variable to return to the previous evil-state before the minibuffer was opened. Also it only uses minibuffer-keyboard-quit if the minibuffer is active.
(defvar evil-state-before-minibuffer-setup 'normal)
(add-hook 'minibuffer-setup-hook
(lambda () (setq evil-state-before-minibuffer-setup evil-state)
(evil-insert-state)))
(add-hook 'minibuffer-exit-hook (lambda ()
(evil-change-state evil-state-before-minibuffer-setup)))
(define-key evil-insert-state-map [escape]
(lambda () (interactive) (evil-normal-state)
(when (eq (active-minibuffer-window))
(selected-window))
(minibuffer-keyboard-quit))))
I make sure I only quit when the minibuffer is the selected window. Otherwise, the minibuffer would quit if we were to, say, edit a buffer while viewing the contents of the minibuffer.

Related

Keybindings specific to a certain buffer

I use a mode (merlin, but that doesn't matter) which opens a buffer with the name *merlin-type* when displays type information in it. I'd like to be able to type q in that buffer to close it. There's no mode specific to the buffer that I can hook into; what I'd like to do is create a buffer-local keybinding; how do I do this/what else should I be doing?
There are hooks, which are not mode-specific. For example
(add-hook 'post-self-insert-hook #'DWIM)
or
(add-hook 'post-command-hook #'DWIM)
Then
(defun DWIM ()
(when (string= MyPrefferedName (buffer-name (get-buffer (current-buffer))))
DoWhatIWant))
or
(defun DWIM ()
(when (buffer-live-p MyPrefferedBuffer)
DoWhatIWant))

how to jump to the newly created buffer/window automatically in Emacs

In compilation, occur search, grep search, etc., Emacs will create a new buffer in a separate window to show the results, is there anyway to jump to that window automatically? It is useful because then I can use n and p instead of M-g n and M-g p to move to next and previous items; plus, the buffer can be quit quickly with q. Currently I manually switch to the new buffer every time I run those commands, which is just annoying. Thanks.
You can use advice.
For example to jump to the grep buffer use the following advice:
(defadvice compilation-start (after compilation-start-maximize activate)
(when (equal mode 'grep-mode)
(switch-to-buffer "*grep*")
;; you may want to maximize the buffer
(delete-other-windows)))
For occur you can use the following advice
(defadvice occur-1 (after occur-maximize activate)
(other-window 1))
After some search, I came up with this solution without advising the built-in functions:
(add-hook 'occur-hook (lambda () (pop-to-buffer occur-buf)))
(add-hook 'grep-mode-hook (lambda () (pop-to-buffer (get-buffer "*grep*"))))
(setq help-window-select t)
(add-hook 'compilation-mode-hook (lambda () (pop-to-buffer (get-buffer "*compilation*"))))
It works for *Occur*, *grep*, *compilation* and *Help*.

emacs function behaves differently when bound to keymap

New to elisp and need help.
I have a simple function that pages down docview when the frame is split into two windows:
(defun noteview-pagedown ()
(interactive)
(with-selected-window (other-window-for-scrolling)
(doc-view-scroll-up-or-next-page nil)))
(defconst noteview-mode-keys
'(("C-M-v" . noteview-pagedown)))
; lifted from android-mode.el
(defvar noteview-mode-map (make-sparse-keymap))
(add-hook 'noteview-mode-hook
(lambda ()
(dolist (spec noteview-mode-keys)
(define-key
noteview-mode-map
(read-kbd-macro (concat noteview-mode-key-prefix " " (car spec)))
(cdr spec)))))
Left window has a text doc with this function defined. Right window has a pdf with docview open.
When I press C-M-v it runs correctly the first time then incorrectly the second time. It seems to do a page-down then a page-up alternately so I never progress to the next page.
When I run this function interactively with M-x noteview-pagedown it works.
Any hints on why this won't work from a keyboard macro would be appreciated.
You've defined a
noteview-mode-map
, but no
noteview-mode
. I'm unconvinced that this dangling map can ever do anything, unless you've defined the minor-mode else where.
This shouldn't be a minor-mode in any case, you appear to want to make C-M-v scroll other window, even when it's showing a doc-view buffer?
(defun my-scroll-up (arg)
(interactive "P")
(with-selected-window (other-window-for-scrolling)
(if (eq 'doc-view-mode major-mode)
(doc-view-scroll-up-or-next-page arg)
(scroll-up arg))))
(define-key (current-global-map) [remap scroll-up] 'my-scroll-up)
I know nothing about doc-view, but I just did C-h f doc-view-scroll-up-or-next-page, and it seems to say that in order for it to move to the next page you must have non-nil doc-view-continuous. Is that the case? Here's the doc:
Scroll page up ARG lines if possible, else goto next page.
When `doc-view-continuous' is non-nil, scrolling upward
at the bottom edge of the page moves to the next page.
Otherwise, goto next page only on typing SPC (ARG is nil).
HTH.

Enable auto-complete in Emacs minibuffer

I'm trying to turn auto-complete in the minibuffer:
(add-hook 'minibuffer-setup-hook 'auto-complete-mode)
What I get is auto-complete working in the first instance of minibuffer, but no longer. That is the full minibuffer-setup-hook after loading:
(auto-complete-mode turn-on-visual-line-mode ido-minibuffer-setup rfn-eshadow-setup-minibuffer minibuffer-history-isearch-setup minibuffer-history-initialize)
How to turn auto-complete on persistently?
You rarely ever want to add a function symbol to a hook variable if that function acts as a toggle (which will be the case for most minor modes).
minibuffer-setup-hook runs "just after entry to minibuffer", which means that you would be enabling auto complete mode the first time you enter the minibuffer; disabling it the second time; enabling it the third time; etc...
Typically you would either look to see if there's a pre-defined turn-on-autocomplete-mode type of function, or define your own:
(defun my-turn-on-auto-complete-mode ()
(auto-complete-mode 1)) ;; an argument of 1 will enable most modes
(add-hook 'minibuffer-setup-hook 'my-turn-on-auto-complete-mode)
I can't test that, because you haven't linked to the autocomplete-mode you are using.
The creator of "auto-complete-mode" explicitly excludes the minibuffer for use with auto completion. The definition for the minor mode is:
(define-global-minor-mode global-auto-complete-mode
auto-complete-mode auto-complete-mode-maybe
:group 'auto-complete)
so the "turn mode on" function is "auto-complete-mode-maybe" - the definition of that function is:
(defun auto-complete-mode-maybe ()
"What buffer `auto-complete-mode' prefers."
(if (and (not (minibufferp (current-buffer)))
(memq major-mode ac-modes))
(auto-complete-mode 1)))
This function explicitly tests in the if statement if the current-buffer is the minibuffer and doesn't turn on the auto-complete-mode if it is.
If you want to use auto-complete-mode in the minibuffer, you should probably contact the maintainer of the mode and ask him why he excluded the minibuffer and what programming changes he feels are necessary to enable the mode in the minibuffer.
Zev called to my attention auto-complete-mode-maybe, and that is the required modifications (file auto-complete.el, all changes have comments):
;; Add this variable
(defcustom ac-in-minibuffer t
"Non-nil means expand in minibuffer."
:type 'boolean
:group 'auto-complete)
...
(defun ac-handle-post-command ()
(condition-case var
(when (and ac-triggered
(not (ido-active)) ;; Disable auto pop-up in ido mode
(or ac-auto-start
ac-completing)
(not isearch-mode))
(setq ac-last-point (point))
(ac-start :requires (unless ac-completing ac-auto-start))
(ac-inline-update))
(error (ac-error var))))
...
(defun auto-complete-mode-maybe ()
"What buffer `auto-complete-mode' prefers."
(if (or (and (minibufferp (current-buffer)) ac-in-minibuffer) ;; Changed
(memq major-mode ac-modes))
(auto-complete-mode 1)))
And .emacs:
(add-hook 'minibuffer-setup-hook 'auto-complete-mode)
Certainly, there are binding conflicts but it is possible to solve them.

Is it possible to evaluate entire buffer in Emacs?

Currently, in order to evaluate elist in Emacs, I need to position the cursor on the last parenthesis and emit C-x e.
Is it possible to evaluate the entire buffer as a single elisp program without a need to position cursor?
M-x eval-buffer
or Alt+x and then type 'eval-buffer' or just type part of it and tab to autocomplete.
I placed this in my .emacs!
It allows you to eval a region if there is one or the entire buffer.
I bound it to C-xE.
(defun eval-region-or-buffer ()
(interactive)
(let ((debug-on-error t))
(cond
(mark-active
(call-interactively 'eval-region)
(message "Region evaluated!")
(setq deactivate-mark t))
(t
(eval-buffer)
(message "Buffer evaluated!")))))
(add-hook 'emacs-lisp-mode-hook
(lambda ()
(local-set-key (kbd "C-x E") 'eval-region-or-buffer)))
C-c C-l to load the entire file at once.