help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: change "word" definition (syntax table) for double-click?


From: Drew Adams
Subject: RE: change "word" definition (syntax table) for double-click?
Date: Mon, 1 Dec 2008 10:29:53 -0800

> What I want is for double-clicking with the mouse to highlight,
> as a word, all contiguous non-whitespace characters.

By "highlight", I think you mean "select", as in setting the active region to
that text.

> Some sample applications I want this for are:
> o   Double-clicking in the middle of URLs.
> o   Double-clicking in the middle of RFC822-compliant email addresses.
> o   Double-clicking in the middle of passwords and other strings
>     having non-alphanumeric characters.

Easy solution: `M-x goto-address'. That will put links on URLs and email
addresses, which you can then click (single-click) with mouse-2 (and mouse-1, if
`mouse-1-click-follows-link' is non-nil). See the Emacs manual, node
Hyperlinking, and its subnodes.

If you don't like that for some reason, and you really want to change
double-clicking mouse-2 so that it selects such things, then read on.

Emacs already does that too, at least for many URLs etc. and at least in some
modes, such as Emacs-Lisp mode. That is, provided you double-click (with
mouse-2) on a symbol-constituent character, such as :/.?=@. If you instead
double-click a word-constituent character, then just that word is selected.

For example, in Emacs-Lisp mode, if you double-click the URL
http://www.emacswiki.org/emacs/SiteMap at the : or a / or a ., then the whole
URL is selected. And in the email address help-gnu-emacs@gnu.org, if you
double-click a - or the @ or the ., then the whole address is selected.

However, if you double-click the ; in this URL, then only the ; itself is
selected:
http://www.emacswiki.org/cgi-bin/wiki?action=rc;days=7;all=0;rollback=1;showedit
=1.
The ;'s divide the URL into sections that you can double-click. The reason for
this is that in Emacs-Lisp mode a ; has the syntax of a comment-starter.

In other modes things are different. In text mode, for instance, a double-click
gets you much less text, because of how words and symbols are defined in text
mode.

Know too that you can use mouse-3 (right button) to extend a selection:
double-click, then right-click farther to the right. That can be pretty quick,
to pick up a URL or address.

None of that answers your question completely, but it is good to know.

For a more general answer, the code to look at for inspiration is in standard
library mouse.el. Function `mouse-skip-word' is used to select a range of text
when you double-click. You could try advising or redefining that function to get
the behavior you want. Here is `mouse-skip-word' (it is the same, from Emacs 20
through Emacs 23, at least):

(defun mouse-skip-word (dir)
  "Skip over word, over whitespace, or over identical punctuation.
If DIR is positive skip forward; if negative, skip backward."
  (let* ((char (following-char))
         (syntax (char-to-string (char-syntax char))))
    (cond ((string= syntax "w")
           ;; Here, we can't use skip-syntax-forward/backward because
           ;; they don't pay attention to word-separating-categories,
           ;; and thus they will skip over a true word boundary.  So,
           ;; we simulate the original behavior by using forward-word.
           (if (< dir 0)
               (if (not (looking-at "\\<"))
                   (forward-word -1))
             (if (or (looking-at "\\<") (not (looking-at "\\>")))
                 (forward-word 1))))
          ((string= syntax " ")
           (if (< dir 0)
               (skip-syntax-backward syntax)
             (skip-syntax-forward syntax)))
          ((string= syntax "_")
           (if (< dir 0)
               (skip-syntax-backward "w_")
             (skip-syntax-forward "w_")))
          ((< dir 0)
           (while (and (not (bobp)) (= (preceding-char) char))
             (forward-char -1)))
          (t
           (while (and (not (eobp)) (= (following-char) char))
             (forward-char 1))))))

It checks the syntax class of the character you click, then extends the region
according to that class. The first `cond' clause deals with word-constituent
characters. The second clause treats whitespace chars. The third treats
symbol-constituent chars, such as - and _.

A quick semi-solution is to change the first clause to something like this:

((or (string= syntax "w") (string= syntax "_"))
     (if (< dir 0)
         (skip-syntax-backward "w_")
       (skip-syntax-forward "w_")))

That just treats word-constituent and symbol-constituent characters the same
way. It still won't treat the ; in the second URL above the way you want. To
include ; in Emacs-Lisp mode, you could add (string= syntax "<") to the `or', to
include comment-starter constituents.

I'm not recommending that you do any of this, mind you; I'm just explaining a
bit.

And again, the behavior depends on the mode, because different modes give
different characters different syntax classes.

> In short, I want the same double-clicking control inside emacs that
> character classes give me inside xterm and cutchars give me inside
> rxvt.
>     xterm(1)
>     CHARACTER CLASSES
>     Clicking  the  left  pointer  button  twice   in   rapid
>     succession  (double-clicking)  causes  all characters of
>     the same class (e.g., letters, white space, punctuation)
>     to  be  selected  as  a ``word''. Since different people
>     have different preferences for what should  be  selected
>     (for example, should filenames be selected as a whole or
>     only the separate subnames),  the default mapping can be
>     overridden  through  the  use  of  the  charClass (class
>     CharClass) resource.

That seems to suggest that you want word constituents, whitespace chars, and
punctuation constituents to act the same. That would mean something like this in
the first clause:

((or (string= syntax "w") (string= syntax " ") (string= syntax "."))

But again, it won't work to double-click the ; in a URL, in Emacs-Lisp mode.

Anyway, you get the idea. You can define the syntax classes that you want
double-clicking to work with.

Another approach is to look at code that recognizes URLs and such, and then
adapt that for use with the mouse. Places to start for that are libraries
ffap.el, browse-url.el, and goto-address.el (the libraries that Emacs manual
node Hyperlinking deals with).

These roll-your-own approaches can be messy, and they're a whole lot more work
than simply using `goto-address', which recognizes just what you want, in all
modes.

HTH





reply via email to

[Prev in Thread] Current Thread [Next in Thread]