From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Michael Heerdegen Newsgroups: gmane.emacs.devel Subject: [Annotation] New package: smart-yank.el Date: Tue, 17 May 2016 01:41:59 +0200 Message-ID: <87inyd3708.fsf@web.de> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1463442322 19166 80.91.229.3 (16 May 2016 23:45:22 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 16 May 2016 23:45:22 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue May 17 01:45:14 2016 Return-path: Envelope-to: ged-emacs-devel@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 1b2SCH-0007Wj-S0 for ged-emacs-devel@m.gmane.org; Tue, 17 May 2016 01:45:14 +0200 Original-Received: from localhost ([::1]:47815 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b2SCH-0001JY-4c for ged-emacs-devel@m.gmane.org; Mon, 16 May 2016 19:45:13 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:55471) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b2SCD-0001E7-JQ for emacs-devel@gnu.org; Mon, 16 May 2016 19:45:10 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1b2SC9-0008H6-Cb for emacs-devel@gnu.org; Mon, 16 May 2016 19:45:08 -0400 Original-Received: from plane.gmane.org ([80.91.229.3]:34256) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b2SC9-0008H0-1K for emacs-devel@gnu.org; Mon, 16 May 2016 19:45:05 -0400 Original-Received: from list by plane.gmane.org with local (Exim 4.69) (envelope-from ) id 1b2SC7-0007So-HZ for emacs-devel@gnu.org; Tue, 17 May 2016 01:45:03 +0200 Original-Received: from dslb-094-217-122-112.094.217.pools.vodafone-ip.de ([94.217.122.112]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Tue, 17 May 2016 01:45:03 +0200 Original-Received: from michael_heerdegen by dslb-094-217-122-112.094.217.pools.vodafone-ip.de with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Tue, 17 May 2016 01:45:03 +0200 X-Injected-Via-Gmane: http://gmane.org/ Original-Lines: 225 Original-X-Complaints-To: usenet@ger.gmane.org X-Gmane-NNTP-Posting-Host: dslb-094-217-122-112.094.217.pools.vodafone-ip.de User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.93 (gnu/linux) Cancel-Lock: sha1:nKMQg4MNT36KXkBzBXmWgXYM5+w= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 80.91.229.3 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:203874 Archived-At: --=-=-= Content-Type: text/plain Hello, I intend to upload the attached package "smart-yank.el" to Gnu Elpa (does that work again btw?). Any comments, objections, ...or something like that? Thanks. Regards, Michael. --=-=-= Content-Type: application/emacs-lisp Content-Disposition: inline; filename=smart-yank.el Content-Transfer-Encoding: quoted-printable ;;; smart-yank.el --- A different approach of yank pointer handling -*- le= xical-binding: t -*- ;; Copyright (C) 2016 Free Software Foundation, Inc ;; Author: Michael Heerdegen ;; Maintainer: Michael Heerdegen ;; Created: 14 May 2016 ;; Keywords: convenience ;; Compatibility: GNU Emacs 24 ;; Version: 0.1 ;; Package-Requires: ((emacs "24")) ;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . ;;; Commentary: ;; ;; Introduction ;; =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D ;; ;; This library implements the global minor mode `smart-yank-mode' ;; that changes the way Emacs handles the `kill-ring-yank-pointer' in ;; a way that some people prefer over the default behavior. ;; ;; Normally, only a kill command resets the yank pointer. With ;; `smart-yank-mode' enabled, any command except yank commands resets ;; it. ;; ;; In addition, when yanking any "older" element from the kill-ring ;; with yank-pop (and not replacing it with a subsequent yank-pop), it ;; is automatically moved to the "first position" so `yank' invoked ;; later will yank this element again. ;; ;; Finally, `yank-pop' (normally bound to M-y) is replaced with ;; `smart-yank-yank-pop' that is a bit more sophisticated: ;; ;; - When _not_ called after a `yank', instead of raising an error ;; like `yank-pop', yank the next-to-the-last kill. ;; ;; - Hit M-y twice in fast succession (delay < 0.2 secs by default) ;; when you got lost. This will remove the yanked text. If you ;; bind a command to `smart-yank-browse-kill-ring-command', this ;; command will be called too (typically something like ;; `browse-kill-ring'). ;; ;; ;; Example: you want to manually replace some words in some buffer ;; with a new word "foo". With `smart-yank-mode' enabled, you can do ;; it like this: ;; ;; 1. Put "foo" into the kill ring. ;; 2. Move to the next word to be replaced. ;; 3. M-d M-y ;; 4. Back to 2, iterate. ;; ;; ;; Setup ;; =3D=3D=3D=3D=3D ;; ;; Just enable `smart-yank-mode' and you are done. ;;; Code: ;;;; Configuration stuff (defgroup smart-yank nil "A different approach of yank pointer handling." :group 'killing) (defcustom smart-yank-yank-pop-multikey-delay .2 "Max delay between two \\[smart-yank-yank-pop] invocations revealing spec= ial behavior. See `smart-yank-yank-pop' for details." :type 'number) (defcustom smart-yank-browse-kill-ring-command nil "Command to invoke when hitting \\[smart-yank-yank-pop] twice (fast)." :type '(choice (const :tag "None" nil) (const browse-kill-ring) (const helm-show-kill-ring) (function :tag "Other Function"))) (defvar smart-yank-map (let ((map (make-sparse-keymap))) (define-key map [remap yank-pop] #'smart-yank-yank-pop) map) "Map used by `smart-yank-mode'.") ;;;; Internals (defun smart-yank--stopwatch () "Return a fresh stopwatch. This is a function accepting zero arguments that upon each call will return the time difference from its last call in seconds. When called the first time it will return nil." (let ((last-invocation nil)) (lambda () (prog1 (and last-invocation (time-to-seconds (time-subtract (current-time) last-invo= cation))) (setq last-invocation (current-time)))))) (defun smart-yank-reset-yank-pointer () (unless (eq last-command #'yank) (setq kill-ring-yank-pointer kill-ring))) (defun smart-yank--before-ad (&rest _args) "Before advice function for `yank'. Reset `kill-ring-yank-pointer'. For yank-pop, move the really yanked text \"to the beginning\" of the kill ring." (unless (eq kill-ring kill-ring-yank-pointer) (let ((last-yank (car kill-ring-yank-pointer))) (when last-yank (setq kill-ring (cons last-yank (delete last-yank kill-ring))) (smart-yank-reset-yank-pointer))))) (let ((r (smart-yank--stopwatch))) (defun smart-yank-yank-pop (&optional arg) "\"smart-yank\"'s private version of `yank-pop'. When called directly after a `yank' command (including itself), call `yank-pop'. If its key was hit two times in fast succession - i.e. with a delay less than `smart-yank-yank-pop-multikey-delay' - delete any yanked text; in addition call `smart-yank-browse-kill-ring-command' when set. When not called after a yank, yank the next-to-the-last `kill-ring' entry; with prefix arg, call the `smart-yank-browse-kill-ring-command'." (interactive "P") (let ((diff (funcall r))) (cond ((not (eq last-command 'yank)) (if arg (call-interactively smart-yan= k-browse-kill-ring-command) (rotate-yank-pointer 1) (yank))) ((or (not diff) (> diff smart-yank-yank-pop-multikey-delay)) (call-interactively #'yank-pop)) (t (funcall (or yank-undo-function #'del= ete-region) (region-beginning) (region-e= nd)) (when smart-yank-browse-kill-ring-com= mand (call-interactively smart-yank-brow= se-kill-ring-command))))))) (declare-function smart-yank-yank-pop 'smart-yank) ;;;; User stuff ;;;###autoload (define-minor-mode smart-yank-mode "Alter the behavior of yank commands in several ways. Turning on this mode has the following effects: - Makes any command except yank commands reset the `kill-ring-yank-pointer', instead of only killing commands. - Remaps `yank-pop' to `smart-yank-yank-pop'. - When yanking an older element from the `kill-ring' with \\[smart-yank-yank-pop] (and not replacing it with a subsequent \\[smart= -yank-yank-pop]), the element is automatically \"moved to the first position\" of the `kill-ring' so that `yank' invoked later will again yank this element." :global t :keymap smart-yank-map (if smart-yank-mode (advice-add 'yank :before #'smart-yank--before-ad) (advice-remove 'yank #'smart-yank--before-ad))) (provide 'smart-yank) ;;; smart-yank.el ends here --=-=-=--