Emacs: How to yank the last yanked text regardless of subsequent kills? - emacs

I often find myself repeatedly yanking something after doing some kills and it becomes a process like:
C-y
C-y M-y
C-y M-y M-y
C-y M-y M-y M-y
Each time I kill some text it pushes the first kill back in the kill ring so that I need to cycle through all the kills to return to text I want to yank. What I want to do is repeatedly yank the same text while killing text in-between yanks. Is this possible?

Don't use the kill ring; put the text into a register instead. C-x r s a to store the region's text into (say) register "a"; then C-x r i a to insert it elsewhere.

This is a strange hack, but may help.
The first time you use M-y you normally get an error (no previous yank). So the idea is that this first time you get the last yank instead of the last kill.
For storing that last yank I use the 'Y' register in this example.
These 2 functions would wrap around yank and yank-pop. You expect bugs, I expect suggestions.
(defun jp/yank (&optional arg)
"Yank and save text to register Y"
(interactive)
(set-register ?Y (current-kill 0 t))
(yank arg))
(defun jp/yank-pop (&optional arg)
"If yank-pop fails, then insert register Y"
(interactive)
(condition-case nil
(yank-pop arg)
(error (insert (get-register ?Y)))))
(global-set-key (kbd "M-y") (quote jp/yank-pop))
(global-set-key (kbd "C-y") (quote jp/yank))

You could use M-x delete-region instead to kill the text, possibly binding it to a key if you want to use it a lot.

If you want to repeatedly yank the same text, use the secondary selection instead of the region or killed text.
What's missing from vanilla Emacs is a key binding to yank the secondary selection. I use C-M-y for that (see library second-sel.el).
To get direct access to any kills in the kill ring, use M-y with Browse Kill Ring or with Icicles.
In both cases, M-y at top level gives you access to all entries in the kill ring.
And if you use library second-sel.el then, in addition to the kill ring, you have access to a ring of your past secondary selections.
And if you use library second-sel.el and Icicles then M-y yanks an entry from the the ring you last yanked from (kill ring or secondary-selection ring).
And if you use library browse-kill-ring+.el then the kill-ring browser gives you access to an alternative ring also (which, by default, is the ring of secondary selections if you use library second-sel.el).

I'll try to use delete-region more, but I know the kill commands better. A trick that requires no programming or advance planning is to use M-w after a particularly annoying string of M-y. This puts a more accessible copy of the final yank into the kill ring.

