Merge capitalized-words-mode and subword-mode

This commit is contained in:
Daniel Colascione 2014-03-23 00:36:26 -07:00
parent 10e00bd5b4
commit 6ddc44225e
5 changed files with 125 additions and 152 deletions

View file

@ -1,3 +1,24 @@
2014-03-23 Daniel Colascione <dancol@dancol.org>
Change subword-mode to use `find-word-boundary-function-table' and
replace `capitalized-words-mode'. Also, convert to lexical
binding.
* progmodes/cap-words.el: Delete now-obsolete file.
* progmodes/subword.el: Reimplement using
`find-word-boundary-function-table'.
(subword-mode-map): Hollow out.
(capitalized-words-mode): Define as obsolete alias for
`subword-mode'.
(subword-mode,superword-mode): Tweak documentation to reflect new
implementation; call `subword-setup-buffer'.
(subword-forward,subword-capitalize): Add underscore to indicate
unused variable.
(subword-find-word-boundary-function-table): New constant.
(subword-empty-char-table): New constant.
(subword-setup-buffer): New function.
(subword-find-word-boundary): New function.
2014-03-23 Daniel Colascione <dancol@dancol.org>
* emacs-lisp/cl-macs.el (cl--do-arglist): Use a little `cl-loop'

View file

@ -1,98 +0,0 @@
;;; cap-words.el --- minor mode for motion in CapitalizedWordIdentifiers
;; Copyright (C) 2002-2014 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Keywords: languages
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Provides Capitalized Words minor mode for word movement in
;; identifiers CapitalizedLikeThis.
;; Note that the same effect could be obtained by frobbing the
;; category of upper case characters to produce word boundaries, but
;; the necessary processing isn't done for ASCII characters.
;; Fixme: This doesn't work properly for mouse double clicks.
;;; Code:
(defun capitalized-find-word-boundary (pos limit)
"Function for use in `find-word-boundary-function-table'.
Looks for word boundaries before capitals."
(save-excursion
(goto-char pos)
(let (case-fold-search)
(if (<= pos limit)
;; Fixme: Are these regexps the best?
(or (and (re-search-forward "\\=.\\w*[[:upper:]]"
limit t)
(progn (backward-char)
t))
(re-search-forward "\\>" limit t))
(or (re-search-backward "[[:upper:]]\\w*\\=" limit t)
(re-search-backward "\\<" limit t))))
(point)))
(defconst capitalized-find-word-boundary-function-table
(let ((tab (make-char-table nil)))
(set-char-table-range tab t #'capitalized-find-word-boundary)
tab)
"Assigned to `find-word-boundary-function-table' in Capitalized Words mode.")
;;;###autoload
(define-minor-mode capitalized-words-mode
"Toggle Capitalized Words mode.
With a prefix argument ARG, enable Capitalized Words mode if ARG
is positive, and disable it otherwise. If called from Lisp,
enable the mode if ARG is omitted or nil.
Capitalized Words mode is a buffer-local minor mode. When
enabled, a word boundary occurs immediately before an uppercase
letter in a symbol. This is in addition to all the normal
boundaries given by the syntax and category tables. There is no
restriction to ASCII.
E.g. the beginning of words in the following identifier are as marked:
capitalizedWorDD
^ ^ ^^
Note that these word boundaries only apply for word motion and
marking commands such as \\[forward-word]. This mode does not affect word
boundaries found by regexp matching (`\\>', `\\w' &c).
This style of identifiers is common in environments like Java ones,
where underscores aren't trendy enough. Capitalization rules are
sometimes part of the language, e.g. Haskell, which may thus encourage
such a style. It is appropriate to add `capitalized-words-mode' to
the mode hook for programming language modes in which you encounter
variables like this, e.g. `java-mode-hook'. It's unlikely to cause
trouble if such identifiers aren't used.
See also `glasses-mode' and `studlify-word'.
Obsoletes `c-forward-into-nomenclature'."
nil " Caps" nil :group 'programming
(set (make-local-variable 'find-word-boundary-function-table)
capitalized-find-word-boundary-function-table))
(provide 'cap-words)
;;; cap-words.el ends here

View file

@ -1,4 +1,4 @@
;;; subword.el --- Handling capitalized subwords in a nomenclature
;;; subword.el --- Handling capitalized subwords in a nomenclature -*- lexical-binding: t -*-
;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
@ -21,13 +21,10 @@
;;; Commentary:
;; This package was cc-submode.el before it was recognized being
;; useful in general and not tied to C and c-mode at all.
;; This package provides `subword' oriented commands and a minor mode
;; (`subword-mode') that substitutes the common word handling
;; functions with them. It also provides the `superword-mode' minor
;; mode that treats symbols as words, the opposite of `subword-mode'.
;; This package provides the `subword' minor mode, which merges the
;; old remap-based subword.el (derived from cc-mode code) and
;; cap-words.el, which takes advantage of core Emacs
;; word-motion-customization functionality.
;; In spite of GNU Coding Standards, it is popular to name a symbol by
;; mixing uppercase and lowercase letters, e.g. "GtkWidget",
@ -47,25 +44,6 @@
;; words. You also get a mode to treat symbols as words instead,
;; called `superword-mode' (the opposite of `subword-mode').
;; In the minor mode, all common key bindings for word oriented
;; commands are overridden by the subword oriented commands:
;; Key Word oriented command Subword oriented command (also superword)
;; ============================================================
;; M-f `forward-word' `subword-forward'
;; M-b `backward-word' `subword-backward'
;; M-@ `mark-word' `subword-mark'
;; M-d `kill-word' `subword-kill'
;; M-DEL `backward-kill-word' `subword-backward-kill'
;; M-t `transpose-words' `subword-transpose'
;; M-c `capitalize-word' `subword-capitalize'
;; M-u `upcase-word' `subword-upcase'
;; M-l `downcase-word' `subword-downcase'
;;
;; Note: If you have changed the key bindings for the word oriented
;; commands in your .emacs or a similar place, the keys you've changed
;; to are also used for the corresponding subword oriented commands.
;; To make the mode turn on automatically, put the following code in
;; your .emacs:
;;
@ -102,18 +80,16 @@
"Regexp used by `subword-backward-internal'.")
(defvar subword-mode-map
(let ((map (make-sparse-keymap)))
(dolist (cmd '(forward-word backward-word mark-word kill-word
backward-kill-word transpose-words
capitalize-word upcase-word downcase-word
left-word right-word))
(let ((othercmd (let ((name (symbol-name cmd)))
(string-match "\\([[:alpha:]-]+\\)-word[s]?" name)
(intern (concat "subword-" (match-string 1 name))))))
(define-key map (vector 'remap cmd) othercmd)))
map)
;; We originally remapped motion keys here, but now use Emacs core
;; hooks. Leave this keymap around so that user additions to it
;; keep working.
(make-sparse-keymap)
"Keymap used in `subword-mode' minor mode.")
;;;###autoload
(define-obsolete-function-alias
'capitalized-words-mode 'subword-mode "24.5")
;;;###autoload
(define-minor-mode subword-mode
"Toggle subword movement and editing (Subword mode).
@ -121,8 +97,8 @@ With a prefix argument ARG, enable Subword mode if ARG is
positive, and disable it otherwise. If called from Lisp, enable
the mode if ARG is omitted or nil.
Subword mode is a buffer-local minor mode. Enabling it remaps
word-based editing commands to subword-based commands that handle
Subword mode is a buffer-local minor mode. Enabling it changes
the definition of a word so that word-based commands stop inside
symbols with mixed uppercase and lowercase letters,
e.g. \"GtkWidget\", \"EmacsFrameClass\", \"NSGraphicsContext\".
@ -136,13 +112,13 @@ called a `subword'. Here are some examples:
EmacsFrameClass => \"Emacs\", \"Frame\" and \"Class\"
NSGraphicsContext => \"NS\", \"Graphics\" and \"Context\"
The subword oriented commands activated in this minor mode recognize
subwords in a nomenclature to move between subwords and to edit them
as words.
This mode changes the definition of a word so that word commands
treat nomenclature boundaries as word bounaries.
\\{subword-mode-map}"
:lighter " ,"
(when subword-mode (superword-mode -1)))
(when subword-mode (superword-mode -1))
(subword-setup-buffer))
(define-obsolete-function-alias 'c-subword-mode 'subword-mode "23.2")
@ -151,6 +127,13 @@ as words.
(lambda () (subword-mode 1))
:group 'convenience)
;; N.B. These commands aren't used unless explicitly invoked; they're
;; here for compatibility. Today, subword-mode leaves motion commands
;; alone and uses `find-word-boundary-function-table' to change how
;; `forward-word' and other low-level commands detect word bounaries.
;; This way, all word-related activities, not just the images we
;; imagine here, get subword treatment.
(defun subword-forward (&optional arg)
"Do the same as `forward-word' but on subwords.
See the command `subword-mode' for a description of subwords.
@ -159,10 +142,10 @@ Optional argument ARG is the same as for `forward-word'."
(unless arg (setq arg 1))
(cond
((< 0 arg)
(dotimes (i arg (point))
(dotimes (_i arg (point))
(funcall subword-forward-function)))
((> 0 arg)
(dotimes (i (- arg) (point))
(dotimes (_i (- arg) (point))
(funcall subword-backward-function)))
(t
(point))))
@ -262,7 +245,7 @@ Optional argument ARG is the same as for `capitalize-word'."
(start (point))
(advance (>= arg 0)))
(dotimes (i count)
(dotimes (_i count)
(if advance
(progn
(re-search-forward "[[:alpha:]]")
@ -290,17 +273,15 @@ With a prefix argument ARG, enable Superword mode if ARG is
positive, and disable it otherwise. If called from Lisp, enable
the mode if ARG is omitted or nil.
Superword mode is a buffer-local minor mode. Enabling it remaps
word-based editing commands to superword-based commands that
treat symbols as words, e.g. \"this_is_a_symbol\".
The superword oriented commands activated in this minor mode
recognize symbols as superwords to move between superwords and to
edit them as words.
Superword mode is a buffer-local minor mode. Enabling it changes
the definition of words such that symbols characters are treated
as parts of words: e.g., in `superword-mode',
\"this_is_a_symbol\" counts as one word.
\\{superword-mode-map}"
:lighter " ²"
(when superword-mode (subword-mode -1)))
(when superword-mode (subword-mode -1))
(subword-setup-buffer))
;;;###autoload
(define-global-minor-mode global-superword-mode superword-mode
@ -347,9 +328,43 @@ edit them as words.
(1+ (match-beginning 0)))))
(backward-word 1))))
(defconst subword-find-word-boundary-function-table
(let ((tab (make-char-table nil)))
(set-char-table-range tab t #'subword-find-word-boundary)
tab)
"Assigned to `find-word-boundary-function-table' in
`subword-mode' and `superword-mode'; defers to
`subword-find-word-bounary'.")
(defconst subword-empty-char-table
(make-char-table nil)
"Assigned to `find-word-boundary-function-table' while we're
searching subwords in order to avoid unwanted reentrancy.")
(defun subword-setup-buffer ()
(set (make-local-variable 'find-word-boundary-function-table)
(if (or subword-mode superword-mode)
subword-find-word-boundary-function-table
subword-empty-char-table)))
(defun subword-find-word-boundary (pos limit)
"Catch-all handler in `subword-find-word-boundary-function-table'."
(let ((find-word-boundary-function-table subword-empty-char-table))
(save-match-data
(save-excursion
(save-restriction
(if (< pos limit)
(progn
(narrow-to-region (point-min) limit)
(funcall subword-forward-function))
(narrow-to-region limit (point-max))
(funcall subword-backward-function))
(point))))))
(provide 'subword)
(provide 'superword)
(provide 'cap-words) ; Obsolete alias
;;; subword.el ends here

View file

@ -1,3 +1,7 @@
2014-03-23 Daniel Colascione <dancol@dancol.org>
* automated/subword-tests.el (subword-tests2): More subword tests.
2014-03-23 Daniel Colascione <dancol@dancol.org>
* automated/cl-lib.el (cl-lib-keyword-names-versus-values): New

View file

@ -46,5 +46,36 @@
(insert "^"))
(should (equal (buffer-string) str)))))
(ert-deftest subword-tests2 ()
"Test that motion in subword-mode stops at the right places."
(let* ((line "fooBarBAZ quXD g_TESTThingAbc word BLAH test")
(fwrd "* * * * * * * * * * * * *")
(bkwd "* * * * * * * * * * * * *"))
(with-temp-buffer
(subword-mode 1)
(insert line)
;; Test forward motion.
(goto-char (point-min))
(let ((stops (make-string (length fwrd) ?\ )))
(while (progn
(aset stops (1- (point)) ?\*)
(not (eobp)))
(forward-word))
(should (equal stops fwrd)))
;; Test backward motion.
(goto-char (point-max))
(let ((stops (make-string (length bkwd) ?\ )))
(while (progn
(aset stops (1- (point)) ?\*)
(not (bobp)))
(backward-word))
(should (equal stops bkwd))))))
(provide 'subword-tests)
;;; subword-tests.el ends here