From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Daniel Colascione Newsgroups: gmane.emacs.devel Subject: [PATCH 1/2] Merge subword-mode and capitalized-words-mode Date: Tue, 07 Aug 2012 10:03:52 -0700 Message-ID: References: NNTP-Posting-Host: plane.gmane.org X-Trace: dough.gmane.org 1344359072 1889 80.91.229.3 (7 Aug 2012 17:04:32 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Tue, 7 Aug 2012 17:04:32 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue Aug 07 19:04:33 2012 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1SynCo-00047f-Nz for ged-emacs-devel@m.gmane.org; Tue, 07 Aug 2012 19:04:31 +0200 Original-Received: from localhost ([::1]:45290 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SynCn-0006uW-U5 for ged-emacs-devel@m.gmane.org; Tue, 07 Aug 2012 13:04:29 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:35382) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SynCS-0006Oe-4l for emacs-devel@gnu.org; Tue, 07 Aug 2012 13:04:21 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SynCE-00074A-ML for emacs-devel@gnu.org; Tue, 07 Aug 2012 13:04:08 -0400 Original-Received: from dancol.org ([96.126.100.184]:38268) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SynCE-00070m-7w for emacs-devel@gnu.org; Tue, 07 Aug 2012 13:03:54 -0400 Original-Received: from dancol by dancol.org with local (Exim 4.72) (envelope-from ) id 1SynCC-0007XU-OK for emacs-devel@gnu.org; Tue, 07 Aug 2012 10:03:52 -0700 In-Reply-To: X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 96.126.100.184 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:152262 Archived-At: subword-mode began life as part of cc-mode, but because it's generally useful, it was extracted and made a generic part of Emacs. subword-mode uses command remapping to achive its subword motion, however, and this mechanism can't catch all kinds of word- based motion, resulting in inconsistency. capitalized-words-mode attempts to do what subword-mode does, but using a hook added to C core for the purpose. This hook allows capitalizd-words-mode to change all kinds of word-based motion into subword motion. Unfortunately, capitalized-words-mode used overly simplistic code that caused it to fail to properly move over words like "fooBarBAZ"; subword-mode handles these words properly. capitalized-words-mode is also disadvantaged by a long and misleading name. This patch merges subword-mode and capitalized-words-mode by modifying subword-mode to use the core hook and marking capitalized-words-mode as an obsolete alias for subword-mode. This patch also includes an automated test for subword motion. --- lisp/progmodes/cap-words.el | 98 ------------------------------------------- lisp/progmodes/subword.el | 88 +++++++++++++++++++++----------------- test/automated/subword.el | 58 +++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 138 deletions(-) delete mode 100644 lisp/progmodes/cap-words.el create mode 100644 test/automated/subword.el diff --git a/lisp/progmodes/cap-words.el b/lisp/progmodes/cap-words.el deleted file mode 100644 index 6d4d9f0..0000000 --- a/lisp/progmodes/cap-words.el +++ /dev/null @@ -1,98 +0,0 @@ -;;; cap-words.el --- minor mode for motion in CapitalizedWordIdentifiers - -;; Copyright (C) 2002-2012 Free Software Foundation, Inc. - -;; Author: Dave Love -;; 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 . - -;;; 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 diff --git a/lisp/progmodes/subword.el b/lisp/progmodes/subword.el index 7d8dd43..735beb0 100644 --- a/lisp/progmodes/subword.el +++ b/lisp/progmodes/subword.el @@ -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-2012 Free Software Foundation, Inc. @@ -25,8 +25,11 @@ ;; 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. +;; (`subword-mode') that changes the definition of a "word" so that +;; Emacs will see subword bounaries as word boundaries in normal +;; movement commands. Previously, `subword-mode' substituted the +;; normal word-movement commands with the subword-oriented versions at +;; the keymap level. ;; In spite of GNU Coding Standards, it is popular to name a symbol by ;; mixing uppercase and lowercase letters, e.g. "GtkWidget", @@ -45,25 +48,6 @@ ;; subwords in a nomenclature to move between them and to edit them as ;; words. -;; 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 -;; ============================================================ -;; 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: ;; @@ -76,22 +60,29 @@ ;; the old `c-forward-into-nomenclature' originally contributed by ;; Terry_Glanfield dot Southern at rxuk dot xerox dot com. -;; TODO: ispell-word. - ;;; Code: (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)) - (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) + ;; Leave an empty keymap present so user customization that modify + ;; it keep working. + (make-sparse-keymap) "Keymap used in `subword-mode' minor mode.") +(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'.") + +(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.") + +;;;###autoload +(define-obsolete-function-alias + 'capitalized-words-mode 'subword-mode "24.1") + ;;;###autoload (define-minor-mode subword-mode "Toggle subword movement and editing (Subword mode). @@ -99,8 +90,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\". @@ -114,14 +105,19 @@ 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. +When this mode is enabled, word-oriented commands recognize +subwords in a nomenclature to move between subwords and treat +them as words. \\{subword-mode-map}" nil nil - subword-mode-map) + subword-mode-map + + (set (make-local-variable 'find-word-boundary-function-table) + (if subword-mode + subword-find-word-boundary-function-table + subword-empty-char-table))) (define-obsolete-function-alias 'c-subword-mode 'subword-mode "23.2") @@ -261,7 +257,6 @@ Optional argument ARG is the same as for `capitalize-word'." (match-end 0)))) (forward-word 1))) - (defun subword-backward-internal () (if (save-excursion (let ((case-fold-search nil)) @@ -280,6 +275,19 @@ Optional argument ARG is the same as for `capitalize-word'." (1+ (match-beginning 0))))) (backward-word 1))) +(defun subword-find-word-boundary (pos limit) + (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) + (subword-forward-internal)) + (narrow-to-region limit (point-max)) + (subword-backward-internal)) + (point)))))) + (provide 'subword) diff --git a/test/automated/subword.el b/test/automated/subword.el new file mode 100644 index 0000000..9e769cf --- /dev/null +++ b/test/automated/subword.el @@ -0,0 +1,58 @@ +;;; vc-bzr.el --- tests for progmodes/subword.el + +;; Copyright (C) 2011 Free Software Foundation, Inc. + +;; Author: Daniel Colascione + +;; 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 . + +;;; Commentary: + +;;; Code: + +(require 'ert) +(require 'subword) + +(ert-deftest subword-test-forward () + "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)))))) -- 1.7.2.5