Fix more minor mode docstrings.
[bpt/emacs.git] / lisp / progmodes / subword.el
CommitLineData
653d1554 1;;; subword.el --- Handling capitalized subwords in a nomenclature
0386b551 2
73b0cd50 3;; Copyright (C) 2004-2011 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
0386b551
AM
29;; functions with them.
30
31;; In spite of GNU Coding Standards, it is popular to name a symbol by
32;; mixing uppercase and lowercase letters, e.g. "GtkWidget",
33;; "EmacsFrameClass", "NSGraphicsContext", etc. Here we call these
34;; mixed case symbols `nomenclatures'. Also, each capitalized (or
35;; completely uppercase) part of a nomenclature is called a `subword'.
36;; Here are some examples:
37
38;; Nomenclature Subwords
39;; ===========================================================
40;; GtkWindow => "Gtk" and "Window"
41;; EmacsFrameClass => "Emacs", "Frame" and "Class"
42;; NSGraphicsContext => "NS", "Graphics" and "Context"
43
44;; The subword oriented commands defined in this package recognize
45;; subwords in a nomenclature to move between them and to edit them as
46;; words.
47
48;; In the minor mode, all common key bindings for word oriented
49;; commands are overridden by the subword oriented commands:
50
51;; Key Word oriented command Subword oriented command
52;; ============================================================
a9b76eec
TH
53;; M-f `forward-word' `subword-forward'
54;; M-b `backward-word' `subword-backward'
55;; M-@ `mark-word' `subword-mark'
56;; M-d `kill-word' `subword-kill'
57;; M-DEL `backward-kill-word' `subword-backward-kill'
58;; M-t `transpose-words' `subword-transpose'
59;; M-c `capitalize-word' `subword-capitalize'
60;; M-u `upcase-word' `subword-upcase'
61;; M-l `downcase-word' `subword-downcase'
0386b551
AM
62;;
63;; Note: If you have changed the key bindings for the word oriented
64;; commands in your .emacs or a similar place, the keys you've changed
65;; to are also used for the corresponding subword oriented commands.
66
67;; To make the mode turn on automatically, put the following code in
68;; your .emacs:
69;;
70;; (add-hook 'c-mode-common-hook
653d1554 71;; (lambda () (subword-mode 1)))
0386b551
AM
72;;
73
74;; Acknowledgment:
75;; The regular expressions to detect subwords are mostly based on
76;; the old `c-forward-into-nomenclature' originally contributed by
77;; Terry_Glanfield dot Southern at rxuk dot xerox dot com.
78
1ddb2ea0 79;; TODO: ispell-word.
0386b551
AM
80
81;;; Code:
82
653d1554 83(defvar subword-mode-map
27558c0d 84 (let ((map (make-sparse-keymap)))
653d1554
TH
85 (dolist (cmd '(forward-word backward-word mark-word kill-word
86 backward-kill-word transpose-words
27558c0d
GM
87 capitalize-word upcase-word downcase-word))
88 (let ((othercmd (let ((name (symbol-name cmd)))
9ee12eee
TH
89 (string-match "\\([[:alpha:]-]+\\)-word[s]?" name)
90 (intern (concat "subword-" (match-string 1 name))))))
653d1554 91 (define-key map (vector 'remap cmd) othercmd)))
27558c0d 92 map)
653d1554 93 "Keymap used in `subword-mode' minor mode.")
27558c0d
GM
94
95;;;###autoload
653d1554 96(define-minor-mode subword-mode
ac6c8639
CY
97 "Toggle subword movement and editing (Subword mode).
98With a prefix argument ARG, enable Subword mode if ARG is
99positive, and disable it otherwise. If called from Lisp, enable
100the mode if ARG is omitted or nil.
101
102Subword mode is a buffer-local minor mode. Enabling it remaps
103word-based editing commands to subword-based commands that handle
104symbols with mixed uppercase and lowercase letters,
105e.g. \"GtkWidget\", \"EmacsFrameClass\", \"NSGraphicsContext\".
106
107Here we call these mixed case symbols `nomenclatures'. Each
108capitalized (or completely uppercase) part of a nomenclature is
109called a `subword'. Here are some examples:
0386b551
AM
110
111 Nomenclature Subwords
112 ===========================================================
113 GtkWindow => \"Gtk\" and \"Window\"
114 EmacsFrameClass => \"Emacs\", \"Frame\" and \"Class\"
115 NSGraphicsContext => \"NS\", \"Graphics\" and \"Context\"
116
117The subword oriented commands activated in this minor mode recognize
118subwords in a nomenclature to move between subwords and to edit them
119as words.
120
653d1554 121\\{subword-mode-map}"
0386b551
AM
122 nil
123 nil
653d1554
TH
124 subword-mode-map)
125
126(define-obsolete-function-alias 'c-subword-mode 'subword-mode "23.2")
0386b551 127
653d1554
TH
128;;;###autoload
129(define-global-minor-mode global-subword-mode subword-mode
130 (lambda () (subword-mode 1)))
131
a9b76eec 132(defun subword-forward (&optional arg)
0386b551 133 "Do the same as `forward-word' but on subwords.
653d1554 134See the command `subword-mode' for a description of subwords.
0386b551
AM
135Optional argument ARG is the same as for `forward-word'."
136 (interactive "p")
137 (unless arg (setq arg 1))
0386b551
AM
138 (cond
139 ((< 0 arg)
140 (dotimes (i arg (point))
a9b76eec 141 (subword-forward-internal)))
0386b551
AM
142 ((> 0 arg)
143 (dotimes (i (- arg) (point))
a9b76eec 144 (subword-backward-internal)))
0386b551
AM
145 (t
146 (point))))
147
a9b76eec 148(put 'subword-forward 'CUA 'move)
5e8c9892 149
a9b76eec 150(defun subword-backward (&optional arg)
0386b551 151 "Do the same as `backward-word' but on subwords.
653d1554 152See the command `subword-mode' for a description of subwords.
0386b551
AM
153Optional argument ARG is the same as for `backward-word'."
154 (interactive "p")
a9b76eec 155 (subword-forward (- (or arg 1))))
0386b551 156
a9b76eec 157(defun subword-mark (arg)
0386b551 158 "Do the same as `mark-word' but on subwords.
653d1554 159See the command `subword-mode' for a description of subwords.
0386b551
AM
160Optional argument ARG is the same as for `mark-word'."
161 ;; This code is almost copied from `mark-word' in GNU Emacs.
162 (interactive "p")
163 (cond ((and (eq last-command this-command) (mark t))
164 (set-mark
165 (save-excursion
166 (goto-char (mark))
a9b76eec 167 (subword-forward arg)
0386b551
AM
168 (point))))
169 (t
170 (push-mark
171 (save-excursion
a9b76eec 172 (subword-forward arg)
0386b551
AM
173 (point))
174 nil t))))
175
a9b76eec 176(put 'subword-backward 'CUA 'move)
5e8c9892 177
a9b76eec 178(defun subword-kill (arg)
0386b551 179 "Do the same as `kill-word' but on subwords.
653d1554 180See the command `subword-mode' for a description of subwords.
0386b551
AM
181Optional argument ARG is the same as for `kill-word'."
182 (interactive "p")
a9b76eec 183 (kill-region (point) (subword-forward arg)))
0386b551 184
a9b76eec 185(defun subword-backward-kill (arg)
0386b551 186 "Do the same as `backward-kill-word' but on subwords.
653d1554 187See the command `subword-mode' for a description of subwords.
0386b551
AM
188Optional argument ARG is the same as for `backward-kill-word'."
189 (interactive "p")
a9b76eec 190 (subword-kill (- arg)))
0386b551 191
a9b76eec 192(defun subword-transpose (arg)
0386b551 193 "Do the same as `transpose-words' but on subwords.
653d1554 194See the command `subword-mode' for a description of subwords.
0386b551
AM
195Optional argument ARG is the same as for `transpose-words'."
196 (interactive "*p")
a9b76eec 197 (transpose-subr 'subword-forward arg))
287787ee 198
a9b76eec 199(defun subword-downcase (arg)
287787ee 200 "Do the same as `downcase-word' but on subwords.
653d1554 201See the command `subword-mode' for a description of subwords.
287787ee
MY
202Optional argument ARG is the same as for `downcase-word'."
203 (interactive "p")
204 (let ((start (point)))
a9b76eec 205 (downcase-region (point) (subword-forward arg))
653d1554 206 (when (< arg 0)
287787ee
MY
207 (goto-char start))))
208
a9b76eec 209(defun subword-upcase (arg)
287787ee 210 "Do the same as `upcase-word' but on subwords.
653d1554 211See the command `subword-mode' for a description of subwords.
287787ee
MY
212Optional argument ARG is the same as for `upcase-word'."
213 (interactive "p")
214 (let ((start (point)))
a9b76eec 215 (upcase-region (point) (subword-forward arg))
653d1554 216 (when (< arg 0)
287787ee
MY
217 (goto-char start))))
218
a9b76eec 219(defun subword-capitalize (arg)
0386b551 220 "Do the same as `capitalize-word' but on subwords.
653d1554 221See the command `subword-mode' for a description of subwords.
0386b551
AM
222Optional argument ARG is the same as for `capitalize-word'."
223 (interactive "p")
224 (let ((count (abs arg))
11d13e96
MY
225 (start (point))
226 (advance (if (< arg 0) nil t)))
0386b551 227 (dotimes (i count)
11d13e96
MY
228 (if advance
229 (progn (re-search-forward
653d1554 230 (concat "[[:alpha:]]")
11d13e96
MY
231 nil t)
232 (goto-char (match-beginning 0)))
a9b76eec 233 (subword-backward))
0386b551
AM
234 (let* ((p (point))
235 (pp (1+ p))
a9b76eec 236 (np (subword-forward)))
0386b551
AM
237 (upcase-region p pp)
238 (downcase-region pp np)
11d13e96
MY
239 (goto-char (if advance np p))))
240 (unless advance
241 (goto-char start))))
0386b551 242
0386b551
AM
243
244\f
245;;
246;; Internal functions
247;;
a9b76eec 248(defun subword-forward-internal ()
0386b551 249 (if (and
5e8c9892 250 (save-excursion
0386b551 251 (let ((case-fold-search nil))
5e8c9892 252 (re-search-forward
653d1554 253 (concat "\\W*\\(\\([[:upper:]]*\\W?\\)[[:lower:][:digit:]]*\\)")
0386b551 254 nil t)))
653d1554 255 (> (match-end 0) (point)))
5e8c9892 256 (goto-char
0386b551
AM
257 (cond
258 ((< 1 (- (match-end 2) (match-beginning 2)))
259 (1- (match-end 2)))
260 (t
261 (match-end 0))))
262 (forward-word 1)))
263
264
a9b76eec 265(defun subword-backward-internal ()
5e8c9892
KS
266 (if (save-excursion
267 (let ((case-fold-search nil))
0386b551
AM
268 (re-search-backward
269 (concat
653d1554 270 "\\(\\(\\W\\|[[:lower:][:digit:]]\\)\\([[:upper:]]+\\W*\\)"
5e8c9892 271 "\\|\\W\\w+\\)")
0386b551 272 nil t)))
5e8c9892
KS
273 (goto-char
274 (cond
0386b551
AM
275 ((and (match-end 3)
276 (< 1 (- (match-end 3) (match-beginning 3)))
277 (not (eq (point) (match-end 3))))
278 (1- (match-end 3)))
279 (t
280 (1+ (match-beginning 0)))))
281 (backward-word 1)))
282
283\f
653d1554 284(provide 'subword)
0386b551 285
653d1554 286;;; subword.el ends here