From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: "Drew Adams" Newsgroups: gmane.emacs.bugs Subject: bug#12232: 24.1.50; regression: repeat.el commit 2012-05-05 breaks repeating commands Date: Sat, 18 Aug 2012 19:55:42 -0700 Message-ID: <26617CF879E04A6689018BFA901EF01A@us.oracle.com> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Trace: ger.gmane.org 1345345025 32289 80.91.229.3 (19 Aug 2012 02:57:05 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sun, 19 Aug 2012 02:57:05 +0000 (UTC) To: 12232@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sun Aug 19 04:57:06 2012 Return-path: Envelope-to: geb-bug-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 1T2vhI-00057i-OG for geb-bug-gnu-emacs@m.gmane.org; Sun, 19 Aug 2012 04:57:05 +0200 Original-Received: from localhost ([::1]:41029 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T2vhH-0007RZ-Cv for geb-bug-gnu-emacs@m.gmane.org; Sat, 18 Aug 2012 22:57:03 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:37218) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T2vhD-0007R8-IZ for bug-gnu-emacs@gnu.org; Sat, 18 Aug 2012 22:57:01 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1T2vhB-0007FB-SY for bug-gnu-emacs@gnu.org; Sat, 18 Aug 2012 22:56:59 -0400 Original-Received: from debbugs.gnu.org ([140.186.70.43]:56764) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T2vhB-0007F6-Oa for bug-gnu-emacs@gnu.org; Sat, 18 Aug 2012 22:56:57 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.72) (envelope-from ) id 1T2vhG-0008OH-LS for bug-gnu-emacs@gnu.org; Sat, 18 Aug 2012 22:57:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: "Drew Adams" Original-Sender: debbugs-submit-bounces@debbugs.gnu.org Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 19 Aug 2012 02:57:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 12232 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: X-Debbugs-Original-To: Original-Received: via spool by submit@debbugs.gnu.org id=B.134534497732197 (code B ref -1); Sun, 19 Aug 2012 02:57:02 +0000 Original-Received: (at submit) by debbugs.gnu.org; 19 Aug 2012 02:56:17 +0000 Original-Received: from localhost ([127.0.0.1]:38077 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.72) (envelope-from ) id 1T2vgU-0008ND-Mt for submit@debbugs.gnu.org; Sat, 18 Aug 2012 22:56:15 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:49167) by debbugs.gnu.org with esmtp (Exim 4.72) (envelope-from ) id 1T2vgQ-0008N3-IZ for submit@debbugs.gnu.org; Sat, 18 Aug 2012 22:56:12 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1T2vgJ-00078F-G2 for submit@debbugs.gnu.org; Sat, 18 Aug 2012 22:56:05 -0400 Original-Received: from lists.gnu.org ([208.118.235.17]:50605) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T2vgJ-00077j-CF for submit@debbugs.gnu.org; Sat, 18 Aug 2012 22:56:03 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:37174) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T2vgH-0007QU-He for bug-gnu-emacs@gnu.org; Sat, 18 Aug 2012 22:56:03 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1T2vgF-00075l-2q for bug-gnu-emacs@gnu.org; Sat, 18 Aug 2012 22:56:01 -0400 Original-Received: from acsinet15.oracle.com ([141.146.126.227]:34816) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T2vgE-00073L-Qb for bug-gnu-emacs@gnu.org; Sat, 18 Aug 2012 22:55:59 -0400 Original-Received: from acsinet22.oracle.com (acsinet22.oracle.com [141.146.126.238]) by acsinet15.oracle.com (Sentrion-MTA-4.2.2/Sentrion-MTA-4.2.2) with ESMTP id q7J2ttlr005782 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Sun, 19 Aug 2012 02:55:56 GMT Original-Received: from acsmt358.oracle.com (acsmt358.oracle.com [141.146.40.158]) by acsinet22.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id q7J2tsYY016573 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 19 Aug 2012 02:55:55 GMT Original-Received: from abhmt107.oracle.com (abhmt107.oracle.com [141.146.116.59]) by acsmt358.oracle.com (8.12.11.20060308/8.12.11) with ESMTP id q7J2tsrb010503 for ; Sat, 18 Aug 2012 21:55:54 -0500 Original-Received: from dradamslap1 (/10.159.171.244) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Sat, 18 Aug 2012 19:55:54 -0700 X-Priority: 1 (Highest) X-MSMail-Priority: High X-Mailer: Microsoft Office Outlook 11 Importance: High Thread-Index: Ac19th790A4wIXJ9Tpu3w2xXIEPQ5g== X-Message-Flag: Follow up X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.6157 X-Source-IP: acsinet22.oracle.com [141.146.126.238] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 1) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.13 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 140.186.70.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:63281 Archived-At: I believe this regression was introduced by the following commit: Stefan Monnier2012-05-05 02:50:20Revision ID: monnier@iro.umontreal.ca-2012= 0505025020-ihjvoqehkrxkfxw8 Use set-temporary-overlay-map. * lisp/repeat.el: Use lexical-binding. (repeat-last-self-insert, repeat-num-input-keys-at-self-insert) (repeat-undo-count): Remove. (repeat): * lisp/progmodes/octave-mod.el (octave-abbrev-start): * lisp/progmodes/f90.el (f90-abbrev-start): * lisp/face-remap.el (text-scale-adjust): * lisp/kmacro.el (kmacro-call-macro): Use set-temporary-overlay-map. ---- I use the following idiom in more than one library, to create repeatable versions of commands - it is very handy. I use such commands to cycle through bookmarks, to move forward over thing-at-point things repeatedly, etc. The idea is this: use `repeat' to create a repeatable command that can be bound to a key sequence with a prefix key. For example, I have `C-x p n' bound to a command that cycles through bookmarks, and I have `C-x ' bound to a command that repeatedly moves forward over thing-at-point things of different kinds. Example: (defun repeat-command (command) "Repeat COMMAND. (more explanation needed)" (interactive) (let ((repeat-previous-repeated-command command) (last-repeatable-command 'repeat)) (repeat nil))) (defun backward-char-repeat () "Like `backward-char'. (more explanation needed)" (interactive) (repeat-command 'backward-char)) (define-key ctl-x-map [up] 'backward-char-repeat) Now do C-x ... to repeat the command `backward-char'. In this case, the particular command that is repeated is not very interesting, and it already has a binding that does not use a prefix key - a key (`C-b') that is itself repeatable. But you get the idea: the idiom works with any command, and it lets me put such commands along with other commands on a common prefix for a given mode. For example, I put `bookmark-map' on a prefix key `C-x p', so all bookmark commands are available on the same prefix. This includes bookmark navigation/cycling commands, which are repeatable. There are several kinds of cycling, with different bookmark navigation lists: C-x p f, C-x p b: cycle bookmarks from the current navigation list (which can be any set of bookmarks, in a particular sort order) C-x p n, C-x p p: cycle the bookmarks of the current file/buffer C-x p C-, C-x p C-: cycle highlighted bookmarks in file E.g., C-x p n n n n n n... cycles bookmarks in the current file. This technique works in all Emacs versions since repeat.el was introduced, which was Emacs 22, I believe. It works in Emacs 24 also, up through a build of 2012-04-30. It does not work in Emacs 24 builds I have, starting with 2012-05-07. This is an important feature for me. I really hope it will be fixed. The symptom of the breakage is this: It seems to work at first: it can be repeated twice (always, it seems), and then I get this when I hit the repeatable key the third time: Debugger entered--Lisp error: (error "Lisp nesting exceeds `max-lisp-eval-d= epth'") repeat(nil) call-interactively(repeat) #[0 "..." [ignore repeat-message-function this-command repeat call-intera= ctively] 2 "\n\n(fn)" nil]() call-interactively(#[0 "..." [ignore repeat-message-function this-command= repeat call-interactively] 2 "\n\n(fn)" nil]) repeat(nil) call-interactively(repeat) #[0 "..." [ignore repeat-message-function this-command repeat call-intera= ctively] 2 "\n\n(fn)" nil]() call-interactively(#[0 "..." [ignore repeat-message-function this-command repeat call-interactively] 2 "\n\n(fn)" nil]) ... repeat(nil) call-interactively(repeat) #[0 "..." [ignore repeat-message-function this-command repeat call-intera= ctively] 2 "\n\n(fn)" nil]() call-interactively(#[0 "..." [ignore repeat-message-function this-command repeat call-interactively] 2 "\n\n(fn)" nil] nil nil) Here is the backtrace when I load repeat.el instead of repeat.elc: Debugger entered--Lisp error: (error "Lisp nesting exceeds `max-lisp-eval-d= epth'") (when (eq last-repeatable-command (quote repeat)) (setq last-repeatable-c= ommand repeat-previous-repeated-command)) repeat(nil) call-interactively(repeat) (let ((repeat-message-function fun)) (setq this-command (quote repeat)) (= call-interactively (quote repeat))) (closure ((fun . ignore) (map keymap (down closure #1 nil (interactive) (= let ((repeat-message-function fun)) (setq this-command (quote repeat)) (cal= l-interactively (quote repeat))))) (repeat-repeat-char . down) (repeat-arg)= t) nil (interactive) (let ((repeat-message-function fun)) (setq this-comma= nd (quote repeat)) (call-interactively (quote repeat))))() call-interactively((closure ((fun . ignore) (map keymap (down closure #1 = nil (interactive) (let ((repeat-message-function fun)) (setq this-command (= quote repeat)) (call-interactively (quote repeat))))) (repeat-repeat-char .= down) (repeat-arg) t) nil (interactive) (let ((repeat-message-function fun= )) (setq this-command (quote repeat)) (call-interactively (quote repeat))))) (if (or (stringp indirect) (vectorp indirect)) (let ((last-repeatable-com= mand last-repeatable-command)) (execute-kbd-macro last-repeatable-command))= (call-interactively last-repeatable-command)) (let ((indirect (indirect-function last-repeatable-command))) (if (or (st= ringp indirect) (vectorp indirect)) (let ((last-repeatable-command last-rep= eatable-command)) (execute-kbd-macro last-repeatable-command)) (call-intera= ctively last-repeatable-command))) (if (memq last-repeatable-command (quote (exit-minibuffer minibuffer-comp= lete-and-exit self-insert-and-exit))) (let ((repeat-command (car command-hi= story))) (repeat-message "Repeating %S" repeat-command) (eval repeat-comman= d)) (if (null repeat-arg) (repeat-message "Repeating command %S" last-repea= table-command) (setq current-prefix-arg repeat-arg) (repeat-message "Repeat= ing command %S %S" repeat-arg last-repeatable-command)) (when (eq last-repe= atable-command (quote self-insert-command)) (setq last-command-event (char-= before))) (let ((indirect (indirect-function last-repeatable-command))) (if= (or (stringp indirect) (vectorp indirect)) (let ((last-repeatable-command = last-repeatable-command)) (execute-kbd-macro last-repeatable-command)) (cal= l-interactively last-repeatable-command)))) (let ((repeat-repeat-char (if (eq repeat-on-final-keystroke t) last-comma= nd-event (car (memq last-command-event (listify-key-sequence repeat-on-fina= l-keystroke)))))) (if (memq last-repeatable-command (quote (exit-minibuffer= minibuffer-complete-and-exit self-insert-and-exit))) (let ((repeat-command= (car command-history))) (repeat-message "Repeating %S" repeat-command) (ev= al repeat-command)) (if (null repeat-arg) (repeat-message "Repeating comman= d %S" last-repeatable-command) (setq current-prefix-arg repeat-arg) (repeat= -message "Repeating command %S %S" repeat-arg last-repeatable-command)) (wh= en (eq last-repeatable-command (quote self-insert-command)) (setq last-comm= and-event (char-before))) (let ((indirect (indirect-function last-repeatabl= e-command))) (if (or (stringp indirect) (vectorp indirect)) (let ((last-rep= eatable-command last-repeatable-command)) (execute-kbd-macro last-repeatabl= e-command)) (call-interactively last-repeatable-command)))) (when repeat-re= peat-char (set-temporary-overlay-map (let ((map (make-sparse-keymap))) (def= ine-key map (vector repeat-repeat-char) (if (null repeat-message-function) = (quote repeat) (let (...) (lambda nil ... ...)))) map)))) repeat(nil) call-interactively(repeat) (let ((repeat-message-function fun)) (setq this-command (quote repeat)) (= call-interactively (quote repeat))) (closure ((fun . ignore) (map keymap (down closure #1 nil (interactive) (= let ((repeat-message-function fun)) (setq this-command (quote repeat)) (cal= l-interactively (quote repeat))))) (repeat-repeat-char . down) (repeat-arg)= t) nil (interactive) (let ((repeat-message-function fun)) (setq this-comma= nd (quote repeat)) (call-interactively (quote repeat))))() call-interactively((closure ((fun . ignore) (map keymap (down closure #1 = nil (interactive) (let ((repeat-message-function fun)) (setq this-command (= quote repeat)) (call-interactively (quote repeat))))) (repeat-repeat-char .= down) (repeat-arg) t) nil (interactive) (let ((repeat-message-function fun= )) (setq this-command (quote repeat)) (call-interactively (quote repeat))))) (if (or (stringp indirect) (vectorp indirect)) (let ((last-repeatable-com= mand last-repeatable-command)) (execute-kbd-macro last-repeatable-command))= (call-interactively last-repeatable-command)) (let ((indirect (indirect-function last-repeatable-command))) (if (or (st= ringp indirect) (vectorp indirect)) (let ((last-repeatable-command last-rep= eatable-command)) (execute-kbd-macro last-repeatable-command)) (call-intera= ctively last-repeatable-command))) (if (memq last-repeatable-command (quote (exit-minibuffer minibuffer-comp= lete-and-exit self-insert-and-exit))) (let ((repeat-command (car command-hi= story))) (repeat-message "Repeating %S" repeat-command) (eval repeat-comman= d)) (if (null repeat-arg) (repeat-message "Repeating command %S" last-repea= table-command) (setq current-prefix-arg repeat-arg) (repeat-message "Repeat= ing command %S %S" repeat-arg last-repeatable-command)) (when (eq last-repe= atable-command (quote self-insert-command)) (setq last-command-event (char-= before))) (let ((indirect (indirect-function last-repeatable-command))) (if= (or (stringp indirect) (vectorp indirect)) (let ((last-repeatable-command = last-repeatable-command)) (execute-kbd-macro last-repeatable-command)) (cal= l-interactively last-repeatable-command)))) (let ((repeat-repeat-char (if (eq repeat-on-final-keystroke t) last-comma= nd-event (car (memq last-command-event (listify-key-sequence repeat-on-fina= l-keystroke)))))) (if (memq last-repeatable-command (quote (exit-minibuffer= minibuffer-complete-and-exit self-insert-and-exit))) (let ((repeat-command= (car command-history))) (repeat-message "Repeating %S" repeat-command) (ev= al repeat-command)) (if (null repeat-arg) (repeat-message "Repeating comman= d %S" last-repeatable-command) (setq current-prefix-arg repeat-arg) (repeat= -message "Repeating command %S %S" repeat-arg last-repeatable-command)) (wh= en (eq last-repeatable-command (quote self-insert-command)) (setq last-comm= and-event (char-before))) (let ((indirect (indirect-function last-repeatabl= e-command))) (if (or (stringp indirect) (vectorp indirect)) (let ((last-rep= eatable-command last-repeatable-command)) (execute-kbd-macro last-repeatabl= e-command)) (call-interactively last-repeatable-command)))) (when repeat-re= peat-char (set-temporary-overlay-map (let ((map (make-sparse-keymap))) (def= ine-key map (vector repeat-repeat-char) (if (null repeat-message-function) = (quote repeat) (let (...) (lambda nil ... ...)))) map)))) ... repeat(nil) call-interactively(repeat) (let ((repeat-message-function fun)) (setq this-command (quote repeat)) (= call-interactively (quote repeat))) (closure ((fun . ignore) (map keymap (down closure #1 nil (interactive) (= let ((repeat-message-function fun)) (setq this-command (quote repeat)) (cal= l-interactively (quote repeat))))) (repeat-repeat-char . down) (repeat-arg)= t) nil (interactive) (let ((repeat-message-function fun)) (setq this-comma= nd (quote repeat)) (call-interactively (quote repeat))))() call-interactively((closure ((fun . ignore) (map keymap (down closure #1 = nil (interactive) (let ((repeat-message-function fun)) (setq this-command (= quote repeat)) (call-interactively (quote repeat))))) (repeat-repeat-char .= down) (repeat-arg) t) nil (interactive) (let ((repeat-message-function fun= )) (setq this-command (quote repeat)) (call-interactively (quote repeat))))= nil nil) As you no doubt know, it is very difficult to debug uses of repeat.el. It is impossible to use the debugger, and even printing `message's is problematic. Hopefully this info will help. You should be able to reproduce the problem using the code above. If you try it in an older version you will see what it should do. In GNU Emacs 24.1.50.1 (i386-mingw-nt5.1.2600) of 2012-08-13 on MARVIN Bzr revision: 109584 monnier@iro.umontreal.ca-20120813141247-76irjqslrfncn3= 0u Windowing system distributor `Microsoft Corp.', version 5.1.2600 Configured using: `configure --with-gcc (4.6) --no-opt --enable-checking --cflags -ID:/devel/emacs/libs/libXpm-3.5.8/include -ID:/devel/emacs/libs/libXpm-3.5.8/src -ID:/devel/emacs/libs/libpng-dev_1.4.3-1/include -ID:/devel/emacs/libs/zlib-dev_1.2.5-2/include -ID:/devel/emacs/libs/giflib-4.1.4-1/include -ID:/devel/emacs/libs/jpeg-6b-4/include -ID:/devel/emacs/libs/tiff-3.8.2-1/include -ID:/devel/emacs/libs/gnutls-3.0.9/include -ID:/devel/emacs/libs/libiconv-1.13.1-1-dev/include -ID:/devel/emacs/libs/libxml2-2.7.8/include/libxml2'