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: Re: yank-pop problem Date: Thu, 6 Aug 2015 16:49:43 -0700 Message-ID: <20150806234942.GA6355@ofb.net> References: <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 1438905014 1905 80.91.229.3 (6 Aug 2015 23:50:14 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 6 Aug 2015 23:50:14 +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 Fri Aug 07 01:50:03 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 1ZNUvC-0004GB-IG for geh-help-gnu-emacs@m.gmane.org; Fri, 07 Aug 2015 01:50:02 +0200 Original-Received: from localhost ([::1]:47319 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZNUvB-0002c9-SU for geh-help-gnu-emacs@m.gmane.org; Thu, 06 Aug 2015 19:50:01 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:54128) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZNUv1-0002bV-EJ for help-gnu-emacs@gnu.org; Thu, 06 Aug 2015 19:49:52 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZNUuz-00021F-Vx for help-gnu-emacs@gnu.org; Thu, 06 Aug 2015 19:49:51 -0400 Original-Received: from ofb.net ([64.13.131.34]:43701) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZNUuu-0001xS-Q1; Thu, 06 Aug 2015 19:49:44 -0400 Original-Received: by ofb.net (Postfix, from userid 30017) id 3BECD20706E0; Thu, 6 Aug 2015 16:49:43 -0700 (PDT) Content-Disposition: inline In-Reply-To: <20150806073831.GA4560@ofb.net> 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-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:106306 gmane.emacs.bugs:105340 Archived-At: I just coded up a solution and posted it under "A Better Yank-Pop Implementation" in the stackoverflow thread: http://stackoverflow.com/questions/5823495/emacs-how-to-yank-the-last-yanked-text-regardless-of-subsequent-kills On Thu, Aug 06, 2015 at 12:38:31AM -0700, Frederik Eaton wrote: > 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. >