From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Frederik Eaton Newsgroups: gmane.emacs.help,gmane.emacs.bugs Subject: yank-pop problem Date: Thu, 6 Aug 2015 00:38:31 -0700 Message-ID: <20150806073831.GA4560@ofb.net> Reply-To: frederik@ofb.net NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1438866338 21172 80.91.229.3 (6 Aug 2015 13:05:38 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 6 Aug 2015 13:05:38 +0000 (UTC) Cc: bug-gnu-emacs@gnu.org To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Thu Aug 06 15:05:28 2015 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1ZNKrO-0002SX-6N for geh-help-gnu-emacs@m.gmane.org; Thu, 06 Aug 2015 15:05:26 +0200 Original-Received: from localhost ([::1]:45029 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZNKrN-0000pk-Jk for geh-help-gnu-emacs@m.gmane.org; Thu, 06 Aug 2015 09:05:25 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:48885) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZNFlC-0005zw-12 for help-gnu-emacs@gnu.org; Thu, 06 Aug 2015 03:38:44 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZNFlA-0006Hf-FC for help-gnu-emacs@gnu.org; Thu, 06 Aug 2015 03:38:41 -0400 Original-Received: from ofb.net ([64.13.131.34]:54668) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZNFl3-0006DR-MD; Thu, 06 Aug 2015 03:38:33 -0400 Original-Received: by ofb.net (Postfix, from userid 30017) id B2A1D20706E5; Thu, 6 Aug 2015 00:38:31 -0700 (PDT) Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 64.13.131.34 X-Mailman-Approved-At: Thu, 06 Aug 2015 09:05:14 -0400 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:106291 gmane.emacs.bugs:105327 Archived-At: Dear Help-Gnu-Emacs, I was chatting on the #emacs freenode.net IRC channel and thought to ask people about a long-standing annoyance I've had with Emacs. One IRC user was horrified that I would find anything wrong with Emacs, but another user suggested that I write up a document with the details and send it as a bug report. So I wrote up a document which explains the issue and how I think it should be fixed. I'm pasting it below and would appreciate your comments. Mostly I'm looking to see if anyone else has previously implemented this suggestion, and is willing to share their code. I hope my thoughts are explained clearly enough. Thanks! Frederick P.S. I Cc'ed bug-gnu-emacs@gnu.org because I figured problems go there, but I haven't subscribed to that list and I'm not really expecting the core of Emacs to be changed. P.P.S. After writing this (typically of me) I just noticed that somebody else posted this problem on stackoverflow.com in 2011! However, none of the solutions posted there are really suitable in my opinion. The basic problem, which is that Emacs puts stuff you don't care about in the kill ring ahead of stuff that you do care about, isn't ever fixed. Although the first ("jp/yank") solution is nearly good enough, it still allows text we care about to get clobbered if there is an intervening yank... http://stackoverflow.com/questions/5823495/emacs-how-to-yank-the-last-yanked-text-regardless-of-subsequent-kills ---------------------------------------------------------------- Emacs Yank Pointer Problem Description Problem: In Emacs, I can use C-y (yank) and then M-y (yank-pop) to go through a list of recent bits of text which have been killed. Having done this, the next time I do C-y, it yanks the last bit of text selected via M-y. This is desired since it means I don't have to rotate through the list to find my favorite item again. This behavior is implemented using the variable "kill-ring-yank-pointer" which points to the last "yank-pop"ed item in the kill ring. However, when I kill some text, the value of "kill-ring-yank-pointer" is reset to point to the head of the "kill ring". This resetting means that when I am interspersing a number of yanks (of the same item of text) with an editing command such as M-d which also populates the kill ring, then my "kill-ring-yank-pointer" is reset each time, and each time I yank, I have to search farther and farther back with an increasing number of M-y keystrokes, just to get the same item I've been yanking. In short, when (say) I am replacing a few strings manually with some text from the kill ring, I end up doing C-y, then for the next replacement C-y M-y, then next C-y M-y M-y, and next C-y M-y M-y M-y, and so on. I'll give a concrete tutorial. Try replacing every animal in the following list with "dog", using only "M-d" and "C-y" and "M-y", and "C-a" and "C-n". dog cat ant chicken The kill ring will first look like ("dog"), then ("cat" "dog"), then ("ant" "cat" "dog"), then ("chicken" "ant" "cat" "dog"). After the final yank-pop of each line, the kill-ring-yank-pointer will point to "dog" at the end of the kill ring. However, when you use M-d to delete the animal being replaced, then kill-ring-yank-pointer gets reset, and so it is never used. Proposed solution: The kill ring, which is a list, should be treated as an array by yank-pop, and rearranged more freely. Killing text should still put stuff at the front of the list, as before. However, each yank-pop'ed item will also be moved to the front of the kill ring. Yank-pop should use a new variable to serve the purpose of "kill-ring-yank-pointer". Rather than pointing to an existing item in the kill ring, the new variable will be an index into the kill ring, which just tells yank-pop how to fix up the kill ring in case the last command was yank-pop. For example, suppose the kill ring looks like this: (I) A B C D E C-y M-y M-y will end up with C being inserted at the cursor. After that, we DON'T want the kill ring to look like "C D E A B" because we care more about A and B than about D or E, as they are more recently used items. What we do want it to look like is (II) C A B D E But suppose the next command is also M-y. Then the kill ring should look like (III) D A B C E because we care more about A and B than about C (since C we saw only on our way to D, and didn't end up using it). In order to obtain this configuration, yank-pop will have to have inserted C back where it came from, and moved D to the front. It would presumably do this with an integer variable which is incremented at each yank-pop, and reset to 0 in the 'yank' command, to guide the insertion and extraction of elements from the kill ring. To be specific, let's call the new variable "kill-ring-yank-pop-index". In state (I) above, "kill-ring-yank-pop-index" could have an arbitrary value, but it is reset to zero by "yank". In state (II) above, it would have the value 2 to indicate that C came from position 2 in the (zero-indexed) kill ring. In state (III), it would have value 3 - at that point, yank-pop will have read the value 2 from "kill-ring-yank-pop-index", used that to put C back into the list at position 2, moved D to the front, and incremented the value to 3. The END.