all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: David Kastrup <dak@gnu.org>
Cc: emacs-devel@gnu.org
Subject: Re: local keymap patch for key-binding
Date: Sun, 10 Sep 2006 15:25:51 +0200	[thread overview]
Message-ID: <85pse3n99c.fsf@lola.goethe.zz> (raw)
In-Reply-To: <87zmd7yjq4.fsf@furball.mit.edu> (Chong Yidong's message of "Sun\, 10 Sep 2006 08\:44\:19 -0400")

Chong Yidong <cyd@stupidchicken.com> writes:

> David Kastrup <dak@gnu.org> writes:
>
>> It does too little.  Check out what read-key-sequence (defined in
>> keyboard.c) does with regard to mouse events (EVENT_HAS_PARAMETERS).
>> The problem is that read-key-sequence does such a load of other stuff
>> that it is hard to extract the material and transfer it to
>> key-binding.
>>
>> The problem is that keymaps may be provided by text properties and
>> overlays, and by keymap properties on strings that display as the
>> display or before-string or after-string properties of text properties
>> or overlays.
>
> I just verified that my patch truly works for keymaps on display
> strings, text properties, and overlays.  For example, with
>
> (with-output-to-temp-buffer "Testo"
>   (set-buffer "Testo")
>   (erase-buffer)
>   (let* ((map (make-sparse-keymap))
> 	 (str (propertize "foostring" 'keymap map 'mouse-face 'highlight))
> 	 ovr)
>     (define-key map [mouse-1] 'delete-window)
>     (insert "1234567890")
>     (setq ovr (make-overlay 2 3))
>     (overlay-put ovr 'keymap map)
>     (overlay-put ovr 'mouse-face 'highlight)
>     (put-text-property 5 6 'display str)
>     (put-text-property 8 9 'keymap map)
>     (put-text-property 8 9 'mouse-face 'highlight)))
>
> C-h k followed by mouse-1 on the overlay, display string, or text
> propertized region all report the correct action for the given local
> keymap.

Uh, C-h k has extra code doing this sort of lookup.  It does not rely
on key-binding.  So you should not test this with C-h k unless you
have previously dumbed it down with
(defun string-key-binding (&rest ignore) nil)
after help.el has been loaded.

> The reason is that the mouse event passed to `key-binding' contains
> all the information you need to reconstruct the binding directly
> (including whether or not the object we are looking at is a buffer
> position or a string.)
>
> So it seems like there's no problem.

Amazing.  Do you have an idea why the stuff in read-key-sequence
concerning mouse related maps appears so much more complicated?  Or is
it just me?  Some complication, of course, is due to read-key-sequence
having to _assemble_ a key sequence instead of merely looking it up.
But still...

Concretely, we have the following in keyboard.c concerning mouse
events, and I'll add my own comments with // in between.

      if (EVENT_HAS_PARAMETERS (key))
	{
	  Lisp_Object kind;
	  Lisp_Object string;

	  kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
	  if (EQ (kind, Qmouse_click))
	    {
	      Lisp_Object window, posn;

	      window = POSN_WINDOW      (EVENT_START (key));
	      posn   = POSN_POSN (EVENT_START (key));

// Fake prefixes probably not relevant for keybinding-lookup
	      if (CONSP (posn)
		  || (!NILP (fake_prefixed_keys)
		      && !NILP (Fmemq (key, fake_prefixed_keys))))
		{
// elided
		}

	      /* Key sequences beginning with mouse clicks are
		 read using the keymaps in the buffer clicked on,
		 not the current buffer.  If we're at the
		 beginning of a key sequence, switch buffers.  */

// Do you change the buffer accordingly in your patch?

	      if (last_real_key_start == 0
		  && WINDOWP (window)
		  && BUFFERP (XWINDOW (window)->buffer)
		  && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
		{
		  XVECTOR (raw_keybuf)->contents[raw_keybuf_count++] = key;
		  keybuf[t] = key;
		  mock_input = t + 1;

		  /* Arrange to go back to the original buffer once we're
		     done reading the key sequence.  Note that we can't
		     use save_excursion_{save,restore} here, because they
		     save point as well as the current buffer; we don't
		     want to save point, because redisplay may change it,
		     to accommodate a Fset_window_start or something.  We
		     don't want to do this at the top of the function,
		     because we may get input from a subprocess which
		     wants to change the selected window and stuff (say,
		     emacsclient).  */
		  record_unwind_protect (Fset_buffer, Fcurrent_buffer ());

		  if (! FRAME_LIVE_P (XFRAME (selected_frame)))
		    Fkill_emacs (Qnil);
		  set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
		  orig_local_map = get_local_map (PT, current_buffer,
						  Qlocal_map);
		  orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
		  goto replay_sequence;

// This starts the whole lookup sequence with new values for local-map
// and, well, I don't quite understand what Qkeymap is.
		}

	      /* For a mouse click, get the local text-property keymap
		 of the place clicked on, rather than point.  */
	      if (last_real_key_start == 0
		  && CONSP (XCDR (key))
		  && ! localized_local_map)
		{
		  Lisp_Object map_here, start, pos;

		  localized_local_map = 1;
		  start = EVENT_START (key);

		  if (CONSP (start) && POSN_INBUFFER_P (start))
		    {
		      pos = POSN_BUFFER_POSN (start);
		      if (INTEGERP (pos)
			  && XINT (pos) >= BEG && XINT (pos) <= Z)
			{
			  map_here = get_local_map (XINT (pos),
						    current_buffer, Qlocal_map);
			  if (!EQ (map_here, orig_local_map))
			    {
			      orig_local_map = map_here;
			      keybuf[t] = key;
			      mock_input = t + 1;

			      goto replay_sequence;
			    }
			  map_here = get_local_map (XINT (pos),
						     current_buffer, Qkeymap);
			  if (!EQ (map_here, orig_keymap))
			    {
			      orig_keymap = map_here;
			      keybuf[t] = key;
			      mock_input = t + 1;

			      goto replay_sequence;
			    }
			}
		    }
		}

// Another class of events: but they mostly don't require looking in
// other maps

	      /* Expand mode-line and scroll-bar events into two events:
		 use posn as a fake prefix key.  */
	      if (SYMBOLP (posn)
		  && (NILP (fake_prefixed_keys)
		      || NILP (Fmemq (key, fake_prefixed_keys))))
		{
		  if (t + 1 >= bufsize)
		    error ("Key sequence too long");

		  keybuf[t]     = posn;
		  keybuf[t + 1] = key;
		  mock_input    = t + 2;

		  /* Record that a fake prefix key has been generated
		     for KEY.  Don't modify the event; this would
		     prevent proper action when the event is pushed
		     back into unread-command-events.  */
		  fake_prefixed_keys = Fcons (key, fake_prefixed_keys);

// Except in the following case:

		  /* If on a mode line string with a local keymap,
		     reconsider the key sequence with that keymap.  */
		  if (string = POSN_STRING (EVENT_START (key)),
		      (CONSP (string) && STRINGP (XCAR (string))))
		    {
		      Lisp_Object pos, map, map2;

		      pos = XCDR (string);
		      string = XCAR (string);
                      if (XINT (pos) >= 0
			  && XINT (pos) < SCHARS (string))
                        {
                          map = Fget_text_property (pos, Qlocal_map, string);
                          if (!NILP (map))
                            orig_local_map = map;
                          map2 = Fget_text_property (pos, Qkeymap, string);
                          if (!NILP (map2))
                            orig_keymap = map2;
                          if (!NILP (map) || !NILP (map2))
                            goto replay_sequence;
                        }
		    }

		  goto replay_key;
		}
	      else if (NILP (from_string)
		       && (string = POSN_STRING (EVENT_START (key)),
			   (CONSP (string) && STRINGP (XCAR (string)))))
		{
		  /* For a click on a string, i.e. overlay string or a
		     string displayed via the `display' property,
		     consider `local-map' and `keymap' properties of
		     that string.  */
		  Lisp_Object pos, map, map2;

		  pos = XCDR (string);
		  string = XCAR (string);
		  if (XINT (pos) >= 0
		      && XINT (pos) < SCHARS (string))
		    {
		      map = Fget_text_property (pos, Qlocal_map, string);
		      if (!NILP (map))
			orig_local_map = map;
		      map2 = Fget_text_property (pos, Qkeymap, string);
		      if (!NILP (map2))
			orig_keymap = map2;

		      if (!NILP (map) || !NILP (map2))
			{
			  from_string = string;
			  goto replay_sequence;
			}
		    }
		}
	    }

// Menu bar: seemingly does not require other maps.

	  else if (CONSP (XCDR (key))
		   && CONSP (EVENT_START (key))
		   && CONSP (XCDR (EVENT_START (key))))
	    {
	      Lisp_Object posn;

	      posn = POSN_POSN (EVENT_START (key));
	      /* Handle menu-bar events:
		 insert the dummy prefix event `menu-bar'.  */
	      if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar))
		{
		  if (t + 1 >= bufsize)
		    error ("Key sequence too long");
		  keybuf[t] = posn;
		  keybuf[t+1] = key;

		  /* Zap the position in key, so we know that we've
		     expanded it, and don't try to do so again.  */
		  POSN_SET_POSN (EVENT_START (key),
				 Fcons (posn, Qnil));

		  mock_input = t + 2;
		  goto replay_sequence;
		}
	      else if (CONSP (posn))
		{
		  /* We're looking at the second event of a
		     sequence which we expanded before.  Set
		     last_real_key_start appropriately.  */
		  if (last_real_key_start == t && t > 0)
		    last_real_key_start = t - 1;
		}
	    }
	}


If it seems to you that your patch gets the same cases (and with the
same order of priorities), that would be great!

Another thing: I had proposed an additional optional "LOCATION"
argument for key-binding.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

  reply	other threads:[~2006-09-10 13:25 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-02-10  9:34 longlines-mode doesn't seem to work with some non-english text Miles Bader
2006-02-11  4:35 ` Chong Yidong
2006-02-13  0:32   ` Kevin Ryde
2006-09-09 15:08 ` local keymap patch for key-binding Chong Yidong
2006-09-09 15:15   ` David Kastrup
2006-09-09 15:26     ` Chong Yidong
2006-09-10 12:44     ` Chong Yidong
2006-09-10 13:25       ` David Kastrup [this message]
2006-09-11  2:36         ` Chong Yidong
2006-09-11  6:25           ` David Kastrup
2006-09-11  7:05           ` David Kastrup
2006-09-11  8:52             ` Kim F. Storm
2006-09-11  9:48               ` David Kastrup
2006-09-11 10:11                 ` David Kastrup
2006-09-11 12:53                   ` Kim F. Storm
2006-09-11 13:04                     ` David Kastrup
2006-09-11 13:07                   ` Chong Yidong
2006-09-11 19:58                 ` Richard Stallman
2006-09-12 10:04                   ` David Kastrup
2006-09-12 15:21                     ` David Kastrup
2006-09-12 15:39                       ` PCL-CVS's diff and marks (was: local keymap patch for key-binding) Stefan Monnier
2006-09-12 15:42                         ` PCL-CVS's diff and marks David Kastrup
2006-09-12 15:54                           ` Stefan Monnier
2006-09-12 21:45                       ` local keymap patch for key-binding Richard Stallman
2006-09-12 22:23                         ` David Kastrup
2006-09-12 23:44                           ` David Kastrup
2006-09-13  7:45                             ` Kim F. Storm
2006-09-13  8:11                               ` David Kastrup
2006-09-13 11:05                                 ` Kim F. Storm
2006-09-13 11:38                                   ` David Kastrup
2006-09-13 12:23                                     ` Kim F. Storm
2006-09-13 12:32                                       ` David Kastrup
2006-09-13 13:45                                         ` Kim F. Storm
2006-09-13 19:25                                     ` Richard Stallman
2006-09-13 19:49                                       ` David Kastrup
2006-09-13 19:25                                 ` Richard Stallman
2006-09-13 20:02                                   ` David Kastrup
2006-09-13 19:24                           ` Richard Stallman
2006-09-13 15:10                       ` Richard Stallman
2006-09-13 15:25                         ` David Kastrup
2006-09-14  2:34                           ` Richard Stallman
2006-09-14 11:57                             ` David Kastrup
2006-09-14 22:34                               ` David Kastrup
2006-09-14 22:36                                 ` David Kastrup
2006-09-15  3:14                               ` Richard Stallman
2006-09-15  8:20                                 ` David Kastrup
2006-09-15 23:47                               ` David Kastrup
2006-09-16  0:14                                 ` Kim F. Storm
2006-09-16 19:05                                   ` Richard Stallman
2006-09-18 15:43                                     ` David Kastrup
2006-09-18 20:34                                       ` Kim F. Storm
2006-09-18 23:39                                       ` Richard Stallman
2006-09-16 16:41                                 ` Stefan Monnier
2006-09-10 18:52       ` Richard Stallman
2006-09-11  2:39         ` Chong Yidong

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

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

  git send-email \
    --in-reply-to=85pse3n99c.fsf@lola.goethe.zz \
    --to=dak@gnu.org \
    --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 external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.