I expect this elisp function to visualize entire function, but it visualizes beginning to cursor - emacs

It looks like the function that I use is not correctly visualizing the entire function. Currently, the function only visually highlights the region from the beginning of the function to the current buffer cursor position.
I want to modify this function to select the function, from top to bottom.
(defun evil-visual-current-function ()
"Highlight the entire current function in Evil's visual mode."
(interactive)
(let ((function-name (which-function)))
(if function-name
(progn
(beginning-of-defun)
(evil-visual-make-selection (point) (end-of-defun) (point)))
(message "Not inside a function"))))

When you leave the save-excursion block, the cursor moves back to the original position, which changes the selected region. Change the function to:
(defun evil-visual-current-function ()
"Highlight the entire current function in Evil's visual mode."
(interactive)
(let ((function-name (which-function))
(if function-name
(progn
(beginning-of-defun)
(evil-visual-make-selection (point) (end-of-defun) (point)))
(message "Not inside a function"))))

Related

Change cursor to insert state while in minubuffer

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.

Apply delete-indentation to a whole region

The function delete-indentation, usually bound to (M-^), joins the current line to the next one and deletes any indentation.
How do I apply this function to a whole region to join multiple lines in a region?
Or is there another way to achieve the desired result?
Thanks
Try unfill-paragraph, taken from the Emacs wiki.
;;; An unfill-paragraph that works in lisp modes
(defun unfill-paragraph (&optional region)
"Takes a multi-line paragraph and makes it into a single line of text."
(interactive (progn (barf-if-buffer-read-only) '(t)))
(let ((fill-column (point-max))
(emacs-lisp-docstring-fill-column t))
(fill-paragraph nil region)))
If you're willing to give up the prefix argument of the standard M-^, you could bind the following function to that keyboard shortcut like so:
(defun join-line-or-unfill-paragraph (&optional unfill)
(interactive "P")
(if unfill (unfill-paragraph) (delete-indentation)))
(global-set-key (kbd "M-^") 'join-line-or-unfill-paragraph)
This way, whenever you type C-u before M-^ the full paragraph will be joined.

Using split-window-below in Emacs. How to get buffer of bottom window?

For instance, when editing an Emacs lisp file test.el, I would like to mark a text (for instance the name of a function) in the current buffer (I am using a single frame with a single window) then press a keyboard shortcut to split the current window into two parts, one above the other. The top window should display my orginal buffer as it was, the bottom window should display the buffer at the point where the function is defined (like (defun test-fun ...).
I have tried this code:
(defun test-split ()
(interactive)
(split-window-below 28)
(let (( w (next-window)))
(let ((buf (window-buffer w)))
(with-current-buffer buf
(beginning-of-buffer)
(re-search-forward "defun test-fun ")))))
but it does not work.. (It searches the top window, not the bottom window)
The two windows are displaying the same buffer, so with-current-buffer is valid for the original window, and hence there is no need for Emacs to switch to another window.
You could modify your code like so:
(defun test-split ()
(interactive)
(split-window-below 28)
(save-selected-window
(select-window (next-window))
(beginning-of-buffer)
(re-search-forward "defun test-fun ")))

Set default value of replace-string in Emacs by selecting a word

I'm using function like this to replace strings in Emacs.
(defun replace-string-from-top ()
(interactive)
(save-excursion
(beginning-of-buffer)
(call-interactively 'replace-string)))
(global-set-key "\C-r" 'replace-string-from-top)
And I want to use default value of replace-string function by selecting a word.
What I want to do is.
select a word by double clicking it.
call replace-string-from-top function with the selected word by default value.
I've tried to write the function but I couldn't.
How can I do it?
Neither replace-string nor the function that it uses to read its args when you call it interactively, which is query-replace-read-args, has any provision for providing a default programmatically in a dynamic way. The most you can do is set variable query-replace-defaults. You can bind that variable to a value in your command, so that the first element in its list value is the string from the region, i.e.:
(let* ((region-string (buffer-substring (region-beginning) (region-end))))
(query-replace-defaults (cons region-string region-string)))
...)
(The value is a cons. Use whatever other value you like as the cdr. Here I've just used the same region string.)
But you can more easily and more directly do what you want if you use library replace+.el. In that case, just set option search/replace-region-as-default-flag to non-nil to get what you want. You can also toggle that option anytime, using command toggle-search/replace-region-as-default. A description of the library is here.
Here's my setup. You can change it in a few places, like add beginning-of-buffer, if you want.
(defvar qr-beg)
(defun string-dwim ()
(let ((bounds
(if (region-active-p)
(cons (region-beginning)
(region-end))
(ignore-errors
(bounds-of-thing-at-point 'symbol)))))
(setq qr-beg (car bounds))
(when (region-active-p)
(set-mark nil))
(when qr-beg
(kill-new
(buffer-substring-no-properties
qr-beg
(cdr bounds))))))
(defun query-replace-dwim (from)
(interactive
(list
(read-regexp "Query replace" (string-dwim))))
(when qr-beg
(goto-char qr-beg)
(setq qr-beg))
(query-replace
from
(query-replace-read-to from "Query replace" nil)))
As you can see, this is a setup for query-replace.
It auto-suggests the thing to be replaced as the current string.
The current string is either the current region, if it's active, or symbol at point.
Also, the current string is kill-newed, so you can yank it as the replacement,
and then just tweak it a bit.

Replace region with result of calling a function on region

How would I write an interactive function that takes a function and replaces the currently selected region with the result of calling that function on the region.
I see this answer:
https://stackoverflow.com/a/6539916/625365
But that's calling the function once per line, not giving it the region as an argument, and it seems like a lot of code.
I think you could do some trickery around filter-buffer-substring, but that seems like an obscure function, at least to me. On the other hand, doing so in Emacs Lisp directly doesn't seem complicate:
(defun apply-function-to-region (fn)
(interactive "XFunction to apply to region: ")
(save-excursion
(let* ((beg (region-beginning))
(end (region-end))
(resulting-text
(funcall
fn
(buffer-substring-no-properties beg end))))
(kill-region beg end)
(insert resulting-text))))
Then you can use a function that accepts and produces text (say capitalize), and capitalize the region. The function will ask for a function to apply. Finally, the deleted text is saved in the kill ring.
(defun apply-to-region (func)
(unless (use-region-p)
(error "need an active region"))
(delete-region (region-beginning) (region-end))
(insert (funcall func)))
(defun foo ()
""
"foobar")
(defun my/test ()
(interactive)
(apply-to-region 'foo))
To test it, select some text and run M-xmy/testRET.