From unknown Fri Aug 15 20:05:16 2025 X-Loop: help-debbugs@gnu.org Subject: bug#25068: 25.1; Edebug fails to instrument code which uses propertized strings Resent-From: Gemini Lasswell Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 29 Nov 2016 23:11:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 25068 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: To: 25068@debbugs.gnu.org X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Received: via spool by submit@debbugs.gnu.org id=B.148046104017033 (code B ref -1); Tue, 29 Nov 2016 23:11:02 +0000 Received: (at submit) by debbugs.gnu.org; 29 Nov 2016 23:10:40 +0000 Received: from localhost ([127.0.0.1]:46613 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cBrXs-0004Qf-Jt for submit@debbugs.gnu.org; Tue, 29 Nov 2016 18:10:40 -0500 Received: from eggs.gnu.org ([208.118.235.92]:58646) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cBrXr-0004QS-4H for submit@debbugs.gnu.org; Tue, 29 Nov 2016 18:10:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cBrXk-0005vx-Ni for submit@debbugs.gnu.org; Tue, 29 Nov 2016 18:10:33 -0500 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=BAYES_50,FREEMAIL_FROM autolearn=disabled version=3.3.2 Received: from lists.gnu.org ([2001:4830:134:3::11]:60150) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cBrXk-0005vr-Jm for submit@debbugs.gnu.org; Tue, 29 Nov 2016 18:10:32 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49598) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cBrXj-0008Nj-Ar for bug-gnu-emacs@gnu.org; Tue, 29 Nov 2016 18:10:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cBrXg-0005ux-03 for bug-gnu-emacs@gnu.org; Tue, 29 Nov 2016 18:10:31 -0500 Received: from aibo.runbox.com ([91.220.196.211]:39724) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cBrXf-0005uX-Ob for bug-gnu-emacs@gnu.org; Tue, 29 Nov 2016 18:10:27 -0500 Received: from [10.9.9.212] (helo=mailfront12.runbox.com) by bars.runbox.com with esmtp (Exim 4.71) (envelope-from ) id 1cBrXd-0004rh-AS for bug-gnu-emacs@gnu.org; Wed, 30 Nov 2016 00:10:25 +0100 Received: from c-24-22-244-161.hsd1.wa.comcast.net ([24.22.244.161] helo=rainbow.local) by mailfront12.runbox.com with esmtpsa (uid:179284 ) (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.82) id 1cBrXX-0001Sv-D9 for bug-gnu-emacs@gnu.org; Wed, 30 Nov 2016 00:10:20 +0100 From: Gemini Lasswell Date: Tue, 29 Nov 2016 15:10:16 -0800 Message-ID: MIME-Version: 1.0 Content-Type: text/plain X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x [fuzzy] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 2001:4830:134:3::11 X-Spam-Score: -4.1 (----) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -4.1 (----) Edebug gives an error message if you try to use it on code which uses strings with text properties. To reproduce, using emacs -Q if you like, enter the following code into *scratch* and type C-u C-M-x: (defun my-fun () (message "%s" #("abcd" 1 3 (face italic)))) This results in the error message: "Invalid read syntax: "Bad char after #" Here is the backtrace: Debugger entered--Lisp error: (invalid-read-syntax "Bad char after #") signal(invalid-read-syntax ("Bad char after #")) edebug-syntax-error("Bad char after #") edebug-read-function(#) edebug-read-storing-offsets(#) edebug-read-list(#) edebug-read-storing-offsets(#) edebug-read-list(#) edebug-read-storing-offsets(#) edebug-read-and-maybe-wrap-form1() edebug-read-and-maybe-wrap-form() edebug-read-top-level-form() edebug-eval-defun((4)) apply(edebug-eval-defun (4)) eval-defun((4)) funcall-interactively(eval-defun (4)) call-interactively(eval-defun nil nil) command-execute(eval-defun) In GNU Emacs 25.1.1 (x86_64-apple-darwin15.6.0, NS appkit-1404.47 Version 10.11.6 (Build 15G1004)) of 2016-10-09 built on rainbow.local Windowing system distributor 'Apple', version 10.3.1404 Configured using: 'configure --disable-dependency-tracking --disable-silent-rules --enable-locallisppath=/usr/local/share/emacs/site-lisp --infodir=/usr/local/Cellar/emacs/25.1/share/info/emacs --prefix=/usr/local/Cellar/emacs/25.1 --without-x --with-xml2 --without-dbus --with-gnutls --with-imagemagick --with-rsvg --with-ns --disable-ns-self-contained' Configured features: JPEG RSVG IMAGEMAGICK NOTIFY ACL GNUTLS LIBXML2 ZLIB TOOLKIT_SCROLL_BARS NS Important settings: value of $LANG: en_US.UTF-8 locale-coding-system: utf-8-unix Major mode: Lisp Interaction Minor modes in effect: tooltip-mode: t global-eldoc-mode: t electric-indent-mode: t mouse-wheel-mode: t tool-bar-mode: t menu-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t blink-cursor-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t line-number-mode: t transient-mark-mode: t Recent messages: For information about GNU Emacs and the GNU system, type C-h C-a. Mark set edebug-syntax-error: Invalid read syntax: "Bad char after #" Load-path shadows: None found. Features: (shadow sort mail-extr emacsbug message dired format-spec rfc822 mml mml-sec password-cache epg epg-config gnus-util mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045 ietf-drums mm-util help-fns help-mode mail-prsvr mail-utils edebug easymenu cl-loaddefs pcase cl-lib time-date mule-util tooltip eldoc electric uniquify ediff-hook vc-hooks lisp-float-type mwheel ns-win ucs-normalize term/common-win tool-bar dnd fontset image regexp-opt fringe tabulated-list newcomment elisp-mode lisp-mode prog-mode register page menu-bar rfn-eshadow timer select scroll-bar mouse jit-lock font-lock syntax facemenu font-core frame cl-generic cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese charscript case-table epa-hook jka-cmpr-hook help simple abbrev minibuffer cl-preloaded nadvice loaddefs button faces cus-face macroexp files text-properties overlay sha1 md5 base64 format env code-pages mule custom widget hashtable-print-readable backquote kqueue cocoa ns multi-tty make-network-process emacs) Memory information: ((conses 16 198711 10003) (symbols 48 20106 0) (miscs 40 50 167) (strings 32 16048 5094) (string-bytes 1 457556) (vectors 16 33450) (vector-slots 8 658299 4717) (floats 8 160 49) (intervals 56 222 0) (buffers 976 17)) From unknown Fri Aug 15 20:05:16 2025 X-Loop: help-debbugs@gnu.org Subject: bug#25068: 25.1; Edebug fails to instrument code which uses propertized strings Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 04 Feb 2017 11:27:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 25068 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: To: Gemini Lasswell Cc: 25068@debbugs.gnu.org Reply-To: Eli Zaretskii Received: via spool by 25068-submit@debbugs.gnu.org id=B25068.148620761532518 (code B ref 25068); Sat, 04 Feb 2017 11:27:01 +0000 Received: (at 25068) by debbugs.gnu.org; 4 Feb 2017 11:26:55 +0000 Received: from localhost ([127.0.0.1]:55543 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cZyUZ-0008SP-5y for submit@debbugs.gnu.org; Sat, 04 Feb 2017 06:26:55 -0500 Received: from eggs.gnu.org ([208.118.235.92]:56814) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cZyUX-0008SC-Mu for 25068@debbugs.gnu.org; Sat, 04 Feb 2017 06:26:54 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZyUO-0003Td-H1 for 25068@debbugs.gnu.org; Sat, 04 Feb 2017 06:26:48 -0500 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD autolearn=disabled version=3.3.2 Received: from fencepost.gnu.org ([2001:4830:134:3::e]:47855) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZyUO-0003TZ-EF; Sat, 04 Feb 2017 06:26:44 -0500 Received: from 84.94.185.246.cable.012.net.il ([84.94.185.246]:1388 helo=home-c4e4a596f7) by fencepost.gnu.org with esmtpsa (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.82) (envelope-from ) id 1cZyUN-0003sv-MF; Sat, 04 Feb 2017 06:26:44 -0500 Date: Sat, 04 Feb 2017 13:26:35 +0200 Message-Id: <83inoq8adw.fsf@gnu.org> From: Eli Zaretskii In-reply-to: (message from Gemini Lasswell on Tue, 29 Nov 2016 15:10:16 -0800) References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2001:4830:134:3::e X-Spam-Score: -5.0 (-----) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -5.0 (-----) > From: Gemini Lasswell > Date: Tue, 29 Nov 2016 15:10:16 -0800 > > Edebug gives an error message if you try to use it on code which uses > strings with text properties. To reproduce, using emacs -Q if you like, > enter the following code into *scratch* and type C-u C-M-x: > > (defun my-fun () > (message "%s" #("abcd" 1 3 (face italic)))) > > This results in the error message: "Invalid read syntax: "Bad char after #" Could someone please look into fixing this? From unknown Fri Aug 15 20:05:16 2025 X-Loop: help-debbugs@gnu.org Subject: bug#25068: 25.1; Edebug fails to instrument code which uses propertized strings Resent-From: Gemini Lasswell Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 04 Feb 2017 17:41:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 25068 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: To: Eli Zaretskii Cc: 25068@debbugs.gnu.org Received: via spool by 25068-submit@debbugs.gnu.org id=B25068.14862300316914 (code B ref 25068); Sat, 04 Feb 2017 17:41:01 +0000 Received: (at 25068) by debbugs.gnu.org; 4 Feb 2017 17:40:31 +0000 Received: from localhost ([127.0.0.1]:56254 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ca4K5-0001nR-Qg for submit@debbugs.gnu.org; Sat, 04 Feb 2017 12:40:31 -0500 Received: from aibo.runbox.com ([91.220.196.211]:37884) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ca4K3-0001nG-5h for 25068@debbugs.gnu.org; Sat, 04 Feb 2017 12:40:29 -0500 Received: from [10.9.9.211] (helo=mailfront11.runbox.com) by mailtransmit03.runbox with esmtp (Exim 4.86_2) (envelope-from ) id 1ca4K1-0007z5-DC; Sat, 04 Feb 2017 18:40:25 +0100 Received: from c-24-22-244-161.hsd1.wa.comcast.net ([24.22.244.161] helo=rainbow.local) by mailfront11.runbox.com with esmtpsa (uid:179284 ) (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.82) id 1ca4Js-0002D3-MY; Sat, 04 Feb 2017 18:40:18 +0100 From: Gemini Lasswell References: <83inoq8adw.fsf@gnu.org> Date: Sat, 04 Feb 2017 09:39:51 -0800 In-Reply-To: <83inoq8adw.fsf@gnu.org> (Eli Zaretskii's message of "Sat, 04 Feb 2017 13:26:35 +0200") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.0.50 (darwin) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Spam-Score: -0.7 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.7 (/) --=-=-= Content-Type: text/plain This could be fixed by updating the list in edebug-read-function of characters that might possibly follow # to keep up with the changes to read1 since the last time that list was updated (in 2001). But I think it's better to remove the test entirely. If there is an invalid character then read1 will report a syntax error. --=-=-= Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename=0001-Add-tests-for-lisp-kmacro.el.patch Content-Transfer-Encoding: quoted-printable >From ad117828d954ddb8c37d134055d1a74b1344b078 Mon Sep 17 00:00:00 2001 From: gazally Date: Sun, 13 Nov 2016 08:02:38 -0800 Subject: [PATCH] Add tests for lisp/kmacro.el * test/lisp/kmacro-tests.el: New file. --- test/lisp/kmacro-tests.el | 907 ++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 907 insertions(+) create mode 100644 test/lisp/kmacro-tests.el diff --git a/test/lisp/kmacro-tests.el b/test/lisp/kmacro-tests.el new file mode 100644 index 0000000..fbf9685 --- /dev/null +++ b/test/lisp/kmacro-tests.el @@ -0,0 +1,907 @@ +;;; kmacro-tests.el --- Tests for kmacro.el -*- lexical-binding: t; = -*- + +;; Copyright (C) 2016 Free Software Foundation, Inc. + +;; Author: Gemini Lasswell + +;; This file is 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: + +;;; Code: + +(require 'kmacro) +(require 'ert) +(require 'ert-x) + +;;; Test fixtures: + +(defmacro kmacro-tests-with-kmacro-clean-slate (&rest body) + "Create a clean environment for a kmacro test BODY to run in." + (declare (debug (body))) + `(cl-letf* ((kmacro-execute-before-append t) + (kmacro-ring-max 8) + (kmacro-repeat-no-prefix t) + (kmacro-call-repeat-key nil) + (kmacro-call-repeat-with-arg nil) + + (kbd-macro-termination-hook nil) + (defining-kbd-macro nil) + (executing-kbd-macro nil) + (executing-kbd-macro-index 0) + (last-kbd-macro nil) + + (kmacro-ring nil) + + (kmacro-counter 0) + (kmacro-default-counter-format "%d") + (kmacro-counter-format "%d") + (kmacro-counter-format-start "%d") + (kmacro-counter-value-start 0) + (kmacro-last-counter 0) + (kmacro-initial-counter-value nil) + + (kmacro-tests-macros nil) + (kmacro-tests-events nil) + (kmacro-tests-sequences nil)) + (advice-add 'end-kbd-macro :after #'kmacro-tests-end-macro-advice) + (advice-add 'read-event :around #'kmacro-tests-read-event-advice ) + (advice-add 'read-key-sequence :around #'kmacro-tests-read-key-sequen= ce-advice) + (unwind-protect + (ert-with-test-buffer (:name "") + (switch-to-buffer (current-buffer)) + ,@body) + (advice-remove 'read-key-sequence #'kmacro-tests-read-key-sequence-= advice) + (advice-remove 'read-event #'kmacro-tests-read-event-advice) + (advice-remove 'end-kbd-macro #'kmacro-tests-end-macro-advice)))) + +(defmacro kmacro-tests-deftest (name _args docstring &rest keys-and-body) + "Define a kmacro unit test. +NAME is the name of the test, _ARGS should be nil, and DOCSTRING +is required. To avoid having to duplicate ert's keyword parsing +here, its keywords and values (if any) must be inside a list +after the docstring, preceding the body, here combined with the +body in KEYS-AND-BODY." + (declare (debug (&define name sexp stringp + [&optional (&rest &or [keywordp sexp])] + def-body)) + (doc-string 3) + (indent 2)) + + (let* ((keys (when (and (listp (car keys-and-body)) + (keywordp (caar keys-and-body))) + (car keys-and-body))) + (body (if keys (cdr keys-and-body) + keys-and-body))) + `(ert-deftest ,name () + ,docstring ,@keys + (kmacro-tests-with-kmacro-clean-slate ,@body)))) + +(defvar kmacro-tests-keymap + (let ((map (make-sparse-keymap))) + (dotimes (i 26) + (define-key map (string (+ ?a i)) 'self-insert-command)) + (dotimes (i 10) + (define-key map (string (+ ?0 i)) 'self-insert-command)) + ;; Define a few key sequences of different lengths. + (dolist (item '(("\C-a" . beginning-of-line) + ("\C-b" . backward-char) + ("\C-e" . end-of-line) + ("\C-f" . forward-char) + ("\C-r" . isearch-backward) + ("\C-u" . universal-argument) + ("\C-w" . kill-region) + ("\C-SPC" . set-mark-command) + ("\M-w" . kill-ring-save) + ("\M-x" . execute-extended-command) + ("\C-cd" . downcase-word) + ("\C-cxu" . upcase-word) + ("\C-cxq" . quoted-insert) + ("\C-cxi" . kmacro-insert-counter) + ("\C-x\C-k" . kmacro-keymap))) + (define-key map (car item) (cdr item))) + map) + "Keymap to use for testing keyboard macros. +This is used to obtain consistent results even if tests are run +in an environment with rebound keys.") + +(defvar kmacro-tests-events nil + "Input events used by the kmacro test in progress.") + +(defun kmacro-tests-read-event-advice (orig-func &rest args) + "Pop and return an event from `kmacro-tests-events'. +Return the result of calling ORIG-FUNC with ARGS if +`kmacro-tests-events' is empty, or if a keyboard macro is +running." + (if (or executing-kbd-macro (null kmacro-tests-events)) + (apply orig-func args) + (pop kmacro-tests-events))) + +(defvar kmacro-tests-sequences nil + "Input sequences used by the kmacro test in progress.") + +(defun kmacro-tests-read-key-sequence-advice (orig-func &rest args) + "Pop and return a string from `kmacro-tests-sequences'. +Return the result of calling ORIG-FUNC with ARGS if +`kmacro-tests-sequences' is empty, or if a keyboard macro is +running." + (if (or executing-kbd-macro (null kmacro-tests-sequences)) + (apply orig-func args) + (pop kmacro-tests-sequences))) + +(defvar kmacro-tests-macros nil + "Keyboard macros (in vector form) used by the kmacro test in progress.") + +(defun kmacro-tests-end-macro-advice (&rest _args) + "Pop a macro from `kmacro-tests-macros' and assign it to `last-kbd-macro= '. +If `kmacro-tests-macros' is empty, do nothing." + (when kmacro-tests-macros + (setq last-kbd-macro (pop kmacro-tests-macros)))) + +;;; Some more powerful expectations: + +(defmacro kmacro-tests-should-insert (value &rest body) + "Verify that VALUE is inserted by the execution of BODY. +Execute BODY, then check that the string VALUE was inserted +into the current buffer at point." + (declare (debug (stringp body)) + (indent 1)) + (let ((g-p (cl-gensym)) + (g-bsize (cl-gensym))) + `(let ((,g-p (point)) + (,g-bsize (buffer-size))) + ,@body + (should (equal (buffer-substring ,g-p (point)) ,value)) + (should (equal (- (buffer-size) ,g-bsize) (length ,value)))))) + +(defmacro kmacro-tests-with-message-capture (var &rest body) + "Execute BODY while collecting anything written with `message' in VAR." + (declare (debug (symbolp body)) + (indent 1)) + (let ((g-advice (cl-gensym))) + `(let* ((,var "") + (,g-advice (lambda (func &rest args) + (if (or (null args) (equal (car args) "")) + (apply func args) + (let ((msg (apply #'format-message args))) + (setq ,var (concat ,var msg "\n")) + (funcall func "%s" msg)))))) + (advice-add 'message :around ,g-advice) + (unwind-protect + (progn ,@body) + (advice-remove 'message ,g-advice))))) + +(defmacro kmacro-tests-should-match-message (value &rest body) + "Verify that a message matching VALUE is issued while executing BODY. +Execute BODY, and then if there is not a regexp match between +VALUE and any text written to *Messages* during the execution, +cause the current test to fail." + (declare (debug (form body)) + (indent 1)) + (let ((g-captured-messages (cl-gensym))) + `(kmacro-tests-with-message-capture ,g-captured-messages + ,@body + (should (string-match-p ,value ,g-captured-messages))))) + +;;; Tests: + +(kmacro-tests-deftest kmacro-tests-test-insert-counter-01-nil () + "`kmacro-insert-counter' adds one to macro counter with nil arg." + (kmacro-tests-should-insert "0" + (kmacro-tests-simulate-command '(kmacro-insert-counter nil))) + (kmacro-tests-should-insert "1" + (kmacro-tests-simulate-command '(kmacro-insert-counter nil)))) + +(kmacro-tests-deftest kmacro-tests-test-insert-counter-02-int () + "`kmacro-insert-counter' increments by value of list argument." + (kmacro-tests-should-insert "0" + (kmacro-tests-simulate-command '(kmacro-insert-counter 2))) + (kmacro-tests-should-insert "2" + (kmacro-tests-simulate-command '(kmacro-insert-counter 3))) + (kmacro-tests-should-insert "5" + (kmacro-tests-simulate-command '(kmacro-insert-counter nil)))) + +(kmacro-tests-deftest kmacro-tests-test-insert-counter-03-list () + "`kmacro-insert-counter' doesn't increment when given universal argument= ." + (kmacro-tests-should-insert "0" + (kmacro-tests-simulate-command '(kmacro-insert-counter (16)))) + (kmacro-tests-should-insert "0" + (kmacro-tests-simulate-command '(kmacro-insert-counter (4))))) + +(kmacro-tests-deftest kmacro-tests-test-insert-counter-04-neg () + "`kmacro-insert-counter' decrements with '- prefix argument" + (kmacro-tests-should-insert "0" + (kmacro-tests-simulate-command '(kmacro-insert-counter -))) + (kmacro-tests-should-insert "-1" + (kmacro-tests-simulate-command '(kmacro-insert-counter nil)))) + +(kmacro-tests-deftest kmacro-tests-test-start-format-counter () + "`kmacro-insert-counter' uses start value and format." + (kmacro-tests-simulate-command '(kmacro-set-counter 10)) + (kmacro-tests-should-insert "10" + (kmacro-tests-simulate-command '(kmacro-insert-counter nil))) + (kmacro-tests-should-insert "11" + (kmacro-tests-simulate-command '(kmacro-insert-counter nil))) + (kmacro-set-format "c=3D%s") + (kmacro-tests-simulate-command '(kmacro-set-counter 50)) + (kmacro-tests-should-insert "c=3D50" + (kmacro-tests-simulate-command '(kmacro-insert-counter nil)))) + +(kmacro-tests-deftest kmacro-tests-test-start-macro-when-defining-macro () + "Starting a macro while defining a macro does not start a second macro." + (kmacro-tests-simulate-command '(kmacro-start-macro nil)) + ;; We should now be in the macro-recording state. + (should defining-kbd-macro) + (should-not last-kbd-macro) + ;; Calling it again should leave us in the same state. + (kmacro-tests-simulate-command '(kmacro-start-macro nil)) + (should defining-kbd-macro) + (should-not last-kbd-macro)) + + +(kmacro-tests-deftest kmacro-tests-set-macro-counter-while-defining () + "Use of the prefix arg with kmacro-start sets kmacro-counter." + ;; Give kmacro-start-macro an argument. + (kmacro-tests-simulate-command '(kmacro-start-macro 5)) + (should defining-kbd-macro) + ;; Verify that the counter is set to that value. + (kmacro-tests-should-insert "5" + (kmacro-tests-simulate-command '(kmacro-insert-counter nil))) + ;; Change it while defining a macro. + (kmacro-tests-simulate-command '(kmacro-set-counter 1)) + (kmacro-tests-should-insert "1" + (kmacro-tests-simulate-command '(kmacro-insert-counter nil))) + ;; Using universal arg to to set counter should reset to starting value. + (kmacro-tests-simulate-command '(kmacro-set-counter (4)) '(4)) + (kmacro-tests-should-insert "5" + (kmacro-tests-simulate-command '(kmacro-insert-counter nil)))) + + +(kmacro-tests-deftest kmacro-tests-start-insert-counter-appends-to-macro () + "Use of the universal arg appends to the previous macro." + (let ((kmacro-tests-macros (list (string-to-vector "hello")))) + ;; Start recording a macro. + (kmacro-tests-simulate-command '(kmacro-start-macro-or-insert-counter = nil)) + ;; Make sure we are recording. + (should defining-kbd-macro) + ;; Call it again and it should insert the counter. + (kmacro-tests-should-insert "0" + (kmacro-tests-simulate-command '(kmacro-start-macro-or-insert-counte= r nil))) + ;; We should still be in the recording state. + (should defining-kbd-macro) + ;; End recording with repeat count. + (kmacro-tests-simulate-command '(kmacro-end-or-call-macro 3)) + ;; Recording should be finished. + (should-not defining-kbd-macro) + ;; Now use prefix arg to append to the previous macro. + ;; This should run the previous macro first. + (kmacro-tests-should-insert "hello" + (kmacro-tests-simulate-command + '(kmacro-start-macro-or-insert-counter (4)))) + ;; Verify that the recording state has changed. + (should (equal defining-kbd-macro 'append)))) + +(kmacro-tests-deftest kmacro-tests-end-call-macro-prefix-args () + "kmacro-end-call-macro changes behavior based on prefix arg." + ;; "Record" two macros. + (dotimes (i 2) + (kmacro-tests-define-macro (vconcat (format "macro #%d" (1+ i))))) + ;; With no prefix arg, it should call the second macro. + (kmacro-tests-should-insert "macro #2" + (kmacro-tests-simulate-command '(kmacro-end-or-call-macro nil))) + ;; With universal arg, it should call the first one. + (kmacro-tests-should-insert "macro #1" + (kmacro-tests-simulate-command '(kmacro-end-or-call-macro (4))))) + +(kmacro-tests-deftest kmacro-tests-end-and-call-macro () + "Keyboard command to end and call macro works under various conditions." + ;; First, try it with no macro to record. + (setq kmacro-tests-macros '("")) + (kmacro-tests-simulate-command '(kmacro-start-macro nil)) + (condition-case err + (kmacro-tests-simulate-command '(kmacro-end-and-call-macro 2) 2) + (error (should (string=3D (cadr err) + "No kbd macro has been defined")))) + + ;; Check that it stopped defining and that no macro was recorded. + (should-not defining-kbd-macro) + (should-not last-kbd-macro) + + ;; Now try it while not recording, but first record a non-nil macro. + (kmacro-tests-define-macro "macro") + (kmacro-tests-should-insert "macro" + (kmacro-tests-simulate-command '(kmacro-end-and-call-macro nil)))) + +(kmacro-tests-deftest kmacro-tests-end-and-call-macro-mouse () + "Commands to end and call macro work under various conditions. +This is a regression test for Bug#24992." + (:expected-result :failed) + (cl-letf (((symbol-function #'mouse-set-point) #'ignore)) + ;; First, try it with no macro to record. + (setq kmacro-tests-macros '("")) + (kmacro-tests-simulate-command '(kmacro-start-macro nil)) + (condition-case err + (kmacro-tests-simulate-command '(kmacro-end-call-mouse 2) 2) + (error (should (string=3D (cadr err) + "No kbd macro has been defined")))) + + ;; Check that it stopped defining and that no macro was recorded. + (should-not defining-kbd-macro) + (should-not last-kbd-macro) + + ;; Now try it while not recording, but first record a non-nil macro. + (kmacro-tests-define-macro "macro") + (kmacro-tests-should-insert "macro" + (kmacro-tests-simulate-command '(kmacro-end-call-mouse nil))))) + +(kmacro-tests-deftest kmacro-tests-call-macro-hint-and-repeat () + "`kmacro-call-macro' gives hint in Messages and sets up repeat keymap. +This is a regression test for: Bug#3412, Bug#11817." + (kmacro-tests-define-macro [?m]) + (let ((kmacro-call-repeat-key t) + (kmacro-call-repeat-with-arg t) + (overriding-terminal-local-map overriding-terminal-local-map) + (last-input-event ?e)) + (message "") ; Clear the echo area. (Bug#3412) + (kmacro-tests-should-match-message "Type e to repeat macro" + (kmacro-tests-should-insert "mmmmmm" + (cl-letf (((symbol-function #'this-single-command-keys) (lambda () + [?\C-x ?= e]))) + (kmacro-call-macro 3)) + ;; Check that it set up for repeat, and run the repeat. + (funcall (lookup-key overriding-terminal-local-map "e")))))) + +(kmacro-tests-deftest + kmacro-tests-run-macro-command-recorded-in-macro () + "No infinite loop if `kmacro-end-and-call-macro' is recorded in the macr= o. +\(Bug#15126)" + (:expected-result :failed) + (ert-skip "Skipping due to Bug#24921 (an ERT bug)") + (kmacro-tests-define-macro (vconcat "foo" [return] "\M-x" + "kmacro-end-and-call-macro")) + (use-local-map kmacro-tests-keymap) + (kmacro-tests-simulate-command '(kmacro-end-and-call-macro nil))) + + +(kmacro-tests-deftest kmacro-tests-test-ring-2nd-commands () + "2nd macro in ring is displayed and executed normally and on repeat." + (use-local-map kmacro-tests-keymap) + ;; Record one macro, with count. + (push (vconcat "\C-cxi" "\C-u\C-cxi") kmacro-tests-macros) + (kmacro-tests-simulate-command '(kmacro-start-macro 1)) + (kmacro-tests-simulate-command '(kmacro-end-macro nil)) + ;; Check that execute and display do nothing with no 2nd macro. + (kmacro-tests-should-insert "" + (kmacro-tests-simulate-command '(kmacro-call-ring-2nd nil))) + (kmacro-tests-should-match-message "Only one keyboard macro defined" + (kmacro-tests-simulate-command '(kmacro-view-ring-2nd))) + ;; Record another one, with format. + (kmacro-set-format "=3D%d=3D") + (kmacro-tests-define-macro (vconcat "bar")) + ;; Execute the first one, mocked up to insert counter. + ;; Should get default format. + (kmacro-tests-should-insert "11" + (kmacro-tests-simulate-command '(kmacro-call-ring-2nd nil))) + ;; Now display the 2nd ring macro and check result. + (kmacro-tests-should-match-message "C-c x i C-u C-c x i" + (kmacro-view-ring-2nd))) + +(kmacro-tests-deftest kmacro-tests-fill-ring-and-rotate () + "Macro ring can shift one way, shift the other way, swap and pop." + (cl-letf ((kmacro-ring-max 4)) + ;; Record enough macros that the first one drops off the history. + (dotimes (n (1+ kmacro-ring-max)) + (kmacro-tests-define-macro (make-vector (1+ n) (+ ?a n)))) + ;; Cycle the ring and check that #2 comes up. + (kmacro-tests-should-match-message "2*b" + (kmacro-tests-simulate-command '(kmacro-cycle-ring-next nil))) + ;; Execute the current macro and check arguments. + (kmacro-tests-should-insert "bbbb" + (kmacro-call-macro 2 t)) + ;; Cycle the ring the other way; #5 expected. + (kmacro-tests-should-match-message "5*e" (kmacro-cycle-ring-previous n= il)) + ;; Swapping the top two should give #4. + (kmacro-tests-should-match-message "4*d" (kmacro-swap-ring)) + ;; Delete the top and expect #5. + (kmacro-tests-should-match-message "5*e" (kmacro-delete-ring-head)))) + + +(kmacro-tests-deftest kmacro-tests-test-ring-commands-when-no-macros () + "Ring commands give appropriate message when no macros exist." + (dolist (cmd '((kmacro-cycle-ring-next nil) + (kmacro-cycle-ring-previous nil) + (kmacro-swap-ring) + (kmacro-delete-ring-head) + (kmacro-view-ring-2nd) + (kmacro-call-ring-2nd nil) + (kmacro-view-macro))) + (kmacro-tests-should-match-message "No keyboard macro defined" + (kmacro-tests-simulate-command cmd)))) + +(kmacro-tests-deftest kmacro-tests-repeat-on-last-key () + "Kmacro commands can be run in sequence without prefix keys." + (let* ((prefix (where-is-internal 'kmacro-keymap nil t)) + ;; Make a sequence of events to run. + ;; Comments are expected output of mock macros + ;; on the first and second run of the sequence (see below). + (events (mapcar #'kmacro-tests-get-kmacro-key + '(kmacro-end-or-call-macro-repeat ;c / b + kmacro-end-or-call-macro-repeat ;c / b + kmacro-call-ring-2nd-repeat ;b / a + kmacro-cycle-ring-next + kmacro-end-or-call-macro-repeat ;a / a + kmacro-cycle-ring-previous + kmacro-end-or-call-macro-repeat ;c / b + kmacro-delete-ring-head + kmacro-end-or-call-macro-repeat ;b / a + ))) + (kmacro-tests-macros (list [?a] [?b] [?c])) + ;; What we want kmacro to see as keyboard command sequence + (first-event (seq-concatenate + 'vector + prefix + (vector (kmacro-tests-get-kmacro-key + 'kmacro-end-or-call-macro-repeat))))) + (cl-letf + ;; standardize repeat options + ((kmacro-repeat-no-prefix t) + (kmacro-call-repeat-key t) + (kmacro-call-repeat-with-arg nil)) + ;; "Record" two macros + (dotimes (_n 2) + (kmacro-tests-simulate-command '(kmacro-start-macro nil)) + (kmacro-tests-simulate-command '(kmacro-end-macro nil))) + ;; Start recording #3 + (kmacro-tests-simulate-command '(kmacro-start-macro nil)) + + ;; Set up pending keyboard events and a fresh buffer + ;; kmacro-set-counter is not one of the repeating kmacro + ;; commands so it should end the sequence. + (let* ((end-key (kmacro-tests-get-kmacro-key 'kmacro-set-counter)) + (kmacro-tests-events (append events (list end-key)))) + (cl-letf (((symbol-function #'this-single-command-keys) + (lambda () first-event))) + (use-local-map kmacro-tests-keymap) + (kmacro-tests-should-insert "ccbacb" + ;; End #3 and launch loop to read events. + (kmacro-end-or-call-macro-repeat nil)))) + + ;; `kmacro-edit-macro-repeat' should also stop the sequence, + ;; so run it again with that at the end. + (let* ((end-key (kmacro-tests-get-kmacro-key 'kmacro-edit-macro-repe= at)) + (kmacro-tests-events (append events (list end-key)))) + (cl-letf (((symbol-function #'edit-kbd-macro) #'ignore) + ((symbol-function #'this-single-command-keys) + (lambda () first-event))) + (use-local-map kmacro-tests-keymap) + (kmacro-tests-should-insert "bbbbbaaba" + (kmacro-end-or-call-macro-repeat 3))))))) + +(kmacro-tests-deftest kmacro-tests-repeat-view-and-run () + "Kmacro view cycles through ring and executes macro just viewed." + (let* ((prefix (where-is-internal 'kmacro-keymap nil t)) + (kmacro-tests-events + (mapcar #'kmacro-tests-get-kmacro-key + (append (make-list 5 'kmacro-view-macro-repeat) + '(kmacro-end-or-call-macro-repeat + kmacro-set-counter)))) + ;; Make kmacro see this as keyboard command sequence. + (first-event (seq-concatenate + 'vector + prefix + (vector (kmacro-tests-get-kmacro-key + 'kmacro-view-macro-repeat)))) + ;; Construct a regexp to match the messages which should be + ;; produced by repeated view-repeats. + (macros-regexp (apply #'concat + (mapcar (lambda (c) (format ".+%s\n" c)) + '("d" "c" "b" "a" "d" "c"))))) + (cl-letf ((kmacro-repeat-no-prefix t) + (kmacro-call-repeat-key t) + (kmacro-call-repeat-with-arg nil) + ((symbol-function #'this-single-command-keys) (lambda () + first-event)= )) + ;; "Record" some macros. + (dotimes (n 4) + (kmacro-tests-define-macro (make-vector 1 (+ ?a n)))) + + (use-local-map kmacro-tests-keymap) + ;; 6 views (the direct call plus the 5 in events) should + ;; cycle through the ring and get to the second-to-last + ;; macro defined. + (kmacro-tests-should-insert "c" + (kmacro-tests-should-match-message macros-regexp + (kmacro-tests-simulate-command '(kmacro-view-macro-repeat nil)))= )))) + +(kmacro-tests-deftest kmacro-tests-bind-to-key-when-recording () + "Bind to key doesn't bind a key during macro recording." + (cl-letf ((global-map global-map) + (saved-binding (key-binding "\C-a")) + (kmacro-tests-sequences (list "\C-a"))) + (kmacro-tests-simulate-command '(kmacro-start-macro 1)) + (kmacro-bind-to-key nil) + (should (eq saved-binding (key-binding "\C-a"))))) + +(kmacro-tests-deftest kmacro-tests-name-or-bind-to-key-when-no-macro () + "Bind to key, symbol or register fails when when no macro exists." + (should-error (kmacro-bind-to-key nil)) + (should-error (kmacro-name-last-macro 'kmacro-tests-symbol-for-test)) + (should-error (kmacro-to-register))) + +(kmacro-tests-deftest kmacro-tests-bind-to-key-bad-key-sequence () + "Bind to key fails to bind to ^G." + (let ((global-map global-map) + (saved-binding (key-binding "\C-g")) + (kmacro-tests-sequences (list "\C-g"))) + (kmacro-tests-define-macro [1]) + (kmacro-bind-to-key nil) + (should (eq saved-binding (key-binding "\C-g"))))) + +(kmacro-tests-deftest kmacro-tests-bind-to-key-with-key-sequence-in-use () + "Bind to key respects yes-or-no-p when given already bound key sequence." + (kmacro-tests-define-macro (vconcat "abaab")) + (let ((global-map global-map) + (map (make-sparse-keymap)) + (kmacro-tests-sequences (make-list 2 "\C-hi"))) + (define-key map "\C-hi" 'info) + (use-local-map map) + ;; Try the command with yes-or-no-p set up to say no. + (cl-letf (((symbol-function #'yes-or-no-p) + (lambda (prompt) + (should (string-match-p "info" prompt)) + (should (string-match-p "C-h i" prompt)) + nil))) + (kmacro-bind-to-key nil)) + + (should (equal (where-is-internal 'info nil t) + (vconcat "\C-hi"))) + ;; Try it again with yes. + (cl-letf (((symbol-function #' yes-or-no-p) + (lambda (_prompt) t))) + (kmacro-bind-to-key nil)) + + (should-not (equal (where-is-internal 'info global-map t) + (vconcat "\C-hi"))) + (use-local-map nil) + (kmacro-tests-should-insert "abaab" + (funcall (key-binding "\C-hi"))))) + +(kmacro-tests-deftest kmacro-tests-kmacro-bind-to-single-key () + "Bind to key uses C-x C-k A when asked to bind to A." + (let ((global-map global-map) + (kmacro-tests-macros (list (string-to-vector "\C-cxi")))) + (use-local-map kmacro-tests-keymap) + + ;; Record a macro with counter and format set. + (kmacro-set-format "<%d>") + (kmacro-tests-simulate-command '(kmacro-start-macro-or-insert-counter = 5)) + (kmacro-tests-simulate-command '(kmacro-end-macro nil)) + + (let ((kmacro-tests-sequences (list "A"))) + (kmacro-bind-to-key nil)) + + ;; Record a second macro with different counter and format. + (kmacro-set-format "%d") + (kmacro-tests-define-macro [2]) + + ;; Check the bound key and run it and verify correct counter + ;; and format. + (should (equal (string-to-vector "\C-cxi") + (car (kmacro-extract-lambda + (key-binding "\C-x\C-kA"))))) + (kmacro-tests-should-insert "<5>" + (funcall (key-binding "\C-x\C-kA"))))) + +(kmacro-tests-deftest kmacro-tests-name-last-macro-unable-to-bind () + "Name last macro won't bind to symbol which is already bound." + (kmacro-tests-define-macro [1]) + ;; Set up a test symbol which looks like a function. + (setplist 'kmacro-tests-symbol-for-test nil) + (fset 'kmacro-tests-symbol-for-test #'ignore) + (should-error (kmacro-name-last-macro 'kmacro-tests-symbol-for-test)) + ;; The empty string symbol also can't be bound. + (should-error (kmacro-name-last-macro (make-symbol "")))) + +(kmacro-tests-deftest kmacro-tests-name-last-macro-bind-and-rebind () + "Name last macro can rebind a symbol it binds." + ;; Make sure our symbol is unbound. + (when (fboundp 'kmacro-tests-symbol-for-test) + (fmakunbound 'kmacro-tests-symbol-for-test)) + (setplist 'kmacro-tests-symbol-for-test nil) + ;; Make two macros and bind them to the same symbol. + (dotimes (i 2) + (kmacro-tests-define-macro (make-vector (1+ i) (+ ?a i))) + (kmacro-name-last-macro 'kmacro-tests-symbol-for-test) + (should (fboundp 'kmacro-tests-symbol-for-test))) + + ;; Now run the function bound to the symbol. Result should be the + ;; second macro. + (kmacro-tests-should-insert "bb" + (kmacro-tests-simulate-command '(kmacro-tests-symbol-for-test)))) + +(kmacro-tests-deftest kmacro-tests-store-in-register () + "Macro can be stored in and retrieved from a register." + (use-local-map kmacro-tests-keymap) + ;; Save and restore register 200 so we can use it for the test. + (let ((saved-reg-contents (get-register 200))) + (unwind-protect + (progn + ;; Define a macro, and save it to a register. + (kmacro-tests-define-macro (vconcat "a\C-a\C-cxu")) + (kmacro-to-register 200) + ;; Then make a new different macro. + (kmacro-tests-define-macro (vconcat "bb\C-a\C-cxu")) + ;; When called from the register, result should be first macro. + (kmacro-tests-should-insert "AAA" + (kmacro-tests-simulate-command '(jump-to-register 200 3) 3)) + (kmacro-tests-should-insert "a C-a C-c x u" + (kmacro-tests-simulate-command '(insert-register 200 t) '(4)))) + (set-register 200 saved-reg-contents)))) + +(kmacro-tests-deftest kmacro-tests-step-edit-act () + "Step-edit steps-through a macro with act and act-repeat." + (kmacro-tests-run-step-edit "he\C-u2lo" + :events (make-list 6 'act) + :result "hello" + :macro-result "he\C-u2lo") + + (kmacro-tests-run-step-edit "f\C-aoo\C-abar" + :events (make-list 5 'act-repeat) + :result "baroof" + :macro-result "f\C-aoo\C-abar")) + +(kmacro-tests-deftest kmacro-tests-step-edit-skip () + "Step-editing can skip parts of macro." + (kmacro-tests-run-step-edit "ofoofff" + :events '(skip skip-keep skip-keep skip-keep + skip-rest) + :result "" + :macro-result "foo")) + +(kmacro-tests-deftest kmacro-tests-step-edit-quit () + "Quit while step-editing leaves macro unchanged." + (kmacro-tests-run-step-edit "bar" + :events '(help insert skip help quit) + :sequences '("f" "o" "o" "\C-j") + :result "foo" + :macro-result "bar")) + +(kmacro-tests-deftest kmacro-tests-step-insert () + "Step edit can insert in macro." + (kmacro-tests-run-step-edit "fbazbop" + :events '(insert act insert-1 act-repeat) + :sequences '("o" "o" "\C-a" "\C-j" "\C-e") + :result "foobazbop" + :macro-result "oo\C-af\C-ebazbop")) + +(kmacro-tests-deftest kmacro-tests-step-edit-replace-digit-argument () + "Step-edit replace can replace a numeric argument in a macro. +This is a regression for item 1 in Bug#24991." + (:expected-result :failed) + (kmacro-tests-run-step-edit "\C-u3b\C-a\C-cxu" + :events '(act replace automatic) + :sequences '("8" "x" "\C-j") + :result "XXXXXXXX" + :macro-result "\C-u8x\C-a\C-cxu")) + +(kmacro-tests-deftest kmacro-tests-step-edit-replace () + "Step-edit replace and replace-1 can replace parts of a macro." + (kmacro-tests-run-step-edit "a\C-a\C-cxu" + :events '(act act replace) + :sequences '("b" "c" "\C-j") + :result "bca" + :macro-result "a\C-abc") + (kmacro-tests-run-step-edit "a\C-a\C-cxucd" + :events '(act replace-1 automatic) + :sequences '("b") + :result "abcd" + :macro-result "ab\C-cxucd") + (kmacro-tests-run-step-edit "by" + :events '(act replace) + :sequences '("a" "r" "\C-j") + :result "bar" + :macro-result "bar")) + +(kmacro-tests-deftest kmacro-tests-step-edit-append () + "Step edit append inserts after point, and append-end inserts at end." + (kmacro-tests-run-step-edit "f-b" + :events '(append append-end) + :sequences '("o" "o" "\C-j" "a" "r" "\C-j") + :result "foo-bar" + :macro-result "foo-bar") + (kmacro-tests-run-step-edit "x" + :events '(append) + :sequences '("\C-a" "\C-cxu" "\C-e" "y" "\C-= j") + :result "Xy" + :macro-result "x\C-a\C-cxu\C-ey")) + +(kmacro-tests-deftest kmacro-tests-append-end-at-end-appends () + "Append-end when already at end of macro appends to end of macro. +This is a regression for item 2 in Bug#24991." + (:expected-result :failed) + (kmacro-tests-run-step-edit "x" + :events '(append-end) + :sequences '("\C-a" "\C-cxu" "\C-e" "y" "\C-= j") + :result "Xy" + :macro-result "x\C-a\C-cxu\C-ey")) + + +(kmacro-tests-deftest kmacro-tests-step-edit-skip-entire () + "Skipping a whole macro in step-edit leaves macro unchanged. +This is a regression for item 3 in Bug#24991." + (:expected-result :failed) + (kmacro-tests-run-step-edit "xyzzy" + :events '(skip-rest) + :result "" + :macro-result "xyzzy")) + +(kmacro-tests-deftest kmacro-tests-step-edit-step-through-negative-argumen= t () + "Step edit works on macros using negative universal argument. +This is a regression for item 4 in Bug#24991." + (:expected-result :failed) + (kmacro-tests-run-step-edit "boo\C-u-\C-cu" + :events '(act-repeat automatic) + :result "BOO" + :macro-result "boo\C-u-\C-cd")) + +(kmacro-tests-deftest kmacro-tests-step-edit-with-quoted-insert () + "Stepping through a macro that uses quoted insert leaves macro unchanged. +This is a regression for item 5 in Bug#24991." + (:expected-result :failed) + (let ((read-quoted-char-radix 8)) + (kmacro-tests-run-step-edit "\C-cxq17051i there" + :events '(act automatic) + :result "=E1=B8=A9i there" + :macro-result "\C-cxq17051i there") + (kmacro-tests-run-step-edit "g\C-cxq17051i" + :events '(act insert-1 automatic) + :sequences '("-") + :result "g-=E1=B8=A9i" + :macro-result "g-\C-cxq17051i"))) + +(kmacro-tests-deftest kmacro-tests-step-edit-can-replace-meta-keys () + "Replacing C-w with M-w produces the expected result. +This is a regression for item 7 in Bug#24991." + (:expected-result :failed) + (kmacro-tests-run-step-edit "abc\C-b\C-b\C-SPC\C-f\C-w\C-e\C-y" + :events '(act-repeat act-repeat + act-repeat act-repeat + replace automatic) + :sequences '("\M-w" "\C-j") + :result "abcb" + :macro-result "abc\C-b\C-b\C-SPC\C-f\M-w\C-e= \C-y") + (kmacro-tests-should-insert "abcb" (kmacro-call-macro nil))) + +(kmacro-tests-deftest kmacro-tests-step-edit-ignores-qr-map-commands () + "Unimplemented commands from `query-replace-map' are ignored." + (kmacro-tests-run-step-edit "yep" + :events '(edit-replacement + act-and-show act-and-exit + delete-and-edit + recenter backup + scroll-up scroll-down + scroll-other-window + scroll-other-window-down + exit-prefix + act act act) + :result "yep" + :macro-result "yep")) + +(kmacro-tests-deftest + kmacro-tests-step-edit-edits-macro-with-extended-command () + "Step-editing a macro which uses the minibuffer can change the macro." + (let ((mac (vconcat [?\M-x] "eval-expression" '[return] + "(insert-char (+ ?a \C-e" [?1] "))" '[return])) + (mac-after (vconcat [?\M-x] "eval-expression" '[return] + "(insert-char (+ ?a \C-e" [?2] "))" '[return])= )) + + (kmacro-tests-run-step-edit mac + :events '(act act-repeat + act act-repeat act + replace-1 act-repeat act) + :sequences '("2") + :result "c" + :macro-result mac-after))) + +(kmacro-tests-deftest kmacro-tests-step-edit-step-through-isearch () + "Step-editing can edit a macro which uses `isearch-backward' (Bug#22488)= ." + (:expected-result :failed) + (let ((mac (vconcat "test Input" '[return] + [?\C-r] "inp" '[return] "\C-cxu")) + (mac-after (vconcat "test input" '[return] + [?\C-r] "inp" '[return] "\C-cd"))) + + (kmacro-tests-run-step-edit mac + :events '(act-repeat act act + act-repeat act + replace-1) + :sequences '("\C-cd") + :result "test input\n" + :macro-result mac-after))) + +(kmacro-tests-deftest kmacro-tests-step-edit-cleans-up-hook () + "Step-editing properly cleans up `post-command-hook.' (Bug #18708)" + (:expected-result :failed) + (let (post-command-hook) + (setq-local post-command-hook '(t)) + (kmacro-tests-run-step-edit "x" + :events '(act) + :result "x" + :macro-result "x") + (kmacro-tests-simulate-command '(beginning-of-line)))) + +(cl-defun kmacro-tests-run-step-edit + (macro &key events sequences result macro-result) + "Set up and run a test of `kmacro-step-edit-macro'. + +Run `kmacro-step-edit-macro' with MACRO defined as a keyboard macro +and `read-event' and `read-key-sequence' set up to return items from +EVENTS and SEQUENCES respectively. SEQUENCES may be nil, but +EVENTS should not be. EVENTS should be a list of symbols bound +in `kmacro-step-edit-map' or `query-replace' map, and this function +will do the keymap lookup for you. SEQUENCES should contain +return values for `read-key-sequence'. + +Before running the macro, the current buffer will be erased. +RESULT is the string that should be inserted during the +step-editing process, and MACRO-RESULT is the expected value of +`last-kbd-macro' after the editing is complete." + + (let* ((kmacro-tests-events (mapcar #'kmacro-tests-get-kmacro-step-edit-= key events)) + (kmacro-tests-sequences sequences)) + + (kmacro-tests-define-macro (string-to-vector macro)) + (use-local-map kmacro-tests-keymap) + (erase-buffer) + (kmacro-step-edit-macro) + (when result + (should (equal result (buffer-string)))) + (when macro-result + (should (equal last-kbd-macro (string-to-vector macro-result)))))) + +;;; Utilities: + +(defun kmacro-tests-simulate-command (command &optional arg) + "Call `ert-simulate-command' after setting `current-prefix-arg'. +Sets `current-prefix-arg' to ARG if it is non-nil, otherwise to +the second element of COMMAND, before executing COMMAND using +`ert-simulate-command'." + (let ((current-prefix-arg (or arg (cadr command)))) + (ert-simulate-command command))) + +(defun kmacro-tests-define-macro (mac) + "Define MAC as a keyboard macro using kmacro commands." + (push mac kmacro-tests-macros) + (kmacro-tests-simulate-command '(kmacro-start-macro nil)) + (should defining-kbd-macro) + (kmacro-tests-simulate-command '(kmacro-end-macro nil)) + (should (equal mac last-kbd-macro))) + +(defun kmacro-tests-get-kmacro-key (sym) + "Look up kmacro command SYM in kmacro's keymap. +Return the integer key value found." + (aref (where-is-internal sym kmacro-keymap t) 0)) + +(defun kmacro-tests-get-kmacro-step-edit-key (sym) + "Return the first key bound to SYM in `kmacro-step-edit-map'." + (let ((where (aref (where-is-internal sym kmacro-step-edit-map t) 0))) + (if (consp where) + (car where) + where))) + +(provide 'kmacro-tests) + +;;; kmacro-tests.el ends here --=20 2.10.1 --=-=-=-- From unknown Fri Aug 15 20:05:16 2025 X-Loop: help-debbugs@gnu.org Subject: bug#25068: 25.1; Edebug fails to instrument code which uses propertized strings Resent-From: Gemini Lasswell Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 05 Feb 2017 01:51:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 25068 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: To: Eli Zaretskii Cc: 25068@debbugs.gnu.org Received: via spool by 25068-submit@debbugs.gnu.org id=B25068.148625941829960 (code B ref 25068); Sun, 05 Feb 2017 01:51:01 +0000 Received: (at 25068) by debbugs.gnu.org; 5 Feb 2017 01:50:18 +0000 Received: from localhost ([127.0.0.1]:56404 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1caBy5-0007n9-N3 for submit@debbugs.gnu.org; Sat, 04 Feb 2017 20:50:17 -0500 Received: from aibo.runbox.com ([91.220.196.211]:50942) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1caBy4-0007n1-6K for 25068@debbugs.gnu.org; Sat, 04 Feb 2017 20:50:16 -0500 Received: from [10.9.9.211] (helo=mailfront11.runbox.com) by mailtransmit02.runbox with esmtp (Exim 4.86_2) (envelope-from ) id 1caBy1-0005Bh-L8; Sun, 05 Feb 2017 02:50:13 +0100 Received: from c-24-22-244-161.hsd1.wa.comcast.net ([24.22.244.161] helo=rainbow.local) by mailfront11.runbox.com with esmtpsa (uid:179284 ) (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.82) id 1caBxn-0004hZ-RN; Sun, 05 Feb 2017 02:50:00 +0100 From: Gemini Lasswell References: <83inoq8adw.fsf@gnu.org> Date: Sat, 04 Feb 2017 17:49:49 -0800 In-Reply-To: (Gemini Lasswell's message of "Sat, 04 Feb 2017 09:39:51 -0800") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.0.50 (darwin) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Spam-Score: -0.7 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.7 (/) --=-=-= Content-Type: text/plain Gemini Lasswell writes: > This could be fixed by updating the list in edebug-read-function of > characters that might possibly follow # to keep up with the changes to > read1 since the last time that list was updated (in 2001). But I think > it's better to remove the test entirely. If there is an invalid > character then read1 will report a syntax error. Ooops, attached the wrong patch. Here's the right one: --=-=-= Content-Type: text/plain Content-Disposition: attachment; filename=0001-Remove-syntax-error-check-from-edebug-read-function-.patch >From 781b23e55488f80ab310f376cf27b5066fea7114 Mon Sep 17 00:00:00 2001 From: Gemini Lasswell Date: Sat, 4 Feb 2017 08:39:55 -0800 Subject: [PATCH] Remove syntax error check from edebug-read-function (Bug#25068) * lisp/emacs-lisp/edebug.el (edebug-read-function): Allow `read' to decide what is and isn't a syntax error. --- lisp/emacs-lisp/edebug.el | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index ec0f08d..a883804 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -880,11 +880,9 @@ edebug-read-function (list (edebug-storing-offsets (- (point) 2) 'function) (edebug-read-storing-offsets stream))) - ((memq (following-char) '(?: ?B ?O ?X ?b ?o ?x ?1 ?2 ?3 ?4 ?5 ?6 - ?7 ?8 ?9 ?0)) + (t (backward-char 1) - (read stream)) - (t (edebug-syntax-error "Bad char after #")))) + (read stream)))) (defun edebug-read-list (stream) (forward-char 1) ; skip \( -- 2.10.1 --=-=-=-- From unknown Fri Aug 15 20:05:16 2025 MIME-Version: 1.0 X-Mailer: MIME-tools 5.505 (Entity 5.505) X-Loop: help-debbugs@gnu.org From: help-debbugs@gnu.org (GNU bug Tracking System) To: Gemini Lasswell Subject: bug#25068: closed (Re: bug#25068: 25.1; Edebug fails to instrument code which uses propertized strings) Message-ID: References: <838tpe4ca1.fsf@gnu.org> X-Gnu-PR-Message: they-closed 25068 X-Gnu-PR-Package: emacs Reply-To: 25068@debbugs.gnu.org Date: Fri, 10 Feb 2017 09:38:02 +0000 Content-Type: multipart/mixed; boundary="----------=_1486719482-11423-1" This is a multi-part message in MIME format... ------------=_1486719482-11423-1 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Your bug report #25068: 25.1; Edebug fails to instrument code which uses propertized strings which was filed against the emacs package, has been closed. The explanation is attached below, along with your original report. If you require more details, please reply to 25068@debbugs.gnu.org. --=20 25068: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=3D25068 GNU Bug Tracking System Contact help-debbugs@gnu.org with problems ------------=_1486719482-11423-1 Content-Type: message/rfc822 Content-Disposition: inline Content-Transfer-Encoding: 7bit Received: (at 25068-done) by debbugs.gnu.org; 10 Feb 2017 09:37:30 +0000 Received: from localhost ([127.0.0.1]:33821 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cc7dy-0002xY-4o for submit@debbugs.gnu.org; Fri, 10 Feb 2017 04:37:30 -0500 Received: from eggs.gnu.org ([208.118.235.92]:39744) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cc7dw-0002xL-Jn for 25068-done@debbugs.gnu.org; Fri, 10 Feb 2017 04:37:28 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cc7dn-0001xW-EM for 25068-done@debbugs.gnu.org; Fri, 10 Feb 2017 04:37:23 -0500 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=BAYES_20,RP_MATCHES_RCVD autolearn=disabled version=3.3.2 Received: from fencepost.gnu.org ([2001:4830:134:3::e]:59514) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cc7dn-0001xS-BS; Fri, 10 Feb 2017 04:37:19 -0500 Received: from 84.94.185.246.cable.012.net.il ([84.94.185.246]:4580 helo=home-c4e4a596f7) by fencepost.gnu.org with esmtpsa (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.82) (envelope-from ) id 1cc7dm-0000fP-ML; Fri, 10 Feb 2017 04:37:19 -0500 Date: Fri, 10 Feb 2017 11:37:26 +0200 Message-Id: <838tpe4ca1.fsf@gnu.org> From: Eli Zaretskii To: Gemini Lasswell In-reply-to: (message from Gemini Lasswell on Sat, 04 Feb 2017 17:49:49 -0800) Subject: Re: bug#25068: 25.1; Edebug fails to instrument code which uses propertized strings References: <83inoq8adw.fsf@gnu.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2001:4830:134:3::e X-Spam-Score: -5.0 (-----) X-Debbugs-Envelope-To: 25068-done Cc: 25068-done@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Eli Zaretskii Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -5.0 (-----) > From: Gemini Lasswell > Cc: 25068@debbugs.gnu.org > Date: Sat, 04 Feb 2017 17:49:49 -0800 > > Gemini Lasswell writes: > > > This could be fixed by updating the list in edebug-read-function of > > characters that might possibly follow # to keep up with the changes to > > read1 since the last time that list was updated (in 2001). But I think > > it's better to remove the test entirely. If there is an invalid > > character then read1 will report a syntax error. > > Ooops, attached the wrong patch. Here's the right one: Thanks, pushed. ------------=_1486719482-11423-1 Content-Type: message/rfc822 Content-Disposition: inline Content-Transfer-Encoding: 7bit Received: (at submit) by debbugs.gnu.org; 29 Nov 2016 23:10:40 +0000 Received: from localhost ([127.0.0.1]:46613 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cBrXs-0004Qf-Jt for submit@debbugs.gnu.org; Tue, 29 Nov 2016 18:10:40 -0500 Received: from eggs.gnu.org ([208.118.235.92]:58646) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cBrXr-0004QS-4H for submit@debbugs.gnu.org; Tue, 29 Nov 2016 18:10:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cBrXk-0005vx-Ni for submit@debbugs.gnu.org; Tue, 29 Nov 2016 18:10:33 -0500 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=BAYES_50,FREEMAIL_FROM autolearn=disabled version=3.3.2 Received: from lists.gnu.org ([2001:4830:134:3::11]:60150) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cBrXk-0005vr-Jm for submit@debbugs.gnu.org; Tue, 29 Nov 2016 18:10:32 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49598) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cBrXj-0008Nj-Ar for bug-gnu-emacs@gnu.org; Tue, 29 Nov 2016 18:10:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cBrXg-0005ux-03 for bug-gnu-emacs@gnu.org; Tue, 29 Nov 2016 18:10:31 -0500 Received: from aibo.runbox.com ([91.220.196.211]:39724) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cBrXf-0005uX-Ob for bug-gnu-emacs@gnu.org; Tue, 29 Nov 2016 18:10:27 -0500 Received: from [10.9.9.212] (helo=mailfront12.runbox.com) by bars.runbox.com with esmtp (Exim 4.71) (envelope-from ) id 1cBrXd-0004rh-AS for bug-gnu-emacs@gnu.org; Wed, 30 Nov 2016 00:10:25 +0100 Received: from c-24-22-244-161.hsd1.wa.comcast.net ([24.22.244.161] helo=rainbow.local) by mailfront12.runbox.com with esmtpsa (uid:179284 ) (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.82) id 1cBrXX-0001Sv-D9 for bug-gnu-emacs@gnu.org; Wed, 30 Nov 2016 00:10:20 +0100 From: Gemini Lasswell To: bug-gnu-emacs@gnu.org Subject: 25.1; Edebug fails to instrument code which uses propertized strings Date: Tue, 29 Nov 2016 15:10:16 -0800 Message-ID: MIME-Version: 1.0 Content-Type: text/plain X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x [fuzzy] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 2001:4830:134:3::11 X-Spam-Score: -4.1 (----) X-Debbugs-Envelope-To: submit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -4.1 (----) Edebug gives an error message if you try to use it on code which uses strings with text properties. To reproduce, using emacs -Q if you like, enter the following code into *scratch* and type C-u C-M-x: (defun my-fun () (message "%s" #("abcd" 1 3 (face italic)))) This results in the error message: "Invalid read syntax: "Bad char after #" Here is the backtrace: Debugger entered--Lisp error: (invalid-read-syntax "Bad char after #") signal(invalid-read-syntax ("Bad char after #")) edebug-syntax-error("Bad char after #") edebug-read-function(#) edebug-read-storing-offsets(#) edebug-read-list(#) edebug-read-storing-offsets(#) edebug-read-list(#) edebug-read-storing-offsets(#) edebug-read-and-maybe-wrap-form1() edebug-read-and-maybe-wrap-form() edebug-read-top-level-form() edebug-eval-defun((4)) apply(edebug-eval-defun (4)) eval-defun((4)) funcall-interactively(eval-defun (4)) call-interactively(eval-defun nil nil) command-execute(eval-defun) In GNU Emacs 25.1.1 (x86_64-apple-darwin15.6.0, NS appkit-1404.47 Version 10.11.6 (Build 15G1004)) of 2016-10-09 built on rainbow.local Windowing system distributor 'Apple', version 10.3.1404 Configured using: 'configure --disable-dependency-tracking --disable-silent-rules --enable-locallisppath=/usr/local/share/emacs/site-lisp --infodir=/usr/local/Cellar/emacs/25.1/share/info/emacs --prefix=/usr/local/Cellar/emacs/25.1 --without-x --with-xml2 --without-dbus --with-gnutls --with-imagemagick --with-rsvg --with-ns --disable-ns-self-contained' Configured features: JPEG RSVG IMAGEMAGICK NOTIFY ACL GNUTLS LIBXML2 ZLIB TOOLKIT_SCROLL_BARS NS Important settings: value of $LANG: en_US.UTF-8 locale-coding-system: utf-8-unix Major mode: Lisp Interaction Minor modes in effect: tooltip-mode: t global-eldoc-mode: t electric-indent-mode: t mouse-wheel-mode: t tool-bar-mode: t menu-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t blink-cursor-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t line-number-mode: t transient-mark-mode: t Recent messages: For information about GNU Emacs and the GNU system, type C-h C-a. Mark set edebug-syntax-error: Invalid read syntax: "Bad char after #" Load-path shadows: None found. Features: (shadow sort mail-extr emacsbug message dired format-spec rfc822 mml mml-sec password-cache epg epg-config gnus-util mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045 ietf-drums mm-util help-fns help-mode mail-prsvr mail-utils edebug easymenu cl-loaddefs pcase cl-lib time-date mule-util tooltip eldoc electric uniquify ediff-hook vc-hooks lisp-float-type mwheel ns-win ucs-normalize term/common-win tool-bar dnd fontset image regexp-opt fringe tabulated-list newcomment elisp-mode lisp-mode prog-mode register page menu-bar rfn-eshadow timer select scroll-bar mouse jit-lock font-lock syntax facemenu font-core frame cl-generic cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese charscript case-table epa-hook jka-cmpr-hook help simple abbrev minibuffer cl-preloaded nadvice loaddefs button faces cus-face macroexp files text-properties overlay sha1 md5 base64 format env code-pages mule custom widget hashtable-print-readable backquote kqueue cocoa ns multi-tty make-network-process emacs) Memory information: ((conses 16 198711 10003) (symbols 48 20106 0) (miscs 40 50 167) (strings 32 16048 5094) (string-bytes 1 457556) (vectors 16 33450) (vector-slots 8 658299 4717) (floats 8 160 49) (intervals 56 222 0) (buffers 976 17)) ------------=_1486719482-11423-1--