* term/xterm.el (xterm--query): Stop after first matching handler. (Bug#14615)
[bpt/emacs.git] / lisp / progmodes / subword.el
CommitLineData
653d1554 1;;; subword.el --- Handling capitalized subwords in a nomenclature
0386b551 2
ab422c4d 3;; Copyright (C) 2004-2013 Free Software Foundation, Inc.
0386b551
AM
4
5;; Author: Masatake YAMATO
6
b1fc2b50
GM
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
0386b551 10;; it under the terms of the GNU General Public License as published by
b1fc2b50
GM
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
0386b551 13
b1fc2b50 14;; GNU Emacs is distributed in the hope that it will be useful,
0386b551
AM
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
b1fc2b50 20;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
0386b551
AM
21
22;;; Commentary:
23
653d1554
TH
24;; This package was cc-submode.el before it was recognized being
25;; useful in general and not tied to C and c-mode at all.
26
0386b551 27;; This package provides `subword' oriented commands and a minor mode
653d1554 28;; (`subword-mode') that substitutes the common word handling
002668e1
TZ
29;; functions with them. It also provides the `superword-mode' minor
30;; mode that treats symbols as words, the opposite of `subword-mode'.
0386b551
AM
31
32;; In spite of GNU Coding Standards, it is popular to name a symbol by
33;; mixing uppercase and lowercase letters, e.g. "GtkWidget",
34;; "EmacsFrameClass", "NSGraphicsContext", etc. Here we call these
35;; mixed case symbols `nomenclatures'. Also, each capitalized (or
36;; completely uppercase) part of a nomenclature is called a `subword'.
37;; Here are some examples:
38
39;; Nomenclature Subwords
40;; ===========================================================
41;; GtkWindow => "Gtk" and "Window"
42;; EmacsFrameClass => "Emacs", "Frame" and "Class"
43;; NSGraphicsContext => "NS", "Graphics" and "Context"
44
45;; The subword oriented commands defined in this package recognize
46;; subwords in a nomenclature to move between them and to edit them as
002668e1
TZ
47;; words. You also get a mode to treat symbols as words instead,
48;; called `superword-mode' (the opposite of `subword-mode').
0386b551
AM
49
50;; In the minor mode, all common key bindings for word oriented
51;; commands are overridden by the subword oriented commands:
52
002668e1 53;; Key Word oriented command Subword oriented command (also superword)
0386b551 54;; ============================================================
a9b76eec
TH
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'
0386b551
AM
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
70;; your .emacs:
71;;
002668e1
TZ
72;; (add-hook 'c-mode-common-hook 'subword-mode)
73;;
74
75;; To make the mode turn `superword-mode' on automatically for
76;; only some modes, put the following code in your .emacs:
77;;
78;; (add-hook 'c-mode-common-hook 'superword-mode)
0386b551
AM
79;;
80
81;; Acknowledgment:
82;; The regular expressions to detect subwords are mostly based on
83;; the old `c-forward-into-nomenclature' originally contributed by
84;; Terry_Glanfield dot Southern at rxuk dot xerox dot com.
85
1ddb2ea0 86;; TODO: ispell-word.
0386b551
AM
87
88;;; Code:
89
1c308380
PS
90(defvar subword-forward-function 'subword-forward-internal
91 "Function to call for forward subword movement.")
92
93(defvar subword-backward-function 'subword-backward-internal
94 "Function to call for backward subword movement.")
95
96(defvar subword-forward-regexp
97 "\\W*\\(\\([[:upper:]]*\\W?\\)[[:lower:][:digit:]]*\\)"
98 "Regexp used by `subword-forward-internal'.")
99
100(defvar subword-backward-regexp
101 "\\(\\(\\W\\|[[:lower:][:digit:]]\\)\\([[:upper:]]+\\W*\\)\\|\\W\\w+\\)"
102 "Regexp used by `subword-backward-internal'.")
103
653d1554 104(defvar subword-mode-map
27558c0d 105 (let ((map (make-sparse-keymap)))
653d1554
TH
106 (dolist (cmd '(forward-word backward-word mark-word kill-word
107 backward-kill-word transpose-words
002668e1
TZ
108 capitalize-word upcase-word downcase-word
109 left-word right-word))
27558c0d 110 (let ((othercmd (let ((name (symbol-name cmd)))
9ee12eee
TH
111 (string-match "\\([[:alpha:]-]+\\)-word[s]?" name)
112 (intern (concat "subword-" (match-string 1 name))))))
653d1554 113 (define-key map (vector 'remap cmd) othercmd)))
27558c0d 114 map)
653d1554 115 "Keymap used in `subword-mode' minor mode.")
27558c0d
GM
116
117;;;###autoload
653d1554 118(define-minor-mode subword-mode
ac6c8639
CY
119 "Toggle subword movement and editing (Subword mode).
120With a prefix argument ARG, enable Subword mode if ARG is
121positive, and disable it otherwise. If called from Lisp, enable
122the mode if ARG is omitted or nil.
123
124Subword mode is a buffer-local minor mode. Enabling it remaps
125word-based editing commands to subword-based commands that handle
126symbols with mixed uppercase and lowercase letters,
127e.g. \"GtkWidget\", \"EmacsFrameClass\", \"NSGraphicsContext\".
128
129Here we call these mixed case symbols `nomenclatures'. Each
130capitalized (or completely uppercase) part of a nomenclature is
131called a `subword'. Here are some examples:
0386b551
AM
132
133 Nomenclature Subwords
134 ===========================================================
135 GtkWindow => \"Gtk\" and \"Window\"
136 EmacsFrameClass => \"Emacs\", \"Frame\" and \"Class\"
137 NSGraphicsContext => \"NS\", \"Graphics\" and \"Context\"
138
139The subword oriented commands activated in this minor mode recognize
140subwords in a nomenclature to move between subwords and to edit them
141as words.
142
653d1554 143\\{subword-mode-map}"
002668e1
TZ
144 :lighter " ,"
145 (when subword-mode (superword-mode -1)))
653d1554
TH
146
147(define-obsolete-function-alias 'c-subword-mode 'subword-mode "23.2")
0386b551 148
653d1554
TH
149;;;###autoload
150(define-global-minor-mode global-subword-mode subword-mode
a21ba35d
GM
151 (lambda () (subword-mode 1))
152 :group 'convenience)
653d1554 153
a9b76eec 154(defun subword-forward (&optional arg)
0386b551 155 "Do the same as `forward-word' but on subwords.
653d1554 156See the command `subword-mode' for a description of subwords.
0386b551 157Optional argument ARG is the same as for `forward-word'."
75a2f981 158 (interactive "^p")
0386b551 159 (unless arg (setq arg 1))
0386b551
AM
160 (cond
161 ((< 0 arg)
162 (dotimes (i arg (point))
1c308380 163 (funcall subword-forward-function)))
0386b551
AM
164 ((> 0 arg)
165 (dotimes (i (- arg) (point))
1c308380 166 (funcall subword-backward-function)))
0386b551
AM
167 (t
168 (point))))
169
a9b76eec 170(put 'subword-forward 'CUA 'move)
5e8c9892 171
a9b76eec 172(defun subword-backward (&optional arg)
0386b551 173 "Do the same as `backward-word' but on subwords.
653d1554 174See the command `subword-mode' for a description of subwords.
0386b551 175Optional argument ARG is the same as for `backward-word'."
75a2f981 176 (interactive "^p")
a9b76eec 177 (subword-forward (- (or arg 1))))
0386b551 178
75a2f981
TZ
179(defun subword-right (&optional arg)
180 "Do the same as `right-word' but on subwords."
181 (interactive "^p")
182 (if (eq (current-bidi-paragraph-direction) 'left-to-right)
183 (subword-forward arg)
184 (subword-backward arg)))
185
186(defun subword-left (&optional arg)
187 "Do the same as `left-word' but on subwords."
188 (interactive "^p")
189 (if (eq (current-bidi-paragraph-direction) 'left-to-right)
190 (subword-backward arg)
191 (subword-forward arg)))
002668e1 192
a9b76eec 193(defun subword-mark (arg)
0386b551 194 "Do the same as `mark-word' but on subwords.
653d1554 195See the command `subword-mode' for a description of subwords.
0386b551
AM
196Optional argument ARG is the same as for `mark-word'."
197 ;; This code is almost copied from `mark-word' in GNU Emacs.
198 (interactive "p")
199 (cond ((and (eq last-command this-command) (mark t))
200 (set-mark
201 (save-excursion
202 (goto-char (mark))
a9b76eec 203 (subword-forward arg)
0386b551
AM
204 (point))))
205 (t
206 (push-mark
207 (save-excursion
a9b76eec 208 (subword-forward arg)
0386b551
AM
209 (point))
210 nil t))))
211
a9b76eec 212(put 'subword-backward 'CUA 'move)
5e8c9892 213
a9b76eec 214(defun subword-kill (arg)
0386b551 215 "Do the same as `kill-word' but on subwords.
653d1554 216See the command `subword-mode' for a description of subwords.
0386b551
AM
217Optional argument ARG is the same as for `kill-word'."
218 (interactive "p")
a9b76eec 219 (kill-region (point) (subword-forward arg)))
0386b551 220
a9b76eec 221(defun subword-backward-kill (arg)
0386b551 222 "Do the same as `backward-kill-word' but on subwords.
653d1554 223See the command `subword-mode' for a description of subwords.
0386b551
AM
224Optional argument ARG is the same as for `backward-kill-word'."
225 (interactive "p")
a9b76eec 226 (subword-kill (- arg)))
0386b551 227
a9b76eec 228(defun subword-transpose (arg)
0386b551 229 "Do the same as `transpose-words' but on subwords.
653d1554 230See the command `subword-mode' for a description of subwords.
0386b551
AM
231Optional argument ARG is the same as for `transpose-words'."
232 (interactive "*p")
a9b76eec 233 (transpose-subr 'subword-forward arg))
287787ee 234
a9b76eec 235(defun subword-downcase (arg)
287787ee 236 "Do the same as `downcase-word' but on subwords.
653d1554 237See the command `subword-mode' for a description of subwords.
287787ee
MY
238Optional argument ARG is the same as for `downcase-word'."
239 (interactive "p")
240 (let ((start (point)))
a9b76eec 241 (downcase-region (point) (subword-forward arg))
653d1554 242 (when (< arg 0)
287787ee
MY
243 (goto-char start))))
244
a9b76eec 245(defun subword-upcase (arg)
287787ee 246 "Do the same as `upcase-word' but on subwords.
653d1554 247See the command `subword-mode' for a description of subwords.
287787ee
MY
248Optional argument ARG is the same as for `upcase-word'."
249 (interactive "p")
250 (let ((start (point)))
a9b76eec 251 (upcase-region (point) (subword-forward arg))
653d1554 252 (when (< arg 0)
287787ee
MY
253 (goto-char start))))
254
a9b76eec 255(defun subword-capitalize (arg)
0386b551 256 "Do the same as `capitalize-word' but on subwords.
653d1554 257See the command `subword-mode' for a description of subwords.
0386b551
AM
258Optional argument ARG is the same as for `capitalize-word'."
259 (interactive "p")
260 (let ((count (abs arg))
11d13e96
MY
261 (start (point))
262 (advance (if (< arg 0) nil t)))
0386b551 263 (dotimes (i count)
11d13e96
MY
264 (if advance
265 (progn (re-search-forward
653d1554 266 (concat "[[:alpha:]]")
11d13e96
MY
267 nil t)
268 (goto-char (match-beginning 0)))
a9b76eec 269 (subword-backward))
0386b551
AM
270 (let* ((p (point))
271 (pp (1+ p))
a9b76eec 272 (np (subword-forward)))
0386b551
AM
273 (upcase-region p pp)
274 (downcase-region pp np)
11d13e96
MY
275 (goto-char (if advance np p))))
276 (unless advance
277 (goto-char start))))
0386b551 278
002668e1
TZ
279\f
280
281(defvar superword-mode-map subword-mode-map
282 "Keymap used in `superword-mode' minor mode.")
283
284;;;###autoload
285(define-minor-mode superword-mode
286 "Toggle superword movement and editing (Superword mode).
287With a prefix argument ARG, enable Superword mode if ARG is
288positive, and disable it otherwise. If called from Lisp, enable
289the mode if ARG is omitted or nil.
290
291Superword mode is a buffer-local minor mode. Enabling it remaps
292word-based editing commands to superword-based commands that
293treat symbols as words, e.g. \"this_is_a_symbol\".
294
295The superword oriented commands activated in this minor mode
296recognize symbols as superwords to move between superwords and to
297edit them as words.
298
299\\{superword-mode-map}"
300 :lighter " ²"
301 (when superword-mode (subword-mode -1)))
302
303;;;###autoload
304(define-global-minor-mode global-superword-mode superword-mode
a21ba35d
GM
305 (lambda () (superword-mode 1))
306 :group 'convenience)
0386b551
AM
307
308\f
309;;
310;; Internal functions
311;;
a9b76eec 312(defun subword-forward-internal ()
002668e1 313 (if superword-mode
0b938190 314 (forward-symbol 1)
002668e1
TZ
315 (if (and
316 (save-excursion
317 (let ((case-fold-search nil))
318 (re-search-forward subword-forward-regexp nil t)))
319 (> (match-end 0) (point)))
320 (goto-char
321 (cond
322 ((< 1 (- (match-end 2) (match-beginning 2)))
323 (1- (match-end 2)))
324 (t
325 (match-end 0))))
326 (forward-word 1))))
0386b551 327
a9b76eec 328(defun subword-backward-internal ()
002668e1 329 (if superword-mode
0b938190 330 (forward-symbol -1)
002668e1
TZ
331 (if (save-excursion
332 (let ((case-fold-search nil))
333 (re-search-backward subword-backward-regexp nil t)))
334 (goto-char
335 (cond
336 ((and (match-end 3)
337 (< 1 (- (match-end 3) (match-beginning 3)))
338 (not (eq (point) (match-end 3))))
339 (1- (match-end 3)))
340 (t
341 (1+ (match-beginning 0)))))
342 (backward-word 1))))
0386b551
AM
343
344\f
002668e1 345
653d1554 346(provide 'subword)
002668e1 347(provide 'superword)
0386b551 348
653d1554 349;;; subword.el ends here