Subject: Re: bug#17558: 24.4.50; global-subword-mode breaks ERC

From: Stefan Monnier <[email-masked]>
Date: Thu, 01 Jan 2015 11:42:56 -0500

>> Thanks for the repro. This bug is probably due to my changing how
>> subword-mode works: now, forward-word will stop at subword boundaries,
>> and I'm guessing ERC was relying on the old behavior. I can try to take
>> a look at it if nobody who knows ERC better wants to try first.

Indeed, with the new implementation of subword-mode, most of the
word-operating commands should be marked as "interactive use only",
since their behavior is too unreliable for use in Lisp code.

> -    (upcase-word 1)
> +
> +    ;; If we're in subword-mode then functions operating on words act
> +    ;; differently. Here I temporarily disable subword-mode before
> +    ;; touching the words
> +    (let ((find-word-boundary-function-table
> +           (if (boundp 'subword-empty-char-table)
> +               subword-empty-char-table find-word-boundary-function-table)))
> +      (upcase-word 1))

Yuck.  I suggest you use upcase-region instead (and probably something
like skip-char-forward to find the word's boundaries).

> -      (while (forward-word 1)
> -        (setq bounds (bounds-of-thing-at-point 'word))
> -        (setq word (buffer-substring-no-properties
> -                    (car bounds) (cdr bounds)))
> -        (when (or (and (erc-server-buffer-p) (erc-get-server-user word))
> -                  (and erc-channel-users (erc-get-channel-user word)))
> -          (erc-button-add-button (car bounds) (cdr bounds)
> -                                 fun t (list word)))))))
> +
> +      ;; If we're in subword-mode then functions operating on words
> +      ;; act differently. Here I temporarily disable subword-mode
> +      ;; before touching the words
> +      (let ((find-word-boundary-function-table
> +             (if (boundp 'subword-empty-char-table)
> +                 subword-empty-char-table find-word-boundary-function-table)))
> +        (while (forward-word 1)
> +          (setq bounds (bounds-of-thing-at-point 'word))
> +          (setq word (buffer-substring-no-properties
> +                      (car bounds) (cdr bounds)))
> +          (when (or (and (erc-server-buffer-p) (erc-get-server-user word))
> +                    (and erc-channel-users (erc-get-channel-user word)))
> +            (erc-button-add-button (car bounds) (cdr bounds)
> +                                   fun t (list word))))))))
 
Similarly here, we should use "word" operations at all.
Maybe forward-sexp can be used instead of forward-word, or else
skip-syntax-forward or skip-chars-forward.

The call to (bounds-of-thing-at-point 'word) should be avoided as well
(we already know the end of the bounds is (point) anyway and we can
probably find the other bound at the same time as we skip-chars-forward.

        Stefan