A Better Yank-Pop Implementation
This defines a better yank-pop implementation which tries to fix the increasing yank-pop problem.
It only overrides the function "current-kill". Due to the modular design of yank, yank-pop, and the kill ring variables and functions in Emacs, it turns out that overriding "current-kill" is all that is necessary to get the behavior we want.
The desired behavior is that (1) killing something still puts it at the front of the kill ring, but now (2) yanking or yank-popping something also puts it at the front of the kill ring (3) we preserve the ability of yank-pop to give the appearance of moving through the kill ring by incrementing a global variable and using this to replace the last yank-pop'ped item back where it was. This also means that (4) items which are transitionally yanked (i.e. items placed by yank or yank-pop commands, where the next command is a yank-pop) ultimately get to stay where they are in the kill ring.
;; Example:
;; (setq kill-ring '("a" "b" "c" "d" "e"))
;;
;; keystroke kill ring contents value of kill-ring-yank-index
;; C-y ("a" "b" "c" "d" "e") 0
;; M-y ("b" "a" "c" "d" "e") 1
;; M-y ("c" "a" "b" "d" "e") 2
;; M-y ("d" "a" "b" "c" "e") 3
;; C-y ("d" "a" "b" "c" "e") 0
;; M-y ("a" "d" "b" "c" "e") 1
;; M-d ("x" "a" "d" "b" "c" "e")
;; etc.
the code:
;; ----------------------------------------------------------------
;; helper functions
(defun list-insert-before (l n x)
(if (<= n 0) (cons x l)
(cons (car l) (list-insert-before (cdr l) (- n 1) x))))
(defun list-prepend-nth (l n)
(if (<= n 0) l
(let* ((lx (list-prepend-nth (cdr l) (- n 1))))
(cons (car lx) (cons (car l) (cdr lx))))))
(defun list-insert-car-at (l n)
(list-insert-before (cdr l) n (car l)))
;; ----------------------------------------------------------------
;; overriding current-kill
(defvar kill-ring-yank-index 0
"Index into kill-ring of last yank-pop. The item yank-popped
will be at the head of the kill ring, but if the next command
is also yank-pop, it will be returned here first before this
variable is incremented.")
(defun current-kill (n)
"Replaces standard 'current-kill' function. This version tries
to fix the increasing yank-pop problem.
TODO:
- respect second argument of original function
- deal with 'interprogram-{cut,paste}-function'
"
(if (eq 0 n) ;; looks like we're doing a yank; reset
;; kill-ring-yank-index to 0 to indicate that the
;; current head of the list is useful to the user
(progn (setq kill-ring-yank-index 0)
(car kill-ring))
;; otherwise put the head of kill-ring back where we had
;; previously found it, and fetch the next element
(setq kill-ring
(list-insert-car-at kill-ring kill-ring-yank-index))
(setq kill-ring-yank-index (+ kill-ring-yank-index n))
(when (>= kill-ring-yank-index (- (length kill-ring) 1))
(setq kill-ring-yank-index (- (length kill-ring) 1))
(message "Reached end of kill-ring"))
(when (< kill-ring-yank-index 0)
(setq kill-ring-yank-index 0)
(message "Reached beginning of kill-ring"))
(setq kill-ring (list-prepend-nth kill-ring kill-ring-yank-index))
(car kill-ring)))
;; ----------------------------------------------------------------
;; new key binding
;; Here's an auxiliary function and key binding that makes it easy to
;; go back and forth in the kill-ring while we're yank-popping
(defun yank-pop-back () "" (interactive "*")
(yank-pop -1))
(global-set-key "\C-\M-y" 'yank-pop-back)

I am trying to hack along the line of using a minor mode. Let's call this delete-mode. Once you get into delete mode, kill commands (kill-line, kill-paragraph, kill-word, ...) will change their behavior so that the kill-region part of their commands will be replaced by delete-region, and new material will not be added to the kill ring. While in this mode, the kill ring will stay constant. When you switch back out of this mode, the behaviour returns to normal.
The following is an incomplete code attempting to implement what I wrote above. It works correctly in switching to delete mode, but it has problem switching back (turning the minor mode off). Any help fixing this would be appreciated.
(defvar delete-mode nil)
(defun delete-mode ()
"delete minor-mode"
(interactive)
(setq delete-mode (not delete-mode))
(if delete-mode
(defalias 'kill-region 'delete-region)
(defalias 'kill-region 'original-kill-region)
)
)
(if (not (assq 'delete-mode minor-mode-alist))
(setq minor-mode-alist
(cons '(delete-mode "Delete mode on") minor-mode-alist)
)
(defalias 'original-kill-region 'kill-region)
)

I use
M-x browse-kill-ring
with keybinding 'M-y'. There is also helm support.
https://www.emacswiki.org/emacs/BrowseKillRing
offers more solutions.

Related

How to hide the symbol $ when highlighting LaTeX equations in Emacs Org-mode?

I know that in Org-mode, the emphasis markers like *, ~, =, +, _ can be hidden by this setting: (setq org-hide-emphasis-markers t).
I wonder if there is any option that enables hiding the markers like $ or \(, \) of LaTeX?
This will be useful when LaTeX math equations can be highlighted by setting:
(setq org-highlight-latex-and-related '(latex script entities))
Update 1
I tried the solution proposed by #Thomas on a fresh emacs -q but somehow the symbol $ is still not hidden, while other markers like *,+ are. \
Not sure if there is something wrong with my Emacs? I'm using Org 9.3 of Emacs 27.1
Update 2
The solution of Thomas does work for Emacs 25.2!
But somehow, there is a major change in Emacs 26.2, 26.3, 27.1 that breaks this feature... :(
Update 3
Since the solution suggested by Thomas doesn't work with recent Emacs (26 or newer), I finally came up with a quick solution by customizing the function org-do-latex-and-related of Org-mode.
(defun org-do-latex-and-related (_limit)
"Highlight LaTeX snippets and environments, entities and sub/superscript.
Stop at first highlighted object, if any. Return t if some
highlighting was done, nil otherwise."
(when (org-string-nw-p org-latex-and-related-regexp)
(catch 'found
(while (re-search-forward org-latex-and-related-regexp
nil t) ;; on purpose, we ignore LIMIT
(unless (cl-some (lambda (f) (memq f '(org-code org-verbatim underline
org-special-keyword)))
(save-excursion
(goto-char (1+ (match-beginning 0)))
(face-at-point nil t)))
(let* ((offset (if (memq (char-after (1+ (match-beginning 0)))
'(?_ ?^))
1
0))
(start (+ offset (match-beginning 0)))
(end (match-end 0)))
(if (memq 'native org-highlight-latex-and-related)
(org-src-font-lock-fontify-block "latex" start end)
(font-lock-prepend-text-property start end
'face 'org-latex-and-related))
;;<<<<<<<<<<<<<<<<<<<<<
;; my code starts here
(when (and org-hide-emphasis-markers (< (+ start 4) end))
(cond ((member (buffer-substring start (+ start 2)) '("$$" "\\("))
(add-text-properties start (+ start 2) '(invisible org-link)))
((string= (buffer-substring (1+ start) (+ start 2)) "$")
(add-text-properties (1+ start) (+ start 2) '(invisible org-link))))
(cond ((member (buffer-substring end (- end 2)) '("$$" "\\)"))
(add-text-properties end (- end 2) '(invisible org-link)))
((string= (buffer-substring (1- end) (- end 2)) "$")
(add-text-properties (1- end) (- end 2) '(invisible org-link)))))
;; my code ends here
;;>>>>>>>>>>>>>>>>>>>>>
(add-text-properties (+ offset (match-beginning 0)) (match-end 0)
'(font-lock-multiline t)))
(throw 'found t)))
nil)))
If anyone interested in this feature, you can place the above function somewhere in your Emacs configuration file, after Org-mode is loaded, so that the new org-do-latex-and-related will override the original one of Org-mode.
Here is what I obtained using the code above:
An alternative approach is to not hide the $ symbol at all and instead use org-fragtog. It automatically toggles org-mode latex fragment previews as the cursor enters and exits them.
However, when you open a file with equations it will only toggle the preview of an equation as the cursor enters and leaves the equation. I also have a keybinding (f5) for org-latex-preview. If I open an org-mode file with many equations I can type C-u C-u f5 to toggle latex preview on all equations in the buffer. If I want to change some equation I can just move the cursor there and org-fragtog-mode will turn-off the preview. Then I can edit the equation and the cursor leaves the equation the preview will be automatically enabled again.
This also works correctly when org-highlight-latex-and-related is set to any of the possible choices as well as when you use prettify-symbols-mode.
Customize the variable org-emphasis-alist and add $ as an additional maker with the default values for all customization options. To do so, type
M-x customize-variable [RET] org-emphasis-alist [RET]
Then go to the bottom of the customization buffer, click on the last INS, and insert a dollar sign under Marker character:.
Finally, click on State to make this change permanent either for the current editing session only or also for all future sessions.
NOTE that you have to restart org-mode by typing M-x org-mode again in order for this change to take effect.

Why the function name that starts with "do-" gets highlighted in emacs?

I am using zenburn.el color-scheme in emacs 23. The function name that starts with "do-" gets highlighted, as given in the figure below --
How do I fix it? Any idea?
I do not observe this with Emacs 24.3 (the current development version).
The code which would have resulted in this highlighting is commented out in lisp-mode.el:
;; This is too general -- rms.
;; A user complained that he has functions whose names start with `do'
;; and that they get the wrong color.
;; ;; CL `with-' and `do-' constructs
;;("(\\(\\(do-\\|with-\\)\\(\\s_\\|\\w\\)*\\)" 1 font-lock-keyword-face)
So, what you need to do is:
(dolist (s (apropos-internal "lisp.*-font-lock" #'boundp))
(set s (cl-remove-if (lambda (l)
(let ((re (car l)))
(and (stringp re)
(string-match re "do-something"))))
(symbol-value s))))
or just edit lisp-mode.el, comment out the appropriate regexp, and rebuild.

Select to beginning / ending of word-wrapped visual line

The default behavior of the latest nightly builds of Aquamacs24 and Emacs-Trunk both appear to function differently than I'm accustomed -- i.e., command+shift+right or command+shift+left jumps to the beginning or end of the visual line without selecting the region. Instead, it is necessary to set the mark by moving the shift+left or shift+right or Ctrl+SPC to activate the mark and then go to the end or beginning of the visual line. In other words, it is a two step approach that needs to be combined into one-fell-swoop.
The following code almost does what I'm looking for, except that I'd like the selection to automatically cancel if I change my mind and release the shift key and move the arrow key. The way the code is presently written keeps the selection mode active and does not cancel unless I use a Ctrl+g.
Can anyone please suggest a modification to my code or an alternative way to achieve the desired behavior?
(defun beginning-of-visual-line (&optional n)
"Move point to the beginning of the current line.
If `word-wrap' is nil, we move to the beginning of the buffer
line (as in `beginning-of-line'); otherwise, point is moved to
the beginning of the visual line."
(interactive)
(if word-wrap
(progn
(if (and n (/= n 1))
(vertical-motion (1- n))
(vertical-motion 0))
(skip-read-only-prompt))
(beginning-of-line n)))
(defun end-of-visual-line (&optional n)
"Move point to the end of the current line.
If `word-wrap' is nil, we move to the end of the line (as in
`beginning-of-line'); otherwise, point is moved to the end of the
visual line."
(interactive)
(if word-wrap
(unless (eobp)
(progn
(if (and n (/= n 1))
(vertical-motion (1- n))
(vertical-motion 1))
(skip-chars-backward " \r\n" (- (point) 1))))
(end-of-line n)))
(defun command-shift-right ()
""
(interactive) ;; this is a command (i.e. can be interactively used)
(when (not (region-active-p)) ;; if the region is not active...
(push-mark (point) t t)) ;; ... set the mark and activate it
(end-of-visual-line)) ;; move point defined
(defun command-shift-left ()
""
(interactive) ;; this is a command (i.e. can be interactively used)
(when (not (region-active-p)) ;; if the region is not active...
(push-mark (point) t t)) ;; ... set the mark and activate it
(beginning-of-visual-line)) ;; move point defined
Emacs has built-in support for shift-select-mode: just use (interactive "^") in your functions and they'll select when triggered with a shift.

Looking forward a way to make cursor blinks like a heartbeat in Emacs

How can I make the cursor in Emacs blink like a heartbeat. Like the LED on the front panel of laptop when the computer is suspended.
There is variable blink-cursor-alist that control the blink of cursor, but I do not know how to use it to satisfy my requirement.
Is it possible?
This simple minor mode implements a heartbeat-style blinking cursor. You can tweak heartbeat-cursor-colors to get different hue or variations thereof.
The code is tested in Emacs 24.2.1, but would be easy to port to older Emacsen.
(require 'cl)
(require 'color)
(defvar heartbeat-fps 16)
(defvar heartbeat-period 5)
(defun heartbeat-range (from to cnt)
(let ((step (/ (- to from) (float cnt))))
(loop for i below cnt collect (+ from (* step i)))))
(defun heartbeat-cursor-colors ()
(let ((cnt (* heartbeat-period heartbeat-fps)))
(mapcar (lambda (r)
(color-rgb-to-hex r 0 0))
(nconc (heartbeat-range .2 1 (/ cnt 2))
(heartbeat-range 1 .2 (/ cnt 2))))))
(defvar heartbeat-cursor-timer nil)
(defvar heartbeat-cursor-old-color)
(define-minor-mode heartbeat-cursor-mode
"Change cursor color with the heartbeat effect."
nil "" nil
:global t
(when heartbeat-cursor-timer
(cancel-timer heartbeat-cursor-timer)
(setq heartbeat-cursor-timer nil)
(set-face-background 'cursor heartbeat-cursor-old-color))
(when heartbeat-cursor-mode
(setq heartbeat-cursor-old-color (face-background 'cursor)
heartbeat-cursor-timer
(run-with-timer
0 (/ 1 (float heartbeat-fps))
(lexical-let ((colors (heartbeat-cursor-colors)) tail)
(lambda ()
(setq tail (or (cdr tail) colors))
(set-face-background 'cursor (car tail))))))))
You guess that the option has something to do with the word "blink".
So you press C-h a (for apropos) and type "blink".
On my emacs, I get two options: blink-cursor-mode and blink-matching-open.
The first one looks right. The description says: "Toggle blinking cursor mode".
The shortcut on my emacs says: <menu-bar> <options> <blink-cursor-mode>.
So I guess that the option is somewhere in the menu, maybe under "options".
I open the Options menu, and there it is: "Blinking Cursor" with a tick box.
This also sounds like an option that can be customised.
So I type M-x customize-option and then blink-cursor-mode. This allows me to toggle the value and also save it for future sessions.
EDIT: To set the interval between ON and OFF for the cursor, there is a variable called blink-cursor-interval. You can use M-x customize-variable and then blink-cursor-interval to set the interval. The variable blink-cursor-alist matches an OFF state cursor type to the ON state cursor type, and is not related to the speed of blinking.
EDIT2: As far as I know there is no way to make the cursor gradually turn off and on, because the shape of the cursor for the ON state could be different to the shape in the OFF state (so a gradual change in shape will be required).

delete (NOT kill) a line in emacs. External clipboard is not appended to the kill ring

Many times I find myself in need of pasting a path from wherever to emacs' minibuffer. To clear the minibuffer fast I navigate to the beginning and do C-k (kill line).
This effectively overrides whatever path I had in the system clipboard with the temporary path I just killed in the minibuffer. Navigating the kill ring with M-y won't bring the path I had in the system clipboard.
Is there a way to delete the current line without killing it( i.e. removing it and adding it to the kill ring)?
So far I'm marking the line and pressing delete having delete-selection-mote active. I would like a one key solution similar to C-k.
As of Emacs 23.2, you can set save-interprogram-paste-before-kill to a non-nil value (hat tip Tyler) to copy the clipboard selection onto the kill ring, so that it is available via C-y M-y:
(setq save-interprogram-paste-before-kill t)
If you're on an older Emacs, the following advice has the same functionality:
(defadvice kill-new (before kill-new-push-xselection-on-kill-ring activate)
"Before putting new kill onto the kill-ring, add the clipboard/external selection to the kill ring"
(let ((have-paste (and interprogram-paste-function
(funcall interprogram-paste-function))))
(when have-paste (push have-paste kill-ring))))
And, you could do something like this (horrible keybinding, customize to suit) to delete the line from the point forward:
(define-key minibuffer-local-map (kbd "C-S-d") 'delete-line)
(defun delete-line (&optional arg)
(interactive "P")
;; taken from kill-line
(delete-region (point)
;; It is better to move point to the other end of the kill
;; before killing. That way, in a read-only buffer, point
;; moves across the text that is copied to the kill ring.
;; The choice has no effect on undo now that undo records
;; the value of point from before the command was run.
(progn
(if arg
(forward-visible-line (prefix-numeric-value arg))
(if (eobp)
(signal 'end-of-buffer nil))
(let ((end
(save-excursion
(end-of-visible-line) (point))))
(if (or (save-excursion
;; If trailing whitespace is visible,
;; don't treat it as nothing.
(unless show-trailing-whitespace
(skip-chars-forward " \t" end))
(= (point) end))
(and kill-whole-line (bolp)))
(forward-visible-line 1)
(goto-char end))))
(point))))
As of Emacs 23.2, this problem can be addressed with save-interprogram-paste-before-kill. If you set this variable to t then stuff in the clipboard gets added to the kill-ring, and isn't discarded by your next kill.
The documentation:
Save clipboard strings into kill ring before replacing them.
When one selects something in another program to paste it into Emacs,
but kills something in Emacs before actually pasting it,
this selection is gone unless this variable is non-nil,
in which case the other program's selection is saved in the `kill-ring'
before the Emacs kill and one can still paste it using C-y M-y.
From Xahlee's page, it shows several commands that are annoying.
(defun my-delete-word (arg)
"Delete characters forward until encountering the end of a word.
With argument, do this that many times.
This command does not push erased text to kill-ring."
(interactive "p")
(delete-region (point) (progn (forward-word arg) (point))))
(defun my-backward-delete-word (arg)
"Delete characters backward until encountering the beginning of a word.
With argument, do this that many times.
This command does not push erased text to kill-ring."
(interactive "p")
(my-delete-word (- arg)))
(defun my-delete-line ()
"Delete text from current position to end of line char."
(interactive)
(delete-region
(point)
(save-excursion (move-end-of-line 1) (point)))
(delete-char 1)
)
(defun my-delete-line-backward ()
"Delete text between the beginning of the line to the cursor position."
(interactive)
(let (x1 x2)
(setq x1 (point))
(move-beginning-of-line 1)
(setq x2 (point))
(delete-region x1 x2)))
; Here's the code to bind them with emacs's default shortcut keys:
(global-set-key (kbd "M-d") 'my-delete-word)
(global-set-key (kbd "<M-backspace>") 'my-backward-delete-word)
(global-set-key (kbd "C-k") 'my-delete-line)
(global-set-key (kbd "C-S-k") 'my-delete-line-backward)
There isn't.
from the GNU Emacs Manual:
We have already described the basic deletion commands C-d
(delete-char) and (delete-backward-char). See Erasing.
The other delete commands are those that delete only whitespace
characters: spaces, tabs and newlines. M-\ (delete-horizontal-space)
deletes all the spaces and tab characters before and after point. With
a prefix argument, this only deletes spaces and tab characters before
point. M- (just-one-space) does likewise but leaves a single
space after point, regardless of the number of spaces that existed
previously (even if there were none before). With a numeric argument
n, it leaves n spaces after point.
What about something like:
(defun del-line (p1)
(interactive "d")
(move-end-of-line 1)
(when (eq p1 (point)) ; special case when p1 is already at the end of the line
(forward-line))
(delete-region p1 (point)))
The behavior should be similar to C-k but without affecting the system clipboard or the kill-ring.
ETA: I read Trey's solution more carefully, and it looks like this is just a simple case of his solution. It worked in my (very!) limited tests, but probably fails for some special cases where the more complicated kill-line code works correctly.
Found an answer to this.
Posted it first here: https://unix.stackexchange.com/questions/26360/emacs-deleting-a-line-without-sending-it-to-the-kill-ring/136581#136581
;; Ctrl-K with no kill
(defun delete-line-no-kill ()
(interactive)
(delete-region
(point)
(save-excursion (move-end-of-line 1) (point)))
(delete-char 1)
)
(global-set-key (kbd "C-k") 'delete-line-no-kill)