From: Chong Yidong <cyd@stupidchicken.com>
To: emacs-devel@gnu.org
Subject: Shift selection using interactive spec
Date: Thu, 13 Mar 2008 19:29:45 -0400 [thread overview]
Message-ID: <87k5k69p92.fsf@stupidchicken.com> (raw)
Here is a prototype for implementing shift-selection using a new
interactive spec code, `^'. It uses transient-mark-mode's `only'
setting as suggested by Miles and Johan.
I haven't changed all the movement commands, just enough of them to
play around with the shift selection. (left, right, up, down, etc).
Currently, M-F doesn't DTRT, but this appears to be due to an existing
bug (feature?): if there is no mapping for M-F, Emacs 22 translates it
to M-f, while Emacs 23 translates it to f. I haven't tracked down
where this change was made.
A few observations:
Firstly, if we adopt this approach, we have to work around the fact
that read_key_sequence automatically attempts translates unbound key
sequences by trying to shift them (e.g., changing S-right to right).
Here, I create a new global variable
this_command_keys_shift_translated, which is set to 1 by
read_key_sequence when it does this translation. This tells
Fcall_interactively that the activating key sequence is indeed
shifted, regardless of what this_command_keys says.
The present code probably doesn't handle shifting/shifting properly
when Fread_key_sequence is called from Lisp, but that is easily
remedied.
Secondly, there are two C level functions, direct_output_forward_char
and direct_output_forward_char, which are called instead of
forward_char and backward_char if certain conditions are met. This is
a redisplay optimization. To get this to work, we must avoid using
these functions when appropriate. In the present code, I don't call
them when this_command_keys_shift_translated is non-zero, but this may
need more analysis.
Thirdly, I'm not too happy about the variable separation in this code.
Here, callint.c pulls in this_command_keys_shift_translated and
this_single_command_key_start from keyboard.c, Qonly from frame.h,
Qidentity from casefiddle.c, and it needs to call intern ("shift") on
each invokation to get the symbol for `shift'. If we end up going
with this approach, maybe someone could suggest a way to clean up
these variables.
Comments are welcome.
*** trunk/src/callint.c.~1.161.~ 2008-02-21 11:10:47.000000000 -0500
--- trunk/src/callint.c 2008-03-13 18:48:05.000000000 -0400
***************
*** 121,128 ****
If the string begins with `@', then Emacs searches the key sequence
which invoked the command for its first mouse click (or any other
event which specifies a window), and selects that window before
! reading any arguments. You may use both `@' and `*'; they are
! processed in the order that they appear.
usage: (interactive ARGS) */)
(args)
Lisp_Object args;
--- 121,132 ----
If the string begins with `@', then Emacs searches the key sequence
which invoked the command for its first mouse click (or any other
event which specifies a window), and selects that window before
! reading any arguments.
! If the string begins with `^', and the key sequence which invoked the
! command contains the shift modifier, then Emacs activates Transient
! Mark Mode temporarily for this command.
! You may use `@', `*', and `^' together; they are processed in the
! order that they appear.
usage: (interactive ARGS) */)
(args)
Lisp_Object args;
***************
*** 244,249 ****
--- 248,258 ----
}
}
+ extern int this_command_keys_shift_translated;
+ extern int this_single_command_key_start;
+ extern Lisp_Object Qonly;
+ extern Lisp_Object Qidentity;
+
DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 3, 0,
doc: /* Call FUNCTION, reading args according to its interactive calling specs.
Return the value FUNCTION returns.
***************
*** 423,428 ****
--- 432,469 ----
/* Ignore this for semi-compatibility with Lucid. */
else if (*string == '-')
string++;
+ else if (*string == '^')
+ {
+ Lisp_Object *key = XVECTOR (this_command_keys)->contents
+ + this_single_command_key_start;
+ Lisp_Object *key_max = XVECTOR (this_command_keys)->contents
+ + this_command_key_count;
+ Lisp_Object shift = intern ("shift");
+ int shifted = this_command_keys_shift_translated;
+
+ if (!shifted)
+ for (; key < key_max; ++key)
+ {
+ if (SYMBOLP (*key))
+ shifted = !NILP (Fmemq (shift,
+ Fget (*key, Qevent_symbol_elements)));
+ if (!shifted)
+ break;
+ }
+
+ if (shifted)
+ {
+ Lisp_Object push_mark_call[4] = { intern ("push-mark"),
+ Qnil, Qnil, Qt };
+ if (!EQ (Vtransient_mark_mode, Qidentity))
+ Ffuncall (4, push_mark_call);
+ if (EQ (Vtransient_mark_mode, Qidentity)
+ || NILP (Vtransient_mark_mode))
+ Vtransient_mark_mode = Qonly;
+ }
+
+ string++;
+ }
else if (*string == '@')
{
Lisp_Object event, tem;
*** trunk/src/keyboard.c.~1.947.~ 2008-02-25 11:04:08.000000000 -0500
--- trunk/src/keyboard.c 2008-03-13 18:49:38.000000000 -0400
***************
*** 132,137 ****
--- 132,142 ----
Lisp_Object raw_keybuf;
int raw_keybuf_count;
+ /* This is non-zero if the present key sequence was obtained by
+ unshifting a key sequence (i.e. changing an upper-case letter to
+ lower-case or a shifted function key to an unshifted one). */
+ int this_command_keys_shift_translated;
+
#define GROW_RAW_KEYBUF \
if (raw_keybuf_count == XVECTOR (raw_keybuf)->size) \
raw_keybuf = larger_vector (raw_keybuf, raw_keybuf_count * 2, Qnil) \
***************
*** 1648,1653 ****
--- 1653,1659 ----
Vthis_command = Qnil;
real_this_command = Qnil;
Vthis_original_command = Qnil;
+ this_command_keys_shift_translated = 0;
/* Read next key sequence; i gets its length. */
i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
***************
*** 1761,1767 ****
/* Recognize some common commands in common situations and
do them directly. */
! if (EQ (Vthis_command, Qforward_char) && PT < ZV)
{
struct Lisp_Char_Table *dp
= window_display_table (XWINDOW (selected_window));
--- 1767,1774 ----
/* Recognize some common commands in common situations and
do them directly. */
! if (EQ (Vthis_command, Qforward_char) && PT < ZV
! && !this_command_keys_shift_translated)
{
struct Lisp_Char_Table *dp
= window_display_table (XWINDOW (selected_window));
***************
*** 1801,1807 ****
direct_output_forward_char (1);
goto directly_done;
}
! else if (EQ (Vthis_command, Qbackward_char) && PT > BEGV)
{
struct Lisp_Char_Table *dp
= window_display_table (XWINDOW (selected_window));
--- 1808,1815 ----
direct_output_forward_char (1);
goto directly_done;
}
! else if (EQ (Vthis_command, Qbackward_char) && PT > BEGV
! && !this_command_keys_shift_translated)
{
struct Lisp_Char_Table *dp
= window_display_table (XWINDOW (selected_window));
***************
*** 9194,9199 ****
--- 9202,9212 ----
/* Likewise, for key_translation_map and input-decode-map. */
volatile keyremap keytran, indec;
+ /* If we are trying to map a key by unshifting it (i.e. changing an
+ upper-case letter to lower-case or a shifted function key to an
+ unshifted one), then we set this to != 0. */
+ volatile int shift_translated = 0;
+
/* If we receive a `switch-frame' or `select-window' event in the middle of
a key sequence, we put it off for later.
While we're reading, we keep the event here. */
***************
*** 10113,10118 ****
--- 10126,10133 ----
keybuf[t - 1] = new_key;
mock_input = max (t, mock_input);
+ shift_translated = 1;
+
goto replay_sequence;
}
/* If KEY is not defined in any of the keymaps,
***************
*** 10154,10159 ****
--- 10169,10176 ----
fkey.start = fkey.end = 0;
keytran.start = keytran.end = 0;
+ shift_translated = 1;
+
goto replay_sequence;
}
}
***************
*** 10191,10196 ****
--- 10208,10215 ----
}
+ if (shift_translated && read_key_sequence_cmd)
+ this_command_keys_shift_translated = 1;
UNGCPRO;
return t;
*** trunk/src/cmds.c.~1.102.~ 2008-02-01 13:47:24.000000000 -0500
--- trunk/src/cmds.c 2008-03-13 13:36:57.000000000 -0400
***************
*** 56,62 ****
return make_number (PT + XINT (n));
}
! DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "p",
doc: /* Move point right N characters (left if N is negative).
On reaching end of buffer, stop and signal error. */)
(n)
--- 56,62 ----
return make_number (PT + XINT (n));
}
! DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "^p",
doc: /* Move point right N characters (left if N is negative).
On reaching end of buffer, stop and signal error. */)
(n)
***************
*** 92,98 ****
return Qnil;
}
! DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 1, "p",
doc: /* Move point left N characters (right if N is negative).
On attempt to pass beginning or end of buffer, stop and signal error. */)
(n)
--- 92,98 ----
return Qnil;
}
! DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 1, "^p",
doc: /* Move point left N characters (right if N is negative).
On attempt to pass beginning or end of buffer, stop and signal error. */)
(n)
*** trunk/lisp/simple.el.~1.905.~ 2008-03-10 21:57:09.000000000 -0400
--- trunk/lisp/simple.el 2008-03-13 13:39:17.000000000 -0400
***************
*** 3651,3657 ****
If you are thinking of using this in a Lisp program, consider
using `forward-line' instead. It is usually easier to use
and more reliable (no dependence on goal column, etc.)."
! (interactive "p\np")
(or arg (setq arg 1))
(if (and next-line-add-newlines (= arg 1))
(if (save-excursion (end-of-line) (eobp))
--- 3651,3657 ----
If you are thinking of using this in a Lisp program, consider
using `forward-line' instead. It is usually easier to use
and more reliable (no dependence on goal column, etc.)."
! (interactive "^p\np")
(or arg (setq arg 1))
(if (and next-line-add-newlines (= arg 1))
(if (save-excursion (end-of-line) (eobp))
***************
*** 3684,3690 ****
If you are thinking of using this in a Lisp program, consider using
`forward-line' with a negative argument instead. It is usually easier
to use and more reliable (no dependence on goal column, etc.)."
! (interactive "p\np")
(or arg (setq arg 1))
(if (interactive-p)
(condition-case nil
--- 3684,3690 ----
If you are thinking of using this in a Lisp program, consider using
`forward-line' with a negative argument instead. It is usually easier
to use and more reliable (no dependence on goal column, etc.)."
! (interactive "^p\np")
(or arg (setq arg 1))
(if (interactive-p)
(condition-case nil
***************
*** 4307,4313 ****
(defun backward-word (&optional arg)
"Move backward until encountering the beginning of a word.
With argument, do this that many times."
! (interactive "p")
(forward-word (- (or arg 1))))
(defun mark-word (&optional arg allow-extend)
--- 4307,4313 ----
(defun backward-word (&optional arg)
"Move backward until encountering the beginning of a word.
With argument, do this that many times."
! (interactive "^p")
(forward-word (- (or arg 1))))
(defun mark-word (&optional arg allow-extend)
next reply other threads:[~2008-03-13 23:29 UTC|newest]
Thread overview: 167+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-03-13 23:29 Chong Yidong [this message]
2008-03-14 0:44 ` Shift selection using interactive spec Thomas Lord
2008-03-14 0:10 ` David Kastrup
2008-03-14 1:22 ` Thomas Lord
2008-03-14 9:46 ` David Kastrup
2008-03-14 10:01 ` Johan Bockgård
2008-03-14 10:30 ` David Kastrup
2008-03-14 11:18 ` Thomas Lord
2008-03-14 11:11 ` Thomas Lord
2008-03-14 10:42 ` David Kastrup
2008-03-14 11:36 ` Thomas Lord
2008-03-14 11:50 ` Thomas Lord
2008-03-14 11:39 ` David Kastrup
2008-03-14 18:41 ` Thomas Lord
2008-03-14 4:06 ` Dan Nicolaescu
2008-03-14 14:26 ` Kim F. Storm
2008-03-14 14:32 ` Chong Yidong
2008-03-14 14:53 ` Kim F. Storm
2008-03-14 16:19 ` David Kastrup
2008-03-14 15:54 ` Stefan Monnier
2008-03-14 16:09 ` Drew Adams
2008-03-14 20:52 ` Chong Yidong
2008-03-14 20:59 ` David Kastrup
2008-03-14 21:08 ` Chong Yidong
2008-03-15 0:56 ` Stefan Monnier
2008-03-15 2:02 ` Chong Yidong
2008-03-15 3:31 ` Stefan Monnier
2008-03-15 14:07 ` Chong Yidong
2008-03-15 15:07 ` Stefan Monnier
2008-03-15 17:11 ` Chong Yidong
2008-03-15 20:52 ` Stefan Monnier
2008-03-15 21:45 ` Thomas Lord
2008-03-16 14:15 ` Chong Yidong
2008-03-16 14:37 ` Lennart Borgman (gmail)
2008-03-15 22:01 ` shift-select harmony Thomas Lord
2008-03-15 23:38 ` Thomas Lord
2008-03-15 17:16 ` Shift selection using interactive spec Kim F. Storm
2008-03-15 20:59 ` Thomas Lord
2008-03-16 23:31 ` Alan Mackenzie
2008-03-15 21:08 ` Thomas Lord
2008-03-16 0:27 ` Chong Yidong
2008-03-16 1:37 ` Thomas Lord
2008-03-16 9:09 ` Mathias Dahl
2008-03-16 14:21 ` Chong Yidong
2008-03-16 16:56 ` Thomas Lord
2008-03-16 16:34 ` Dear lazyweb (Re: Shift selection using interactive spec) Thomas Lord
2008-03-16 18:40 ` Shift selection using interactive spec Stefan Monnier
2008-03-16 21:00 ` Thomas Lord
2008-03-16 20:45 ` Thien-Thi Nguyen
2008-03-16 21:46 ` Thomas Lord
2008-03-16 21:24 ` Thien-Thi Nguyen
2008-03-16 22:27 ` Thomas Lord
2008-03-16 23:04 ` Lennart Borgman (gmail)
2008-03-16 23:17 ` Lennart Borgman (gmail)
2008-03-17 0:46 ` Thomas Lord
2008-03-17 0:21 ` Lennart Borgman (gmail)
2008-03-17 1:16 ` Thomas Lord
2008-03-16 23:35 ` Stephen J. Turnbull
2008-03-17 0:55 ` Thomas Lord
2008-03-17 2:23 ` Stefan Monnier
2008-03-17 3:12 ` Thomas Lord
2008-03-17 2:21 ` Stefan Monnier
2008-03-17 3:47 ` what's the point (re shift selection) Thomas Lord
2008-03-16 14:40 ` Shift selection using interactive spec Chong Yidong
2008-03-16 15:04 ` Lennart Borgman (gmail)
2008-03-16 17:13 ` Thomas Lord
2008-03-17 0:54 ` Chong Yidong
2008-03-17 2:40 ` Stefan Monnier
2008-03-17 3:24 ` Chong Yidong
2008-03-17 13:26 ` Stefan Monnier
2008-03-17 16:33 ` Chong Yidong
2008-03-17 17:21 ` Lennart Borgman (gmail)
2008-03-17 19:11 ` Stefan Monnier
2008-03-17 21:10 ` Chong Yidong
2008-03-17 21:44 ` Drew Adams
2008-03-18 11:40 ` Kim F. Storm
2008-03-18 14:16 ` Chong Yidong
2008-03-18 15:07 ` Kim F. Storm
2008-03-18 16:24 ` Stefan Monnier
2008-03-18 17:54 ` Drew Adams
2008-03-20 5:03 ` Chong Yidong
2008-03-23 1:39 ` Stefan Monnier
2008-03-17 22:24 ` martin rudalics
2008-03-17 22:37 ` Lennart Borgman (gmail)
2008-03-18 0:50 ` Thomas Lord
2008-03-18 7:48 ` martin rudalics
2008-03-18 17:46 ` Thomas Lord
2008-03-18 17:36 ` Lennart Borgman (gmail)
2008-03-18 19:07 ` Thomas Lord
2008-03-18 7:48 ` martin rudalics
2008-03-17 22:53 ` Chong Yidong
2008-03-18 3:12 ` Stefan Monnier
2008-03-18 7:49 ` martin rudalics
2008-03-18 16:36 ` Stefan Monnier
2008-03-18 16:44 ` Lennart Borgman (gmail)
2008-03-18 14:45 ` Chong Yidong
2008-03-18 16:39 ` Stefan Monnier
2008-03-18 18:28 ` Chong Yidong
2008-03-18 21:42 ` Stefan Monnier
2008-03-18 22:30 ` Kim F. Storm
2008-03-18 22:39 ` Lennart Borgman (gmail)
2008-03-19 4:40 ` M Jared Finder
2008-03-26 8:09 ` David Kastrup
2008-03-26 10:48 ` Juri Linkov
2008-03-26 11:32 ` David Kastrup
2008-03-26 11:39 ` Juri Linkov
2008-03-26 12:20 ` David Kastrup
2008-03-26 13:14 ` Johan Bockgård
2008-03-26 13:26 ` David Kastrup
2008-03-26 14:52 ` Stefan Monnier
2008-03-27 0:46 ` Juri Linkov
2008-03-26 12:02 ` Lennart Borgman (gmail)
2008-03-26 11:47 ` Lennart Borgman (gmail)
2008-03-26 22:26 ` Richard Stallman
2008-03-26 23:31 ` Lennart Borgman (gmail)
2008-03-27 7:02 ` David Kastrup
2008-03-27 8:19 ` Lennart Borgman (gmail)
2008-03-27 8:41 ` David Kastrup
2008-03-27 13:57 ` Lennart Borgman (gmail)
2008-03-27 14:39 ` David Kastrup
2008-03-27 15:01 ` Juanma Barranquero
2008-03-27 15:34 ` David Kastrup
2008-03-27 15:41 ` Juanma Barranquero
2008-03-27 15:13 ` Johan Bockgård
2008-03-27 19:41 ` Richard Stallman
2008-03-27 23:52 ` Juri Linkov
2008-03-28 7:33 ` David Kastrup
2008-03-29 0:47 ` Juri Linkov
2008-03-29 7:03 ` David Kastrup
2008-03-29 11:53 ` Lennart Borgman (gmail)
2008-03-29 12:30 ` Juri Linkov
2008-03-29 14:07 ` David Kastrup
2008-03-29 14:45 ` Lennart Borgman (gmail)
2008-03-29 15:09 ` David Kastrup
2008-03-29 15:30 ` Lennart Borgman (gmail)
2008-03-30 0:52 ` Juri Linkov
2008-03-30 17:56 ` David Kastrup
2008-03-30 5:49 ` Richard Stallman
2008-03-28 4:05 ` M Jared Finder
2008-03-28 11:10 ` David Kastrup
2008-03-28 17:14 ` Lennart Borgman (gmail)
2008-03-28 20:05 ` David Kastrup
2008-03-28 23:49 ` Lennart Borgman (gmail)
2008-03-28 20:42 ` Richard Stallman
2008-03-28 21:47 ` Chong Yidong
2008-03-28 22:01 ` David Kastrup
2008-03-30 0:48 ` Juri Linkov
2008-03-30 17:55 ` David Kastrup
2008-03-30 18:55 ` Juri Linkov
2008-03-27 0:49 ` Juri Linkov
2008-03-27 2:59 ` Chong Yidong
2008-03-27 19:41 ` Richard Stallman
2008-03-27 23:48 ` Juri Linkov
2008-03-28 20:41 ` Richard Stallman
2008-03-29 0:54 ` Juri Linkov
2008-03-29 1:15 ` Lennart Borgman (gmail)
2008-03-29 16:37 ` Richard Stallman
2008-03-30 1:05 ` Juri Linkov
2008-03-30 4:12 ` Stefan Monnier
2008-03-30 18:33 ` Juri Linkov
2008-03-31 16:24 ` Richard Stallman
2008-03-30 19:56 ` Richard Stallman
2008-03-30 22:46 ` Juri Linkov
2008-03-26 22:26 ` Richard Stallman
2008-03-18 17:45 ` Thomas Lord
2008-03-16 2:33 ` Richard Stallman
-- strict thread matches above, loose matches on Subject: below --
2008-03-16 12:58 Robert J. Chassell
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=87k5k69p92.fsf@stupidchicken.com \
--to=cyd@stupidchicken.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 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.