From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Michael Kifer Newsgroups: gmane.emacs.bugs Subject: bug#13793: 24.3.50; M-x broken in viper and X Date: Thu, 04 Jul 2013 17:13:05 -0400 Message-ID: <51D5E561.5070802@stonybrook.edu> References: <20130223123501.43568c52@susi> <20130615122529.GA25730@upsilon.cc> <435158c2008843bb9bd4a75345251bbe@HUBCAS1.cs.stonybrook.edu> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Trace: ger.gmane.org 1372972475 23433 80.91.229.3 (4 Jul 2013 21:14:35 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 4 Jul 2013 21:14:35 +0000 (UTC) Cc: "13793@debbugs.gnu.org" <13793@debbugs.gnu.org>, Stefano Zacchiroli To: Stefan Monnier Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Thu Jul 04 23:14:35 2013 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 1UuqrK-0006yp-Ns for geb-bug-gnu-emacs@m.gmane.org; Thu, 04 Jul 2013 23:14:35 +0200 Original-Received: from localhost ([::1]:56970 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UuqrK-0007kI-9p for geb-bug-gnu-emacs@m.gmane.org; Thu, 04 Jul 2013 17:14:34 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:58800) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Uuqr2-0007SK-ER for bug-gnu-emacs@gnu.org; Thu, 04 Jul 2013 17:14:32 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Uuqqp-0005Js-2D for bug-gnu-emacs@gnu.org; Thu, 04 Jul 2013 17:14:16 -0400 Original-Received: from debbugs.gnu.org ([140.186.70.43]:35551) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Uuqqo-0005Jm-QN for bug-gnu-emacs@gnu.org; Thu, 04 Jul 2013 17:14:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.80) (envelope-from ) id 1Uuqqn-0007zw-WE for bug-gnu-emacs@gnu.org; Thu, 04 Jul 2013 17:14:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Michael Kifer Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Thu, 04 Jul 2013 21:14:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 13793 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 13793-submit@debbugs.gnu.org id=B13793.137297240130669 (code B ref 13793); Thu, 04 Jul 2013 21:14:01 +0000 Original-Received: (at 13793) by debbugs.gnu.org; 4 Jul 2013 21:13:21 +0000 Original-Received: from localhost ([127.0.0.1]:58092 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Uuqq6-0007yW-IP for submit@debbugs.gnu.org; Thu, 04 Jul 2013 17:13:21 -0400 Original-Received: from mail-gh0-f178.google.com ([209.85.160.178]:42399) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Uuqq0-0007yG-Sz for 13793@debbugs.gnu.org; Thu, 04 Jul 2013 17:13:16 -0400 Original-Received: by mail-gh0-f178.google.com with SMTP id g15so524871ghb.23 for <13793@debbugs.gnu.org>; Thu, 04 Jul 2013 14:13:07 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:cc:subject :references:in-reply-to:content-type:content-transfer-encoding :x-gm-message-state; bh=YsqdR7jViDEo2vQCV8e+HnILOKtqZJtfrIqIW7nYroU=; b=Yy3quC5FbWikYdAkNvOsUa+BLgEWX2U/RVmGVaN+OFmLMKloT4I19kToEhZN+f5F/4 znCbTfbBGXzPu6BxEGFVb7UY3MVWoVL/DTGhBpZrpY6r8egrF0fja9xV1DkiTsDwRBQ9 YAtA08Up6fRugttTT9hhxNp8xvcBkfhep7WXNlSGnLdiuaOhyf0fnZeU/wEBcr47mbw/ PYz3EpndxDenxtsjlHu/NoBwrNJ/nAqyyvZoaiAa2NCT6Rww9/UrakTAIeQiMHo77DE2 N1izEtDfn7VerZLbADOSgwAUkdJucn594l4v5rMLKlBj1rBeh7eApYDxrwxhXdnOFzP/ UxQw== X-Received: by 10.236.202.211 with SMTP id d59mr4089793yho.221.1372972387406; Thu, 04 Jul 2013 14:13:07 -0700 (PDT) Original-Received: from [192.168.1.106] (ool-18bf47c9.dyn.optonline.net. [24.191.71.201]) by mx.google.com with ESMTPSA id f67sm7519102yhh.9.2013.07.04.14.13.06 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 04 Jul 2013 14:13:06 -0700 (PDT) User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130510 Thunderbird/17.0.6 In-Reply-To: <435158c2008843bb9bd4a75345251bbe@HUBCAS1.cs.stonybrook.edu> X-Gm-Message-State: ALoCoQkpI22/38kTB+htm8xQsWAwfnVJYwk3tJnKVelMBVfWZfNHMXCBwOgMJqSiv7EDOMJhXgBo X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x 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:75919 Archived-At: Stefan,
the patch seems to be working. Thanks for fixing it.
I'll play with it some more and will then commit.

