unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Drew Adams <drew.adams@oracle.com>
To: emacs-devel@gnu.org
Subject: bitten by lexical-binding
Date: Sat, 21 Nov 2015 14:28:11 -0800 (PST)	[thread overview]
Message-ID: <9b834ee9-4f63-42ca-98b4-c0f14986642e@default> (raw)

I should hardly complain without understanding completely
what is going on, but FWIW:

I redefine `mouse-drag-region', so that if you click in
the echo area when *Messages* is already displayed then:
(1) `M-x' is invoked and (2) the *Messages* window is
removed.  Otherwise, it behaves the same as the vanilla
version.

Not a big change, and this code has worked from Emacs 22
on.  And the part of the redefinition that differs from
the vanilla definition is not even in question here.

The vanilla definition of `mouse-drag-region' is this:

 (defun mouse-drag-region (start-event)
   (interactive "e")
   (run-hooks 'mouse-leave-buffer-hook)
   (mouse-drag-track start-event))

Prior to Emacs 24.4 it was the same, except the last line
had (mouse-drag-track start-event t).  My version of it too
had (mouse-drag-track start-event t).

Starting with Emacs 25, `mouse-drag-track' does not accept
the second arg.  But invoking it without that argument meant
that (my version of) `mouse-drag-region' no longer copied
the text to the kill ring, when `mouse-drag-copy-region'=t.
That was the problem.

I spent quite a while debugging this.  Using the debugger
or using calls to `message' to print out state was useless.

What changed in vanilla Emacs was `mouse-drag-track'.  It
now uses `set-transient-map' instead of handling a second
arg.  But finding just what change to make, to fix my code,
was really not easy.

It turned out (though I do not understand completely) that
the only thing I needed to do was to add a `lexical-binding'
declaration to my file.  (Luckily, the code in the file did
not depend on dynamic binding.)

My redefinition of `mouse-drag-region' does not make any
apparent use of visible lexical binding - no free vars,
no use of closures, etc.

`mouse-drag-track' does depend on lexical binding.  But
my code does not change `mouse-drag-track' in any way -
it just calls it, exactly the same way that vanilla Emacs
calls it.

Why is it that with dynamic binding my code did not work
(but it works with lexical binding)?

The same thing was true whether I byte-compiled my code or
not, and regardless of which Emacs version I byte-compiled
it in (even Emacs 20!).  And the same thing was true if I
loaded the vanilla source code (mouse.el) first, instead
of its byte-compiled version (mouse.elc).

An explanation of this would be great.  Meanwhile, this
seems like a gotcha.  Just because some function depends
on lexical binding, why should code that calls it also
need to use lexical binding?

----

Here is my code, FWIW.  The only part that differs from the
vanilla code is the handling of a click in the echo area.
And that part is not what misbehaved - it can be ignored here.

AFAIU, nothing in this code should change because of lexical
vs dynamic binding.  What am I missing?

(defun mouse-drag-region (start-event)
  (interactive "e")
  (let ((clickwin  (posn-window (event-start start-event))))
    (if (and (window-minibuffer-p clickwin)
	     (not (minibuffer-window-active-p clickwin)))
	(let* ((Messages-buf (get-buffer-create "*Messages*"))
	       (Messages-win (get-buffer-window Messages-buf
                                               'visible)))
	  (if Messages-win
	      (let ((M-x-cmd  (or (key-binding "\M-x" t)
				    'execute-extended-command)))
		(read-event)
		(if (eq Messages-win (selected-window))
		    (bury-buffer)
		  (delete-window Messages-win))
		(save-window-excursion
		  (call-interactively M-x-cmd nil [(meta ?x)])))
	    (save-excursion
	      (read-event)
	      (set-buffer Messages-buf)
	      (goto-char (point-max))
	      (display-buffer (current-buffer)))))
      (run-hooks 'mouse-leave-buffer-hook)
      (let ((emacs24.4+
	      (or (> emacs-major-version 24)
		  (and (= emacs-major-version 24)
		       (not (version< emacs-version "24.3.50"))))))
	(if emacs24.4+
	    (mouse-drag-track start-event) ; <=========
	  (mouse-drag-track start-event t))))))



             reply	other threads:[~2015-11-21 22:28 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-21 22:28 Drew Adams [this message]
2015-11-22 14:02 ` bitten by lexical-binding Johan Bockgård
2015-11-22 14:12 ` Artur Malabarba
2015-11-22 14:23 ` Andreas Schwab
2015-11-22 14:29   ` David Kastrup
2015-11-22 15:57   ` Drew Adams
2015-11-22 14:28 ` Michael Heerdegen
2015-11-22 17:08   ` Drew Adams

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9b834ee9-4f63-42ca-98b4-c0f14986642e@default \
    --to=drew.adams@oracle.com \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).