aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Colascione2014-03-23 00:36:26 -0700
committerDaniel Colascione2014-03-23 00:36:26 -0700
commit6ddc44225e743e2b2a0d5c192f50aefd7a4a915b (patch)
treecdd5a777e46741a6372df97ed4acc51126b42e93
parent10e00bd5b43c277ab59f336966a4a3ed35678d40 (diff)
downloademacs-6ddc44225e743e2b2a0d5c192f50aefd7a4a915b.tar.gz
emacs-6ddc44225e743e2b2a0d5c192f50aefd7a4a915b.zip
Merge capitalized-words-mode and subword-mode
-rw-r--r--lisp/ChangeLog21
-rw-r--r--lisp/progmodes/cap-words.el98
-rw-r--r--lisp/progmodes/subword.el123
-rw-r--r--test/ChangeLog4
-rw-r--r--test/automated/subword-tests.el31
5 files changed, 125 insertions, 152 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 64f138a2dc8..306570323df 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,26 @@
12014-03-23 Daniel Colascione <dancol@dancol.org> 12014-03-23 Daniel Colascione <dancol@dancol.org>
2 2
3 Change subword-mode to use `find-word-boundary-function-table' and
4 replace `capitalized-words-mode'. Also, convert to lexical
5 binding.
6
7 * progmodes/cap-words.el: Delete now-obsolete file.
8 * progmodes/subword.el: Reimplement using
9 `find-word-boundary-function-table'.
10 (subword-mode-map): Hollow out.
11 (capitalized-words-mode): Define as obsolete alias for
12 `subword-mode'.
13 (subword-mode,superword-mode): Tweak documentation to reflect new
14 implementation; call `subword-setup-buffer'.
15 (subword-forward,subword-capitalize): Add underscore to indicate
16 unused variable.
17 (subword-find-word-boundary-function-table): New constant.
18 (subword-empty-char-table): New constant.
19 (subword-setup-buffer): New function.
20 (subword-find-word-boundary): New function.
21
222014-03-23 Daniel Colascione <dancol@dancol.org>
23
3 * emacs-lisp/cl-macs.el (cl--do-arglist): Use a little `cl-loop' 24 * emacs-lisp/cl-macs.el (cl--do-arglist): Use a little `cl-loop'
4 list to look for keyword arguments instead of `memq', fixing 25 list to look for keyword arguments instead of `memq', fixing
5 (Bug#3647) --- unfortunately, only for freshly-compiled code. 26 (Bug#3647) --- unfortunately, only for freshly-compiled code.
diff --git a/lisp/progmodes/cap-words.el b/lisp/progmodes/cap-words.el
deleted file mode 100644
index b03daf4cd5a..00000000000
--- a/lisp/progmodes/cap-words.el
+++ /dev/null
@@ -1,98 +0,0 @@
1;;; cap-words.el --- minor mode for motion in CapitalizedWordIdentifiers
2
3;; Copyright (C) 2002-2014 Free Software Foundation, Inc.
4
5;; Author: Dave Love <fx@gnu.org>
6;; Keywords: languages
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software: you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
22
23;;; Commentary:
24
25;; Provides Capitalized Words minor mode for word movement in
26;; identifiers CapitalizedLikeThis.
27
28;; Note that the same effect could be obtained by frobbing the
29;; category of upper case characters to produce word boundaries, but
30;; the necessary processing isn't done for ASCII characters.
31
32;; Fixme: This doesn't work properly for mouse double clicks.
33
34;;; Code:
35
36(defun capitalized-find-word-boundary (pos limit)
37 "Function for use in `find-word-boundary-function-table'.
38Looks for word boundaries before capitals."
39 (save-excursion
40 (goto-char pos)
41 (let (case-fold-search)
42 (if (<= pos limit)
43 ;; Fixme: Are these regexps the best?
44 (or (and (re-search-forward "\\=.\\w*[[:upper:]]"
45 limit t)
46 (progn (backward-char)
47 t))
48 (re-search-forward "\\>" limit t))
49 (or (re-search-backward "[[:upper:]]\\w*\\=" limit t)
50 (re-search-backward "\\<" limit t))))
51 (point)))
52
53
54(defconst capitalized-find-word-boundary-function-table
55 (let ((tab (make-char-table nil)))
56 (set-char-table-range tab t #'capitalized-find-word-boundary)
57 tab)
58 "Assigned to `find-word-boundary-function-table' in Capitalized Words mode.")
59
60;;;###autoload
61(define-minor-mode capitalized-words-mode
62 "Toggle Capitalized Words mode.
63With a prefix argument ARG, enable Capitalized Words mode if ARG
64is positive, and disable it otherwise. If called from Lisp,
65enable the mode if ARG is omitted or nil.
66
67Capitalized Words mode is a buffer-local minor mode. When
68enabled, a word boundary occurs immediately before an uppercase
69letter in a symbol. This is in addition to all the normal
70boundaries given by the syntax and category tables. There is no
71restriction to ASCII.
72
73E.g. the beginning of words in the following identifier are as marked:
74
75 capitalizedWorDD
76 ^ ^ ^^
77
78Note that these word boundaries only apply for word motion and
79marking commands such as \\[forward-word]. This mode does not affect word
80boundaries found by regexp matching (`\\>', `\\w' &c).
81
82This style of identifiers is common in environments like Java ones,
83where underscores aren't trendy enough. Capitalization rules are
84sometimes part of the language, e.g. Haskell, which may thus encourage
85such a style. It is appropriate to add `capitalized-words-mode' to
86the mode hook for programming language modes in which you encounter
87variables like this, e.g. `java-mode-hook'. It's unlikely to cause
88trouble if such identifiers aren't used.
89
90See also `glasses-mode' and `studlify-word'.
91Obsoletes `c-forward-into-nomenclature'."
92 nil " Caps" nil :group 'programming
93 (set (make-local-variable 'find-word-boundary-function-table)
94 capitalized-find-word-boundary-function-table))
95
96(provide 'cap-words)
97
98;;; cap-words.el ends here
diff --git a/lisp/progmodes/subword.el b/lisp/progmodes/subword.el
index f9efa3732c7..50e4b42d5de 100644
--- a/lisp/progmodes/subword.el
+++ b/lisp/progmodes/subword.el
@@ -1,4 +1,4 @@
1;;; subword.el --- Handling capitalized subwords in a nomenclature 1;;; subword.el --- Handling capitalized subwords in a nomenclature -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2004-2014 Free Software Foundation, Inc. 3;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
4 4
@@ -21,13 +21,10 @@
21 21
22;;; Commentary: 22;;; Commentary:
23 23
24;; This package was cc-submode.el before it was recognized being 24;; This package provides the `subword' minor mode, which merges the
25;; useful in general and not tied to C and c-mode at all. 25;; old remap-based subword.el (derived from cc-mode code) and
26 26;; cap-words.el, which takes advantage of core Emacs
27;; This package provides `subword' oriented commands and a minor mode 27;; word-motion-customization functionality.
28;; (`subword-mode') that substitutes the common word handling
29;; functions with them. It also provides the `superword-mode' minor
30;; mode that treats symbols as words, the opposite of `subword-mode'.
31 28
32;; In spite of GNU Coding Standards, it is popular to name a symbol by 29;; In spite of GNU Coding Standards, it is popular to name a symbol by
33;; mixing uppercase and lowercase letters, e.g. "GtkWidget", 30;; mixing uppercase and lowercase letters, e.g. "GtkWidget",
@@ -47,25 +44,6 @@
47;; words. You also get a mode to treat symbols as words instead, 44;; words. You also get a mode to treat symbols as words instead,
48;; called `superword-mode' (the opposite of `subword-mode'). 45;; called `superword-mode' (the opposite of `subword-mode').
49 46
50;; In the minor mode, all common key bindings for word oriented
51;; commands are overridden by the subword oriented commands:
52
53;; Key Word oriented command Subword oriented command (also superword)
54;; ============================================================
55;; M-f `forward-word' `subword-forward'
56;; M-b `backward-word' `subword-backward'
57;; M-@ `mark-word' `subword-mark'
58;; M-d `kill-word' `subword-kill'
59;; M-DEL `backward-kill-word' `subword-backward-kill'
60;; M-t `transpose-words' `subword-transpose'
61;; M-c `capitalize-word' `subword-capitalize'
62;; M-u `upcase-word' `subword-upcase'
63;; M-l `downcase-word' `subword-downcase'
64;;
65;; Note: If you have changed the key bindings for the word oriented
66;; commands in your .emacs or a similar place, the keys you've changed
67;; to are also used for the corresponding subword oriented commands.
68
69;; To make the mode turn on automatically, put the following code in 47;; To make the mode turn on automatically, put the following code in
70;; your .emacs: 48;; your .emacs:
71;; 49;;
@@ -102,27 +80,25 @@
102 "Regexp used by `subword-backward-internal'.") 80 "Regexp used by `subword-backward-internal'.")
103 81
104(defvar subword-mode-map 82(defvar subword-mode-map
105 (let ((map (make-sparse-keymap))) 83 ;; We originally remapped motion keys here, but now use Emacs core
106 (dolist (cmd '(forward-word backward-word mark-word kill-word 84 ;; hooks. Leave this keymap around so that user additions to it
107 backward-kill-word transpose-words 85 ;; keep working.
108 capitalize-word upcase-word downcase-word 86 (make-sparse-keymap)
109 left-word right-word))
110 (let ((othercmd (let ((name (symbol-name cmd)))
111 (string-match "\\([[:alpha:]-]+\\)-word[s]?" name)
112 (intern (concat "subword-" (match-string 1 name))))))
113 (define-key map (vector 'remap cmd) othercmd)))
114 map)
115 "Keymap used in `subword-mode' minor mode.") 87 "Keymap used in `subword-mode' minor mode.")
116 88
117;;;###autoload 89;;;###autoload
90(define-obsolete-function-alias
91 'capitalized-words-mode 'subword-mode "24.5")
92
93;;;###autoload
118(define-minor-mode subword-mode 94(define-minor-mode subword-mode
119 "Toggle subword movement and editing (Subword mode). 95 "Toggle subword movement and editing (Subword mode).
120With a prefix argument ARG, enable Subword mode if ARG is 96With a prefix argument ARG, enable Subword mode if ARG is
121positive, and disable it otherwise. If called from Lisp, enable 97positive, and disable it otherwise. If called from Lisp, enable
122the mode if ARG is omitted or nil. 98the mode if ARG is omitted or nil.
123 99
124Subword mode is a buffer-local minor mode. Enabling it remaps 100Subword mode is a buffer-local minor mode. Enabling it changes
125word-based editing commands to subword-based commands that handle 101the definition of a word so that word-based commands stop inside
126symbols with mixed uppercase and lowercase letters, 102symbols with mixed uppercase and lowercase letters,
127e.g. \"GtkWidget\", \"EmacsFrameClass\", \"NSGraphicsContext\". 103e.g. \"GtkWidget\", \"EmacsFrameClass\", \"NSGraphicsContext\".
128 104
@@ -136,13 +112,13 @@ called a `subword'. Here are some examples:
136 EmacsFrameClass => \"Emacs\", \"Frame\" and \"Class\" 112 EmacsFrameClass => \"Emacs\", \"Frame\" and \"Class\"
137 NSGraphicsContext => \"NS\", \"Graphics\" and \"Context\" 113 NSGraphicsContext => \"NS\", \"Graphics\" and \"Context\"
138 114
139The subword oriented commands activated in this minor mode recognize 115This mode changes the definition of a word so that word commands
140subwords in a nomenclature to move between subwords and to edit them 116treat nomenclature boundaries as word bounaries.
141as words.
142 117
143\\{subword-mode-map}" 118\\{subword-mode-map}"
144 :lighter " ," 119 :lighter " ,"
145 (when subword-mode (superword-mode -1))) 120 (when subword-mode (superword-mode -1))
121 (subword-setup-buffer))
146 122
147(define-obsolete-function-alias 'c-subword-mode 'subword-mode "23.2") 123(define-obsolete-function-alias 'c-subword-mode 'subword-mode "23.2")
148 124
@@ -151,6 +127,13 @@ as words.
151 (lambda () (subword-mode 1)) 127 (lambda () (subword-mode 1))
152 :group 'convenience) 128 :group 'convenience)
153 129
130;; N.B. These commands aren't used unless explicitly invoked; they're
131;; here for compatibility. Today, subword-mode leaves motion commands
132;; alone and uses `find-word-boundary-function-table' to change how
133;; `forward-word' and other low-level commands detect word bounaries.
134;; This way, all word-related activities, not just the images we
135;; imagine here, get subword treatment.
136
154(defun subword-forward (&optional arg) 137(defun subword-forward (&optional arg)
155 "Do the same as `forward-word' but on subwords. 138 "Do the same as `forward-word' but on subwords.
156See the command `subword-mode' for a description of subwords. 139See the command `subword-mode' for a description of subwords.
@@ -159,10 +142,10 @@ Optional argument ARG is the same as for `forward-word'."
159 (unless arg (setq arg 1)) 142 (unless arg (setq arg 1))
160 (cond 143 (cond
161 ((< 0 arg) 144 ((< 0 arg)
162 (dotimes (i arg (point)) 145 (dotimes (_i arg (point))
163 (funcall subword-forward-function))) 146 (funcall subword-forward-function)))
164 ((> 0 arg) 147 ((> 0 arg)
165 (dotimes (i (- arg) (point)) 148 (dotimes (_i (- arg) (point))
166 (funcall subword-backward-function))) 149 (funcall subword-backward-function)))
167 (t 150 (t
168 (point)))) 151 (point))))
@@ -262,7 +245,7 @@ Optional argument ARG is the same as for `capitalize-word'."
262 (start (point)) 245 (start (point))
263 (advance (>= arg 0))) 246 (advance (>= arg 0)))
264 247
265 (dotimes (i count) 248 (dotimes (_i count)
266 (if advance 249 (if advance
267 (progn 250 (progn
268 (re-search-forward "[[:alpha:]]") 251 (re-search-forward "[[:alpha:]]")
@@ -290,17 +273,15 @@ With a prefix argument ARG, enable Superword mode if ARG is
290positive, and disable it otherwise. If called from Lisp, enable 273positive, and disable it otherwise. If called from Lisp, enable
291the mode if ARG is omitted or nil. 274the mode if ARG is omitted or nil.
292 275
293Superword mode is a buffer-local minor mode. Enabling it remaps 276Superword mode is a buffer-local minor mode. Enabling it changes
294word-based editing commands to superword-based commands that 277the definition of words such that symbols characters are treated
295treat symbols as words, e.g. \"this_is_a_symbol\". 278as parts of words: e.g., in `superword-mode',
296 279\"this_is_a_symbol\" counts as one word.
297The superword oriented commands activated in this minor mode
298recognize symbols as superwords to move between superwords and to
299edit them as words.
300 280
301\\{superword-mode-map}" 281\\{superword-mode-map}"
302 :lighter " ²" 282 :lighter " ²"
303 (when superword-mode (subword-mode -1))) 283 (when superword-mode (subword-mode -1))
284 (subword-setup-buffer))
304 285
305;;;###autoload 286;;;###autoload
306(define-global-minor-mode global-superword-mode superword-mode 287(define-global-minor-mode global-superword-mode superword-mode
@@ -347,9 +328,43 @@ edit them as words.
347 (1+ (match-beginning 0))))) 328 (1+ (match-beginning 0)))))
348 (backward-word 1)))) 329 (backward-word 1))))
349 330
331(defconst subword-find-word-boundary-function-table
332 (let ((tab (make-char-table nil)))
333 (set-char-table-range tab t #'subword-find-word-boundary)
334 tab)
335 "Assigned to `find-word-boundary-function-table' in
336`subword-mode' and `superword-mode'; defers to
337`subword-find-word-bounary'.")
338
339(defconst subword-empty-char-table
340 (make-char-table nil)
341 "Assigned to `find-word-boundary-function-table' while we're
342searching subwords in order to avoid unwanted reentrancy.")
343
344(defun subword-setup-buffer ()
345 (set (make-local-variable 'find-word-boundary-function-table)
346 (if (or subword-mode superword-mode)
347 subword-find-word-boundary-function-table
348 subword-empty-char-table)))
349
350(defun subword-find-word-boundary (pos limit)
351 "Catch-all handler in `subword-find-word-boundary-function-table'."
352 (let ((find-word-boundary-function-table subword-empty-char-table))
353 (save-match-data
354 (save-excursion
355 (save-restriction
356 (if (< pos limit)
357 (progn
358 (narrow-to-region (point-min) limit)
359 (funcall subword-forward-function))
360 (narrow-to-region limit (point-max))
361 (funcall subword-backward-function))
362 (point))))))
363
350 364
351 365
352(provide 'subword) 366(provide 'subword)
353(provide 'superword) 367(provide 'superword)
368(provide 'cap-words) ; Obsolete alias
354 369
355;;; subword.el ends here 370;;; subword.el ends here
diff --git a/test/ChangeLog b/test/ChangeLog
index 1fe024a1286..026357771bf 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,5 +1,9 @@
12014-03-23 Daniel Colascione <dancol@dancol.org> 12014-03-23 Daniel Colascione <dancol@dancol.org>
2 2
3 * automated/subword-tests.el (subword-tests2): More subword tests.
4
52014-03-23 Daniel Colascione <dancol@dancol.org>
6
3 * automated/cl-lib.el (cl-lib-keyword-names-versus-values): New 7 * automated/cl-lib.el (cl-lib-keyword-names-versus-values): New
4 test: correct parsing of keyword arguments. 8 test: correct parsing of keyword arguments.
5 9
diff --git a/test/automated/subword-tests.el b/test/automated/subword-tests.el
index 3b37bc84886..7c6c77d4cc9 100644
--- a/test/automated/subword-tests.el
+++ b/test/automated/subword-tests.el
@@ -46,5 +46,36 @@
46 (insert "^")) 46 (insert "^"))
47 (should (equal (buffer-string) str))))) 47 (should (equal (buffer-string) str)))))
48 48
49(ert-deftest subword-tests2 ()
50 "Test that motion in subword-mode stops at the right places."
51
52 (let* ((line "fooBarBAZ quXD g_TESTThingAbc word BLAH test")
53 (fwrd "* * * * * * * * * * * * *")
54 (bkwd "* * * * * * * * * * * * *"))
55
56 (with-temp-buffer
57 (subword-mode 1)
58 (insert line)
59
60 ;; Test forward motion.
61
62 (goto-char (point-min))
63 (let ((stops (make-string (length fwrd) ?\ )))
64 (while (progn
65 (aset stops (1- (point)) ?\*)
66 (not (eobp)))
67 (forward-word))
68 (should (equal stops fwrd)))
69
70 ;; Test backward motion.
71
72 (goto-char (point-max))
73 (let ((stops (make-string (length bkwd) ?\ )))
74 (while (progn
75 (aset stops (1- (point)) ?\*)
76 (not (bobp)))
77 (backward-word))
78 (should (equal stops bkwd))))))
79
49(provide 'subword-tests) 80(provide 'subword-tests)
50;;; subword-tests.el ends here 81;;; subword-tests.el ends here