--

       --- michael


On 06/22/2013 05:56 PM, Stefan Monnier wrote:
Heya, just checking back about the status of this bug report. I'm
affected by it and I've been stuck with Emacs 23 since its first arrival
(or else I can jump back on Emacs 24.3.x ditching viper all together,
which might even be a good thing for my saneness :-))
I don't understand all of what Viper does with the ESC key, nor do
I know what are the different cases where ESC has to behave in
a specific way, so it's difficult for me to come up with
a trustworthy patch.

Could you try the patch below under X11 and under a tty, ideally even
using emacsclient to create new X11 and tty frames?

Michael, could you also take a look at this patch?


        Stefan


=== modified file 'lisp/emulation/viper-cmd.el'
--- lisp/emulation/viper-cmd.el	2013-06-18 20:24:44 +0000
+++ lisp/emulation/viper-cmd.el	2013-06-22 21:40:32 +0000
@@ -996,93 +996,7 @@
 	(suspend-emacs))
     (viper-change-state-to-emacs)))
 
-
-;; Intercept ESC sequences on dumb terminals.
-;; Based on the idea contributed by Marcelino Veiga Tuimil <mveiga@dit.upm.es>
-
-;; Check if last key was ESC and if so try to reread it as a function key.
-;; But only if there are characters to read during a very short time.
-;; Returns the last event, if any.
-(defun viper-envelop-ESC-key ()
-  (let ((event last-input-event)
-	(keyseq [nil])
-	(inhibit-quit t))
-    (if (viper-ESC-event-p event)
-	(progn
-	  ;; Some versions of Emacs (eg., 22.50.8 (?)) have a bug, which makes
-          ;; even a single ESC into a fast keyseq. To guard against this, we
-	  ;; added a check if there are other events as well.  Keep the next
-	  ;; line for the next time the bug reappears, so that will remember to
-	  ;; report it.
-	  ;;(if (and (viper-fast-keysequence-p) unread-command-events)
-	  (if (viper-fast-keysequence-p) ;; for Emacsen without the above bug
-	      (progn
-		(let (minor-mode-map-alist emulation-mode-map-alists)
-		  (viper-set-unread-command-events event)
-		  (setq keyseq (read-key-sequence nil 'continue-echo))
-		  ) ; let
-		;; If keyseq translates into something that still has ESC
-		;; at the beginning, separate ESC from the rest of the seq.
-		;; In XEmacs we check for events that are keypress meta-key
-		;; and convert them into [escape key]
-		;;
-		;; This is needed for the following reason:
-		;; If ESC is the first symbol, we interpret it as if the
-		;; user typed ESC and then quickly some other symbols.
-		;; If ESC is not the first one, then the key sequence
-		;; entered was apparently translated into a function key or
-		;; something (e.g., one may have
-		;; (define-key function-key-map "\e[192z" [f11])
-		;; which would translate the escape-sequence generated by
-		;; f11 in an xterm window into the symbolic key f11.
-		;;
-		;; If `first-key' is not an ESC event, we make it into the
-		;; last-command-event in order to pretend that this key was
-		;; pressed.  This is needed to allow arrow keys to be bound to
-		;; macros.  Otherwise, viper-exec-mapped-kbd-macro will think
-		;; that the last event was ESC and so it'll execute whatever is
-		;; bound to ESC. (Viper macros can't be bound to
-		;; ESC-sequences).
-		(let* ((first-key (elt keyseq 0))
-		       (key-mod (event-modifiers first-key)))
-		  (cond ((and (viper-ESC-event-p first-key)
-			      (not (viper-translate-all-ESC-keysequences)))
-			 ;; put keys following ESC on the unread list
-			 ;; and return ESC as the key-sequence
-			 (viper-set-unread-command-events (viper-subseq keyseq 1))
-			 (setq last-input-event event
-			       keyseq (if (featurep 'emacs)
-					  "\e"
-					(vector (character-to-event ?\e)))))
-			((and (featurep 'xemacs)
-			      (key-press-event-p first-key)
-			      (equal '(meta) key-mod))
-			 (viper-set-unread-command-events
-			  (vconcat (vector
-				    (character-to-event (event-key first-key)))
-				   (viper-subseq keyseq 1)))
-			 (setq last-input-event event
-			       keyseq (vector (character-to-event ?\e))))
-			((eventp first-key)
-			 (setq last-command-event
-			       (viper-copy-event first-key)))
-			))
-		) ; end progn
-
-	    ;; this is escape event with nothing after it
-	    ;; put in unread-command-event and then re-read
-	    (viper-set-unread-command-events event)
-	    (setq keyseq (read-key-sequence nil))
-	    ))
-      ;; not an escape event
-      (setq keyseq (vector event)))
-    keyseq))
-
-
-
 ;; Listen to ESC key.
-;; If a sequence of keys starting with ESC is issued with very short delays,
-;; interpret these keys in Emacs mode, so ESC won't be interpreted as a Vi key.
 (defun viper-intercept-ESC-key ()
   "Function that implements ESC key in Viper emulation of Vi."
   (interactive)
@@ -1090,13 +1004,7 @@
   ;; minor-mode map(s) have been temporarily disabled so the ESC
   ;; binding to viper-intercept-ESC-key doesn't hide the binding we're
   ;; looking for (Bug#9146):
-  (let* ((event (viper-envelop-ESC-key))
-	 (cmd (cond ((equal event viper-ESC-key)
-		     'viper-intercept-ESC-key)
-		    ((let ((emulation-mode-map-alists nil))
-		       (key-binding event)))
-		    (t
-		     (error "Viper bell")))))
+  (let* ((cmd 'viper-intercept-ESC-key))
 
     ;; call the actual function to execute ESC (if no other symbols followed)
     ;; or the key bound to the ESC sequence (if the sequence was issued

=== modified file 'lisp/emulation/viper-keym.el'
--- lisp/emulation/viper-keym.el	2013-01-01 09:11:05 +0000
+++ lisp/emulation/viper-keym.el	2013-06-22 21:43:10 +0000
@@ -192,7 +192,7 @@
   :type 'string
   :group 'viper)
 
-(defvar viper-ESC-key (kbd "ESC")
+(defconst viper-ESC-key [escape]
   "Key used to ESC.")
 
 

=== modified file 'lisp/emulation/viper.el'
--- lisp/emulation/viper.el	2013-03-12 02:08:21 +0000
+++ lisp/emulation/viper.el	2013-06-22 21:54:55 +0000
@@ -660,7 +660,7 @@
 undone.
 It also can't undo some Viper settings."
   (interactive)
-
+  (viper-setup-ESC-to-escape nil)
   ;; restore non-viper vars
   (setq-default
    next-line-add-newlines
@@ -825,6 +825,58 @@
   (add-hook 'viper-post-command-hooks 'set-viper-state-in-major-mode t))
 
 
+;;; Handling of tty's ESC event
+
+;; On a tty, an ESC event can either be the user hitting the escape key, or
+;; some element of a byte sequence used to encode for example cursor keys.
+;; So we try to recognize those events that correspond to the escape key and
+;; turn them into `escape' events (same as used under GUIs).  The heuristic we
+;; use to distinguish the two cases is based, as usual, on a timeout, and on
+;; the fact that the special ESC=>escape mapping only takes place if the whole
+;; last key-sequence so far is just [?\e], i.e. either we're still in
+;; read-key-sequence, or the last read-key-sequence only read [?\e], which
+;; should ideally never happen because it should have been mapped to [escape].
+
+(defun viper--tty-ESC-filter (map)
+  (if (and (equal (this-single-command-keys) [?\e])
+           (sit-for (/ viper-fast-keyseq-timeout 1000)))
+      [escape] map))
+
+(defun viper--lookup-key (map key)
+  "Kind of like `lookup-key'.
+Two differences:
+- KEY is a single key, not a sequence.
+- the result is the \"raw\" binding, so it can be a `menu-item', rather than the
+  binding contained in that menu item."
+  (catch 'found
+    (map-keymap (lambda (k b) (if (equal key k) (throw 'found b))) map)))
+
+(defun viper-catch-tty-ESC ()
+  "Setup key mappings of current terminal to turn a tty's ESC into `escape'."
+  (when (memq (terminal-live-p (frame-terminal)) '(t pc))
+    (let ((esc-binding (viper-uncatch-tty-ESC)))
+      (define-key input-decode-map
+        [?\e] `(menu-item "" ,esc-binding :filter viper--tty-ESC-filter)))))
+
+(defun viper-uncatch-tty-ESC ()
+  "Don't hack ESC into `escape' any more."
+  (let ((b (viper--lookup-key input-decode-map ?\e)))
+    (and (eq 'menu-item (car-safe b))
+         (eq 'viper--tty-ESC-filter (nth 4 b))
+         (define-key input-decode-map [?\e] (setq b (nth 2 b))))
+    b))
+
+(defun viper-setup-ESC-to-escape (enable)
+  (if enable
+      (add-hook 'tty-setup-hook 'viper-catch-tty-ESC)
+    (remove-hook 'tty-setup-hook 'viper-catch-tty-ESC))
+  (let ((seen ()))
+    (dolist (frame (frame-list))
+      (let ((terminal (frame-terminal frame)))
+        (unless (memq terminal seen)
+          (push terminal seen)
+          (with-selected-frame frame
+            (if enable (viper-catch-tty-ESC) (viper-uncatch-tty-ESC))))))))
 
 ;; This sets major mode hooks to make them come up in vi-state.
 (defun viper-set-hooks ()
@@ -837,6 +889,8 @@
   (if (eq (default-value 'major-mode) 'fundamental-mode)
       (setq-default major-mode 'viper-mode))
 
+  (viper-setup-ESC-to-escape t)
+
   (add-hook 'change-major-mode-hook 'viper-major-mode-change-sentinel)
   (add-hook 'find-file-hooks 'set-viper-state-in-major-mode)
 
@@ -847,13 +901,6 @@
   (defvar emerge-startup-hook)
   (add-hook 'emerge-startup-hook 'viper-change-state-to-emacs)
 
-  ;; Zap bad bindings in flyspell-mouse-map, which prevent ESC from working
-  ;; over misspelled words (due to the overlay keymaps)
-  (defvar flyspell-mode-hook)
-  (defvar flyspell-mouse-map)
-  (add-hook 'flyspell-mode-hook
-	    (lambda ()
-              (define-key flyspell-mouse-map viper-ESC-key nil)))
   ;; if viper is started from .emacs, it might be impossible to get certain
   ;; info about the display and windows until emacs initialization is complete
   ;; So do it via the window-setup-hook

=== modified file 'lisp/faces.el'
--- lisp/faces.el	2013-05-15 23:55:41 +0000
+++ lisp/faces.el	2013-06-22 20:22:31 +0000
@@ -2126,7 +2126,8 @@
 		       type)
 	(when (fboundp term-init-func)
 	  (funcall term-init-func))
-	(set-terminal-parameter frame 'terminal-initted term-init-func)))))
+        (set-terminal-parameter frame 'terminal-initted term-init-func)
+	(run-hooks 'tty-setup-hook)))))
 
 ;; Called from C function init_display to initialize faces of the
 ;; dumped terminal frame on startup.