├── .gitignore ├── .travis.yml ├── HISTORY.org ├── README.org ├── string-inflection.el └── test └── string-inflection-test.el /.gitignore: -------------------------------------------------------------------------------- 1 | /*.html 2 | ert.* 3 | *.elc 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: emacs-lisp 2 | env: 3 | - EMACS=emacs24 4 | - EMACS=emacs-snapshot 5 | matrix: 6 | allow_failures: 7 | - env: EMACS=emacs-snapshot 8 | before_install: 9 | # Install Emacs 10 | - sudo add-apt-repository -y ppa:cassou/emacs 11 | - sudo add-apt-repository -y ppa:ubuntu-elisp 12 | - sudo apt-get update -qq 13 | - sudo apt-get install -qq $EMACS 14 | # # Install Cask 15 | # - curl -fsSkL --max-time 10 --retry 10 --retry-delay 10 16 | # https://raw.github.com/cask/cask/master/go | python 17 | # - export PATH="$HOME/.cask/bin:$PATH" 18 | # - cask 19 | script: 20 | $EMACS --script test/string-inflection-test.el 21 | -------------------------------------------------------------------------------- /HISTORY.org: -------------------------------------------------------------------------------- 1 | * HISTORY 2 | 3 | ** Version 1.1.0 4 | 5 | - Support non ascii [[https://github.com/akicho8/string-inflection/pull/39][#39]] 6 | - Use (bounds-of-thing-at-point) for word detection [[https://github.com/akicho8/string-inflection/pull/41][#41]] 7 | - Implement string-inflect-final-position [[https://github.com/akicho8/string-inflection/pull/43][#43]] 8 | 9 | =string-inflection-skip-backward-when-done= is deprecated. 10 | Use the =string-inflection-final-position= option instead. 11 | However, leaving it as the default seems to be the easiest to use. 12 | 13 | Previously, the rule for identifying words was shared across all modes. However, with this recent change, we have adapted the word boundaries to reflect the specifics of each mode. As a result, we have eliminated the need for handling edge cases, allowing for simpler and more flexible transformations. 14 | 15 | On the other hand, there are now cases where the range considered as a "word" has become too broad, leading to situations where the intended transformation does not occur. For example, in org-mode, when you try to transform only the "foo_bar" portion of "path/to/foo_bar.txt" by placing the cursor over it, nothing happens. In such cases, you can achieve a partial transformation by selecting "foo_bar" as a range. 16 | 17 | ** Version 1.0.16 18 | 19 | Fix [[https://github.com/akicho8/string-inflection/issues/34][#34]] kebabing a region can insert an unexpected hyphen 20 | 21 | add =string-inflection-erase-chars-when-region= variable 22 | 23 | Changed behavior when selecting region. 24 | 25 | #+BEGIN_SRC 26 | before: Foo::Bar --> foo_bar 27 | after: Foo::Bar --> foo::bar 28 | #+END_SRC 29 | 30 | Include =:= in =string-inflection-erase-chars-when-region= if want to behave as before. 31 | 32 | ** Version 1.0.14 33 | 34 | Merged [[https://github.com/akicho8/string-inflection/pull/32][PR #32]] Use defcustom and Change Some Wording 35 | 36 | ** Version 1.0.13 37 | 38 | Fix [[https://github.com/akicho8/string-inflection/issues/31][#31]] Better Whitespace Handling When Converting a Region 39 | 40 | ** Version 1.0.12 41 | 42 | Fix [[https://github.com/akicho8/string-inflection/issues/30][#30]] string-inflection-underscore affects C++ method accessors 43 | 44 | #+BEGIN_SRC 45 | before: fooBar->method --> foo_bar_>method 46 | after: fooBar->method --> foo_bar->method 47 | #+END_SRC 48 | 49 | ** Version 1.0.11 50 | 51 | Merged [[https://github.com/akicho8/string-inflection/pull/28][PR #28]] Make string-inflection-get-current-word work more sensibly when transient mark mode is off 52 | 53 | ** Version 1.0.10 54 | 55 | Merged [[https://github.com/akicho8/string-inflection/pull/26][PR #26]] Add `Capital_Underscore_Form` 56 | 57 | add string-inflection-capital-underscore function 58 | 59 | The behavior of =string-inflection-all-cycle= has changed 60 | 61 | #+BEGIN_SRC 62 | before: foo_bar => FOO_BAR => FooBar => fooBar => foo-bar => foo_bar 63 | after: foo_bar => FOO_BAR => FooBar => fooBar => foo-bar => Foo_Bar => foo_bar 64 | #+END_SRC 65 | 66 | ** Version 1.0.9 67 | 68 | Bugfix [[https://github.com/akicho8/string-inflection/issues/27][issue #25]] When executing kebab-case etc., point advances to the next word, and the previous word can not be converted continuously 69 | 70 | ** Version 1.0.8 71 | 72 | [[https://github.com/akicho8/string-inflection/issues/25][issue #25]] 73 | 74 | When it is simply =camelcase=, it means the name with the leading letters in lowercase. 75 | 76 | The name with the initial capital letter is called the =pascal-case=. 77 | 78 | *** Behavior of the camelcase function has changed 79 | 80 | | Before | After | 81 | |--------+--------| 82 | | FooBar | fooBar | 83 | 84 | *** Function name changed as well 85 | 86 | | Before | After | 87 | |-----------------+-------------| 88 | | camelcase | pascal-case | 89 | | lower-camelcase | camelcase | 90 | 91 | *** Add alias 92 | 93 | #+BEGIN_SRC elisp 94 | (fset 'string-inflection-upper-camelcase-function 'string-inflection-pascal-case-function) 95 | (fset 'string-inflection-lower-camelcase-function 'string-inflection-camelcase-function) 96 | 97 | (fset 'string-inflection-upper-camelcase-p 'string-inflection-pascal-case-p) 98 | (fset 'string-inflection-lower-camelcase-p 'string-inflection-camelcase-p) 99 | #+END_SRC 100 | 101 | *** Remove camelize function 102 | 103 | Originally we had defined functions of both =camelcase= and =camelize= names. 104 | 105 | I deleted the function containing =camelize= to make it simple. 106 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | * underscore -> UPCASE -> CamelCase conversion of names 2 | 3 | #+html: 4 | #+html:
5 | #+html:
6 | 7 | [[https://github.com/akicho8/string-inflection/blob/master/HISTORY.org][Change History]] 8 | 9 | ** Configuration Examples 10 | 11 | *** Example 1 12 | 13 | #+BEGIN_SRC elisp 14 | (require 'string-inflection) 15 | 16 | ;; C-q C-u is similar to the keybinding used by Vz Editor. 17 | (global-unset-key (kbd "C-q")) 18 | (global-set-key (kbd "C-q C-u") 'my-string-inflection-cycle-auto) 19 | 20 | (defun my-string-inflection-cycle-auto () 21 | "switching by major-mode" 22 | (interactive) 23 | (cond 24 | ;; for emacs-lisp-mode 25 | ((eq major-mode 'emacs-lisp-mode) 26 | (string-inflection-all-cycle)) 27 | ;; for python 28 | ((eq major-mode 'python-mode) 29 | (string-inflection-python-style-cycle)) 30 | ;; for java 31 | ((eq major-mode 'java-mode) 32 | (string-inflection-java-style-cycle)) 33 | ;; for elixir 34 | ((eq major-mode 'elixir-mode) 35 | (string-inflection-elixir-style-cycle)) 36 | (t 37 | ;; default 38 | (string-inflection-ruby-style-cycle)))) 39 | #+END_SRC 40 | 41 | *** Example 2 42 | 43 | #+BEGIN_SRC elisp 44 | (require 'string-inflection) 45 | 46 | ;; default 47 | (global-set-key (kbd "C-c C-u") 'string-inflection-all-cycle) 48 | 49 | ;; for ruby 50 | (add-hook 'ruby-mode-hook 51 | '(lambda () 52 | (local-set-key (kbd "C-c C-u") 'string-inflection-ruby-style-cycle))) 53 | 54 | ;; for elixir 55 | (add-hook 'elixir-mode-hook 56 | '(lambda () 57 | (local-set-key (kbd "C-c C-u") 'string-inflection-elixir-style-cycle))) 58 | 59 | ;; for java 60 | (add-hook 'java-mode-hook 61 | '(lambda () 62 | (local-set-key (kbd "C-c C-u") 'string-inflection-java-style-cycle))) 63 | 64 | ;; for python 65 | (add-hook 'python-mode-hook 66 | '(lambda () 67 | (local-set-key (kbd "C-c C-u") 'string-inflection-python-style-cycle))) 68 | 69 | #+END_SRC 70 | 71 | ** How to Use 72 | 73 | For each of the following, place the cursor at =emacs_lisp= and type =C-q C-u=, the results will be as follows: 74 | 75 | In the case of =string-inflection-ruby-style-cycle= 76 | 77 | : emacs_lisp => EMACS_LISP => EmacsLisp => emacs_lisp 78 | 79 | In the case of =string-inflection-elixir-style-cycle= 80 | 81 | : emacs_lisp => EmacsLisp => emacs_lisp 82 | 83 | In the case of =string-inflection-python-style-cycle= 84 | 85 | : emacs_lisp => EMACS_LISP => EmacsLisp => emacs_lisp 86 | 87 | In the case of =string-inflection-java-style-cycle= 88 | 89 | : emacsLisp => EMACS_LISP => EmacsLisp => emacsLisp 90 | 91 | In the case of =string-inflection-all-cycle= 92 | 93 | : emacs_lisp => EMACS_LISP => EmacsLisp => emacsLisp => emacs-lisp => Emacs_Lisp => emacs_lisp 94 | 95 | It is recommended that the major mode functions are used instead of =string-inflection-all-cycle=. 96 | 97 | ** Standalone Functions 98 | 99 | #+BEGIN_SRC elisp 100 | (string-inflection-underscore-function "EmacsLisp") ; => "emacs_lisp" 101 | (string-inflection-pascal-case-function "emacs_lisp") ; => "EmacsLisp" 102 | (string-inflection-camelcase-function "emacs_lisp") ; => "emacsLisp" 103 | (string-inflection-upcase-function "emacs_lisp") ; => "EMACS_LISP" 104 | (string-inflection-kebab-case-function "emacs_lisp") ; => "emacs-lisp" 105 | (string-inflection-capital-underscore-function "emacs_lisp") ; => "Emacs_Lisp" 106 | 107 | (string-inflection-pascal-case-p "EmacsLisp") ; => t 108 | (string-inflection-pascal-case-p "emacs_lisp") ; => nil 109 | ; etc... 110 | #+END_SRC 111 | 112 | ** Region usage 113 | 114 | You can also use this library to convert a region's casing. That applies the 115 | operation to all symbols of the region. If a symbol is only partially covered 116 | by the region, the operation is performed only on that part. 117 | 118 | For that, simply select a region and perform =M-x string-inflection-kebab-case= (or any such other function). 119 | 120 | ** Other configuration options 121 | 122 | You can configure where the cursor shall finish after the inflection operation 123 | using the =string-inflection-final-position= customization option. 124 | -------------------------------------------------------------------------------- /string-inflection.el: -------------------------------------------------------------------------------- 1 | ;;; string-inflection.el --- underscore -> UPCASE -> CamelCase -> lowerCamelCase conversion of names -*- lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2004,2014,2016,2017,2018,2020,2021,2022,2023,2024 Free Software Foundation, Inc. 4 | 5 | ;; Author: akicho8 6 | ;; Keywords: elisp 7 | ;; Version: 1.1.0 8 | 9 | ;; This file is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation; either version 2, or (at your option) 12 | ;; any later version. 13 | 14 | ;; This file is distributed in the hope that it will be useful, 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 20 | ;; along with GNU Emacs; see the file COPYING. If not, write to 21 | ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 22 | ;; Boston, MA 02111-1307, USA. 23 | 24 | ;;; Commentary: 25 | 26 | ;; There are three main functions: 27 | ;; 28 | ;; 1. For Ruby -> string-inflection-ruby-style-cycle (foo_bar => FOO_BAR => FooBar => foo_bar) 29 | ;; 2. For Elixir -> string-inflection-elixir-style-cycle (foo_bar => FooBar => foo_bar) 30 | ;; 3. For Python -> string-inflection-python-style-cycle (foo_bar => FOO_BAR => FooBar => foo_bar) 31 | ;; 4. For Java -> string-inflection-java-style-cycle (fooBar => FOO_BAR => FooBar => fooBar) 32 | ;; 5. For All -> string-inflection-all-cycle (foo_bar => FOO_BAR => FooBar => fooBar => foo-bar => Foo_Bar => foo_bar) 33 | ;; 34 | ;; 35 | ;; Example 1: 36 | ;; 37 | ;; (require 'string-inflection) 38 | ;; (global-unset-key (kbd "C-q")) 39 | ;; ;; C-q C-u is the key bindings similar to Vz Editor. 40 | ;; (global-set-key (kbd "C-q C-u") 'my-string-inflection-cycle-auto) 41 | ;; 42 | ;; (defun my-string-inflection-cycle-auto () 43 | ;; "switching by major-mode" 44 | ;; (interactive) 45 | ;; (cond 46 | ;; ;; for emacs-lisp-mode 47 | ;; ((eq major-mode 'emacs-lisp-mode) 48 | ;; (string-inflection-all-cycle)) 49 | ;; ;; for java 50 | ;; ((eq major-mode 'java-mode) 51 | ;; (string-inflection-java-style-cycle)) 52 | ;; ;; for python 53 | ;; ((eq major-mode 'python-mode) 54 | ;; (string-inflection-python-style-cycle)) 55 | ;; ;; for elixir 56 | ;; ((eq major-mode 'elixir-mode) 57 | ;; (string-inflection-elixir-style-cycle)) 58 | ;; (t 59 | ;; ;; default 60 | ;; (string-inflection-ruby-style-cycle)))) 61 | ;; 62 | ;; 63 | ;; Example 2: 64 | ;; 65 | ;; (require 'string-inflection) 66 | ;; 67 | ;; ;; default 68 | ;; (global-set-key (kbd "C-c C-u") 'string-inflection-all-cycle) 69 | ;; 70 | ;; ;; for ruby 71 | ;; (add-hook 'ruby-mode-hook 72 | ;; '(lambda () 73 | ;; (local-set-key (kbd "C-c C-u") 'string-inflection-ruby-style-cycle))) 74 | ;; 75 | ;; ;; for elixir 76 | ;; (add-hook 'elixir-mode-hook 77 | ;; '(lambda () 78 | ;; (local-set-key (kbd "C-c C-u") 'string-inflection-elixir-style-cycle))) 79 | ;; 80 | ;; ;; for python 81 | ;; (add-hook 'python-mode-hook 82 | ;; '(lambda () 83 | ;; (local-set-key (kbd "C-c C-u") 'string-inflection-python-style-cycle))) 84 | ;; 85 | ;; ;; for java 86 | ;; (add-hook 'java-mode-hook 87 | ;; '(lambda () 88 | ;; (local-set-key (kbd "C-c C-u") 'string-inflection-java-style-cycle))) 89 | ;; 90 | ;; You can configure where the cursor should end up after the inflection using the 91 | ;; `string-inflection-final-position' option. 92 | ;; 93 | ;; When a region is active during the inflect operation there are two effects: 94 | ;; 95 | ;; * If the region marks a part of a symbol the operation is only performed on that 96 | ;; part. 97 | ;; * If the region contains more than one symbols, the operation is performed on all 98 | ;; the symbols in the region. 99 | ;; * The region is preserved after the operation. 100 | 101 | ;;; Code: 102 | 103 | (defgroup string-inflection nil 104 | "Change the casing of words." 105 | :group 'convenience) 106 | 107 | (defcustom string-inflection-final-position 'remain 108 | "Where to finish after the inflection. 109 | This can be `remain' – remain at the initial position but not beyond the end of the inflected string –, 110 | `beginning' – jump to the beginning of the inflection – or 111 | `end' – jump to the end of the inflection." 112 | :group 'string-inflection 113 | :type '(choice (const remain) (const beginning) (const end))) 114 | 115 | ;; -------------------------------------------------------------------------------- 116 | 117 | ;;;###autoload 118 | (defun string-inflection-ruby-style-cycle () 119 | "foo_bar => FOO_BAR => FooBar => foo_bar" 120 | (interactive) 121 | (string-inflection--single-or-region #'string-inflection-ruby-style-cycle-function)) 122 | 123 | (fset 'string-inflection-cycle 'string-inflection-ruby-style-cycle) 124 | 125 | ;;;###autoload 126 | (defun string-inflection-elixir-style-cycle () 127 | "foo_bar => FooBar => foo_bar" 128 | (interactive) 129 | (string-inflection--single-or-region #'string-inflection-elixir-style-cycle-function)) 130 | 131 | ;;;###autoload 132 | (defun string-inflection-python-style-cycle () 133 | "foo_bar => FOO_BAR => FooBar => foo_bar" 134 | (interactive) 135 | (string-inflection--single-or-region #'string-inflection-python-style-cycle-function)) 136 | 137 | ;;;###autoload 138 | (defun string-inflection-java-style-cycle () 139 | "fooBar => FOO_BAR => FooBar => fooBar" 140 | (interactive) 141 | (string-inflection--single-or-region #'string-inflection-java-style-cycle-function)) 142 | 143 | ;;;###autoload 144 | (defun string-inflection-all-cycle () 145 | "foo_bar => FOO_BAR => FooBar => fooBar => foo-bar => Foo_Bar => foo_bar" 146 | (interactive) 147 | (string-inflection--single-or-region #'string-inflection-all-cycle-function)) 148 | 149 | ;;;###autoload 150 | (defun string-inflection-toggle () 151 | "toggle foo_bar <=> FooBar" 152 | (interactive) 153 | (string-inflection--single-or-region #'string-inflection-toggle-function)) 154 | 155 | ;;;###autoload 156 | (defun string-inflection-camelcase () 157 | "FooBar format" 158 | (interactive) 159 | (string-inflection--single-or-region #'string-inflection-pascal-case-function)) 160 | 161 | ;;;###autoload 162 | (defun string-inflection-lower-camelcase () 163 | "fooBar format" 164 | (interactive) 165 | (string-inflection--single-or-region #'string-inflection-camelcase-function)) 166 | 167 | ;;;###autoload 168 | (defun string-inflection-underscore () 169 | "foo_bar format" 170 | (interactive) 171 | (string-inflection--single-or-region #'string-inflection-underscore-function)) 172 | 173 | ;;;###autoload 174 | (defun string-inflection-capital-underscore () 175 | "Foo_Bar format" 176 | (interactive) 177 | (string-inflection--single-or-region #'string-inflection-capital-underscore-function)) 178 | 179 | ;;;###autoload 180 | (defun string-inflection-upcase () 181 | "FOO_BAR format" 182 | (interactive) 183 | (string-inflection--single-or-region #'string-inflection-upcase-function)) 184 | 185 | ;;;###autoload 186 | (defun string-inflection-kebab-case () 187 | "foo-bar format" 188 | (interactive) 189 | (string-inflection--single-or-region #'string-inflection-kebab-case-function)) 190 | 191 | (fset 'string-inflection-lisp 'string-inflection-kebab-case) 192 | 193 | ;; -------------------------------------------------------------------------------- 194 | 195 | (defun string-inflection--count-symbols-between-start-and-end (start end) 196 | "Count the symbols between START and END." 197 | (let ((symbol-num 0)) 198 | (goto-char start) 199 | (save-excursion 200 | (while (< (point) end) 201 | (setq symbol-num (1+ symbol-num)) 202 | (forward-symbol 1))) 203 | symbol-num)) 204 | 205 | (defun string-inflection--single-or-region (inflect-func) 206 | "Perform INFLECT-FUNC depending on if in region or single." 207 | (if (use-region-p) 208 | (string-inflection--region inflect-func) 209 | (string-inflection--single inflect-func))) 210 | 211 | (defun string-inflection--single (inflect-func) 212 | "Perform INFLECT-FUNC for a single occurrence." 213 | (let ((orig-point (point))) 214 | (insert (funcall inflect-func (string-inflection-get-current-word))) 215 | (pcase string-inflection-final-position 216 | ('remain (goto-char (min orig-point (cdr (bounds-of-thing-at-point 'symbol))))) 217 | ('beginning (goto-char (car (bounds-of-thing-at-point 'symbol))))))) 218 | 219 | (defun string-inflection--region (inflect-func) 220 | "Perform INFLECT-FUNC for all occurrences in the region." 221 | (let ((orig-point (point)) 222 | (start (region-beginning)) 223 | (end (region-end))) 224 | (dotimes (_ (string-inflection--count-symbols-between-start-and-end start end)) 225 | (let ((orig-length (length (symbol-name (symbol-at-point))))) 226 | (insert (funcall inflect-func (string-inflection-get-current-word-limited-by start end))) 227 | (setq end (+ end (- (length (symbol-name (symbol-at-point))) orig-length))) 228 | (forward-symbol 1) 229 | (if-let* ((bounds (bounds-of-thing-at-point 'symbol))) 230 | (goto-char (car bounds))))) 231 | (let ((new-region 232 | (pcase string-inflection-final-position 233 | ('remain (if (/= orig-point start) (cons start end) (cons end start))) 234 | ('beginning (cons end start)) 235 | ('end (cons start end))))) 236 | (set-mark (car new-region)) 237 | (goto-char (cdr new-region))) 238 | (activate-mark) 239 | (setq deactivate-mark nil))) 240 | 241 | (defun string-inflection-get-current-word () 242 | "Gets the symbol near the cursor" 243 | (interactive) 244 | (if-let* ((bounds (bounds-of-thing-at-point 'symbol)) 245 | (start (car bounds)) 246 | (end (cdr bounds)) 247 | (str (buffer-substring start end))) 248 | (progn 249 | (delete-region start end) 250 | str) 251 | "")) 252 | 253 | (defun string-inflection-get-current-word-limited-by (reg-start reg-end) 254 | "Gets the symbol near the cursor limited by REG-START and REG-END." 255 | (interactive) 256 | (if-let* ((bounds (bounds-of-thing-at-point 'symbol)) 257 | (start (max (car bounds) reg-start)) 258 | (end (min (cdr bounds) reg-end)) 259 | (str (buffer-substring start end))) 260 | (progn 261 | (delete-region start end) 262 | str) 263 | "")) 264 | 265 | ;; -------------------------------------------------------------------------------- 266 | 267 | (defun string-inflection-pascal-case-function (str) 268 | "foo_bar => FooBar" 269 | (setq str (string-inflection-underscore-function str)) 270 | (mapconcat 'capitalize (split-string str "_") "")) 271 | 272 | (fset 'string-inflection-upper-camelcase-function 'string-inflection-pascal-case-function) 273 | 274 | (defun string-inflection-camelcase-function (str) 275 | "foo_bar => fooBar" 276 | (setq str (split-string (string-inflection-underscore-function str) "_")) 277 | (concat (downcase (car str)) 278 | (mapconcat 'capitalize (cdr str) ""))) 279 | 280 | (fset 'string-inflection-lower-camelcase-function 'string-inflection-camelcase-function) 281 | 282 | (defun string-inflection-upcase-function (str) 283 | "FooBar => FOO_BAR" 284 | (upcase (string-inflection-underscore-function str))) 285 | 286 | (defun string-inflection-underscore-function (str) 287 | "FooBar => foo_bar" 288 | (let ((case-fold-search nil)) 289 | (setq str (replace-regexp-in-string "\\([[:lower:][:digit:]]\\)\\([[:upper:]]\\)" "\\1_\\2" str)) 290 | (setq str (replace-regexp-in-string "\\([[:upper:]]+\\)\\([[:upper:]][[:lower:]]\\)" "\\1_\\2" str)) 291 | (setq str (replace-regexp-in-string "-" "_" str)) ; FOO-BAR => FOO_BAR 292 | (setq str (replace-regexp-in-string "_+" "_" str)) 293 | (downcase str))) 294 | 295 | (defun string-inflection-capital-underscore-function (str) 296 | "foo_bar => Foo_Bar" 297 | (setq str (string-inflection-underscore-function str)) 298 | (mapconcat 'capitalize (split-string str "_") "_")) 299 | 300 | (defun string-inflection-kebab-case-function (str) 301 | "foo_bar => foo-bar" 302 | (let ((case-fold-search nil)) 303 | (setq str (string-inflection-underscore-function str)) 304 | (setq str (replace-regexp-in-string "_" "-" str)))) 305 | 306 | (defun string-inflection-all-cycle-function (str) 307 | "foo_bar => FOO_BAR => FooBar => fooBar => foo-bar => Foo_Bar => foo_bar 308 | foo => FOO => Foo => foo" 309 | (cond 310 | ;; foo => FOO 311 | ((string-inflection-word-p str) 312 | (string-inflection-upcase-function str)) 313 | ;; foo_bar => FOO_BAR 314 | ((string-inflection-underscore-p str) 315 | (string-inflection-upcase-function str)) 316 | ;; FOO_BAR => FooBar 317 | ((string-inflection-upcase-p str) 318 | (string-inflection-pascal-case-function str)) 319 | ;; FooBar => fooBar 320 | ;; Foo => foo 321 | ((string-inflection-pascal-case-p str) 322 | (string-inflection-camelcase-function str)) 323 | ;; fooBar => foo-bar 324 | ((string-inflection-camelcase-p str) 325 | (string-inflection-kebab-case-function str)) 326 | ;; foo-bar => Foo_Bar 327 | ((string-inflection-kebab-case-p str) 328 | (string-inflection-capital-underscore-function str)) 329 | ;; foo-bar => foo_bar 330 | (t 331 | (string-inflection-underscore-function str)))) 332 | 333 | (defun string-inflection-ruby-style-cycle-function (str) 334 | "foo_bar => FOO_BAR => FooBar => foo_bar" 335 | (cond 336 | ((string-inflection-underscore-p str) 337 | (string-inflection-upcase-function str)) 338 | ((string-inflection-upcase-p str) 339 | (string-inflection-pascal-case-function str)) 340 | (t 341 | (string-inflection-underscore-function str)))) 342 | 343 | (defalias 'string-inflection-python-style-cycle-function 344 | 'string-inflection-ruby-style-cycle-function) 345 | 346 | (defun string-inflection-elixir-style-cycle-function (str) 347 | "foo_bar => FooBar => foo_bar" 348 | (cond 349 | ((string-inflection-underscore-p str) 350 | (string-inflection-pascal-case-function str)) 351 | (t 352 | (string-inflection-underscore-function str)))) 353 | 354 | (defun string-inflection-java-style-cycle-function (str) 355 | "fooBar => FOO_BAR => FooBar => fooBar" 356 | (cond 357 | ((string-inflection-underscore-p str) 358 | (string-inflection-upcase-function str)) 359 | ((string-inflection-camelcase-p str) 360 | (string-inflection-upcase-function str)) 361 | ((string-inflection-upcase-p str) 362 | (string-inflection-pascal-case-function str)) 363 | (t 364 | (string-inflection-camelcase-function str)))) 365 | 366 | ;; Toggle function. But cycle function. 367 | (defun string-inflection-toggle-function (str) 368 | "Not so much the case that in all caps when using normal foo_bar <--> FooBar" 369 | (cond 370 | ((string-inflection-underscore-p str) 371 | (string-inflection-pascal-case-function str)) 372 | ((string-inflection-pascal-case-p str) 373 | (string-inflection-camelcase-function str)) 374 | (t 375 | (string-inflection-underscore-function str)))) 376 | 377 | ;; -------------------------------------------------------------------------------- 378 | 379 | (defun string-inflection-word-p (str) 380 | "if foo => t" 381 | (let ((case-fold-search nil)) 382 | (string-match "\\`[[:lower:][:digit:]]+\\'" str))) 383 | 384 | (defun string-inflection-underscore-p (str) 385 | "if foo_bar => t" 386 | (let ((case-fold-search nil)) 387 | (string-match "\\`[[:lower:][:digit:]_]+\\'" str))) 388 | 389 | (defun string-inflection-upcase-p (str) 390 | "if FOO_BAR => t" 391 | (let ((case-fold-search nil)) 392 | (string-match "\\`[[:upper:][:digit:]_]+\\'" str))) 393 | 394 | (defun string-inflection-pascal-case-p (str) 395 | "if FooBar => t" 396 | (let ((case-fold-search nil)) 397 | (and 398 | (string-match "[[:lower:]]" str) 399 | (string-match "\\`[[:upper:]][[:lower:][:upper:][:digit:]]+\\'" str)))) 400 | 401 | (fset 'string-inflection-upper-camelcase-p 'string-inflection-pascal-case-p) 402 | 403 | (defun string-inflection-camelcase-p (str) 404 | "if fooBar => t" 405 | (let ((case-fold-search nil)) 406 | (and 407 | (string-match "[[:upper:]]" str) 408 | (string-match "\\`[[:lower:]][[:lower:][:upper:][:digit:]]+\\'" str)))) 409 | 410 | (fset 'string-inflection-lower-camelcase-p 'string-inflection-camelcase-p) 411 | 412 | (defun string-inflection-kebab-case-p (str) 413 | "if foo-bar => t" 414 | (string-match "-" str)) 415 | 416 | (defun string-inflection-capital-underscore-p (str) 417 | "if Foo_Bar => t" 418 | (let ((case-fold-search nil)) 419 | (and 420 | (string-match "_" str) 421 | (string-match "\\`[[:upper:]][[:lower:][:upper:][:digit:]_]+\\'" str)))) 422 | 423 | (provide 'string-inflection) 424 | ;;; string-inflection.el ends here 425 | -------------------------------------------------------------------------------- /test/string-inflection-test.el: -------------------------------------------------------------------------------- 1 | ;; -*- compile-command: "emacs --script string-inflection-test.el" -*- 2 | 3 | (setq load-path (cons ".." load-path)) 4 | (setq load-path (cons "." load-path)) 5 | 6 | (require 'string-inflection) 7 | 8 | (require 'ert) 9 | 10 | ;; -------------------------------------------------------------------------------- cycle function 11 | 12 | (ert-deftest test-ruby-style-cycle () 13 | (should (equal "FOO_BAR" (string-inflection-ruby-style-cycle-function "foo_bar"))) 14 | (should (equal "FooBar" (string-inflection-ruby-style-cycle-function "FOO_BAR"))) 15 | (should (equal "foo_bar" (string-inflection-ruby-style-cycle-function "FooBar")))) 16 | 17 | (ert-deftest test-elixir-style-cycle () 18 | (should (equal "foo_bar" (string-inflection-elixir-style-cycle-function "FOO_BAR"))) 19 | (should (equal "FooBar" (string-inflection-elixir-style-cycle-function "foo_bar"))) 20 | (should (equal "foo_bar" (string-inflection-elixir-style-cycle-function "FooBar")))) 21 | 22 | (ert-deftest test-java-style-cycle () 23 | (should (equal "FOO_BAR" (string-inflection-java-style-cycle-function "foo_bar"))) 24 | (should (equal "FOO_BAR" (string-inflection-java-style-cycle-function "fooBar"))) 25 | (should (equal "FooBar" (string-inflection-java-style-cycle-function "FOO_BAR"))) 26 | (should (equal "fooBar" (string-inflection-java-style-cycle-function "FooBar")))) 27 | 28 | (ert-deftest test-all-cycle () 29 | (should (equal "FOO_BAR" (string-inflection-all-cycle-function "foo_bar"))) 30 | (should (equal "FooBar" (string-inflection-all-cycle-function "FOO_BAR"))) 31 | (should (equal "fooBar" (string-inflection-all-cycle-function "FooBar"))) 32 | (should (equal "fooBar" (string-inflection-all-cycle-function "FooBar"))) 33 | (should (equal "foo-bar" (string-inflection-all-cycle-function "fooBar"))) 34 | (should (equal "Foo_Bar" (string-inflection-all-cycle-function "foo-bar"))) 35 | (should (equal "foo_bar" (string-inflection-all-cycle-function "Foo_Bar")))) 36 | 37 | ; -------------------------------------------------------------------------------- 38 | 39 | (ert-deftest test-underscore () 40 | (should (equal "foo1_bar" (string-inflection-underscore-function "foo1_bar"))) 41 | (should (equal "foo1_bar" (string-inflection-underscore-function "FOO1_BAR"))) 42 | (should (equal "foo1bar" (string-inflection-underscore-function "foo1bar"))) 43 | (should (equal "foo1_bar" (string-inflection-underscore-function "foo1__bar"))) 44 | (should (equal "foo1_bar" (string-inflection-underscore-function "Foo1Bar"))) 45 | (should (equal "foo1_bar" (string-inflection-underscore-function "FOO1Bar"))) 46 | (should (equal "foo_bar" (string-inflection-underscore-function "FOO_BAR")))) 47 | 48 | (ert-deftest test-consecutive-uppercase () 49 | (should (equal "a_single_line" (string-inflection-underscore-function "ASingleLine"))) 50 | (should (equal "php_mode" (string-inflection-underscore-function "PHPMode"))) 51 | (should (equal "ends_with_php" (string-inflection-underscore-function "EndsWithPHP"))) 52 | (should (equal "php_and_xml_too" (string-inflection-underscore-function "PHPAndXMLToo"))) 53 | (should (equal "php_and_xml_too" (string-inflection-underscore-function "phpAndXmlToo"))) 54 | (should (equal "ph_pand_xm_ltoo" (string-inflection-underscore-function "PHPandXMLtoo"))) 55 | (should (equal "eĥo_ŝanĝo_ĉiu_ĵaŭde" (string-inflection-underscore-function "EĤOŜanĝoĈIUĴaŭde")))) 56 | 57 | (ert-deftest test-pascal-case () 58 | (should (equal "Foo1Bar" (string-inflection-pascal-case-function "Foo1Bar"))) 59 | (should (equal "Eĥo1Ŝanĝo" (string-inflection-pascal-case-function "Eĥo1Ŝanĝo"))) 60 | (should (equal "Foo1Bar" (string-inflection-pascal-case-function "FOO1_BAR"))) 61 | (should (equal "Eĥo1Ŝanĝo" (string-inflection-pascal-case-function "EĤO1_ŜANĜO"))) 62 | (should (equal "Foo1Bar" (string-inflection-pascal-case-function "FOO1__BAR"))) 63 | (should (equal "Eĥo1Ŝanĝo" (string-inflection-pascal-case-function "EĤO1__ŜANĜO"))) 64 | (should (equal "Foo" (string-inflection-pascal-case-function "foo"))) 65 | (should (equal "Eĥo" (string-inflection-pascal-case-function "eĥo")))) 66 | 67 | (ert-deftest test-lower-camelcase () 68 | (should (equal "fooBar" (string-inflection-camelcase-function "FooBar"))) 69 | (should (equal "eĥoŜanĝo" (string-inflection-camelcase-function "EĥoŜanĝo"))) 70 | (should (equal "foo1Bar" (string-inflection-camelcase-function "FOO1BAR"))) 71 | (should (equal "eĥo1Ŝanĝo" (string-inflection-camelcase-function "EĤO1ŜANĜO")))) 72 | 73 | (ert-deftest test-kebab-case () 74 | (should (equal "foo-bar" (string-inflection-kebab-case-function "FooBar"))) 75 | (should (equal "eĥo-ŝanĝo" (string-inflection-kebab-case-function "EĥoŜanĝo")))) 76 | 77 | (ert-deftest test-toggle () 78 | (should (equal "FooBar" (string-inflection-toggle-function "foo_bar"))) 79 | (should (equal "EĥoŜanĝo" (string-inflection-toggle-function "eĥo_ŝanĝo"))) 80 | (should (equal "fooBar" (string-inflection-toggle-function "FooBar"))) 81 | (should (equal "eĥoŜanĝo" (string-inflection-toggle-function "EĥoŜanĝo"))) 82 | (should (equal "ĉirkaŭIro" (string-inflection-toggle-function "ĈirkaŭIro"))) 83 | (should (equal "foo_bar" (string-inflection-toggle-function "FOO_BAR"))) 84 | (should (equal "eĥo_ŝanĝo" (string-inflection-toggle-function "EĤO_ŜANĜO")))) 85 | 86 | (ert-deftest test-upcase () 87 | (should (equal "FOO1_BAR" (string-inflection-upcase-function "foo1_bar"))) 88 | (should (equal "EĤO1_ŜANĜO" (string-inflection-upcase-function "eĥo1_ŝanĝo"))) 89 | (should (equal "FOO1_BAR" (string-inflection-upcase-function "Foo1Bar"))) 90 | (should (equal "EĤO1_ŜANĜO" (string-inflection-upcase-function "Eĥo1Ŝanĝo"))) 91 | (should (equal "FOO_BAR" (string-inflection-upcase-function "Foo_bar"))) 92 | (should (equal "EĤO_ŜANĜO" (string-inflection-upcase-function "Eĥo_ŝanĝo")))) 93 | 94 | (ert-deftest test-capital-underscore () 95 | (should (equal "Foo1_Bar" (string-inflection-capital-underscore-function "foo1_bar"))) 96 | (should (equal "Eĥo1_Ŝanĝo" (string-inflection-capital-underscore-function "eĥo1_ŝanĝo"))) 97 | (should (equal "Foo1_Bar" (string-inflection-capital-underscore-function "FOO1_BAR"))) 98 | (should (equal "Eĥo1_Ŝanĝo" (string-inflection-capital-underscore-function "EĤO1_ŜANĜO"))) 99 | (should (equal "Foo1bar" (string-inflection-capital-underscore-function "foo1bar"))) 100 | (should (equal "Eĥo1ŝanĝo" (string-inflection-capital-underscore-function "eĥo1ŝanĝo"))) 101 | (should (equal "Foo1_Bar" (string-inflection-capital-underscore-function "foo1__bar"))) 102 | (should (equal "Eĥo1_Ŝanĝo" (string-inflection-capital-underscore-function "eĥo1__ŝanĝo"))) 103 | (should (equal "Foo1_Bar" (string-inflection-capital-underscore-function "Foo1Bar"))) 104 | (should (equal "Eĥo1_Ŝanĝo" (string-inflection-capital-underscore-function "Eĥo1Ŝanĝo"))) 105 | (should (equal "Foo1_Bar" (string-inflection-capital-underscore-function "FOO1Bar"))) 106 | (should (equal "Eĥo1_Ŝanĝo" (string-inflection-capital-underscore-function "EĤO1Ŝanĝo"))) 107 | (should (equal "Foo_Bar" (string-inflection-capital-underscore-function "FOO_BAR"))) 108 | (should (equal "Eĥo_Ŝanĝo" (string-inflection-capital-underscore-function "EĤO_ŜANĜO")))) 109 | 110 | ;; -------------------------------------------------------------------------------- 111 | 112 | (ert-deftest test-word-p () 113 | (should (string-inflection-word-p "foo")) 114 | (should (string-inflection-word-p "eĥo")) 115 | (should-not (string-inflection-word-p "foo_bar")) 116 | (should-not (string-inflection-word-p "eĥo_ŝanĝo"))) 117 | 118 | (ert-deftest test-underscore-p () 119 | (should (string-inflection-underscore-p "foo")) 120 | (should (string-inflection-underscore-p "eĥo")) 121 | (should (string-inflection-underscore-p "foo_bar")) 122 | (should (string-inflection-underscore-p "eĥo_ŝanĝo"))) 123 | 124 | (ert-deftest test-pascal-case-p () 125 | (should (string-inflection-pascal-case-p "Foo")) 126 | (should (string-inflection-pascal-case-p "Eĥo")) 127 | (should (string-inflection-pascal-case-p "FooBar")) 128 | (should (string-inflection-pascal-case-p "EĥoŜanĝo")) 129 | (should-not (string-inflection-pascal-case-p "FOO")) 130 | (should (string-inflection-pascal-case-p "Eĥĥ"))) 131 | 132 | (ert-deftest test-camelcase-p () 133 | (should-not (string-inflection-camelcase-p "foo")) 134 | (should-not (string-inflection-camelcase-p "eĥo")) 135 | (should (string-inflection-camelcase-p "fooBar")) 136 | (should (string-inflection-camelcase-p "eĥoŜanĝo"))) 137 | 138 | (ert-deftest test-lower-upcase-p () 139 | (should (string-inflection-upcase-p "FOO")) 140 | (should (string-inflection-upcase-p "EĤO")) 141 | (should (string-inflection-upcase-p "FOO_BAR")) 142 | (should (string-inflection-upcase-p "EĤO_ŜANĜO"))) 143 | 144 | (ert-deftest test-kebab-case-p () 145 | (should (string-inflection-kebab-case-p "foo-bar")) 146 | (should (string-inflection-kebab-case-p "eĥo-ŝanĝo"))) 147 | 148 | (ert-deftest test-capital-underscore-p () 149 | (should (string-inflection-capital-underscore-p "Foo_Bar")) 150 | (should (string-inflection-capital-underscore-p "Eĥo_Ŝanĝo"))) 151 | 152 | ;; -------------------------------------------------------------------------------- Target word of cursor position 153 | 154 | (defun buffer-try (str position &optional mode-func) 155 | (with-temp-buffer 156 | (funcall (or mode-func #'fundamental-mode)) 157 | (insert str) 158 | (goto-char (apply position)) 159 | (prog1 160 | (string-inflection-get-current-word) 161 | (kill-this-buffer)))) 162 | 163 | (ert-deftest test-get-current-word-on-cursor () 164 | (should (equal "foo" (buffer-try "foo" '(point-max)))) 165 | (should (equal "eĥo" (buffer-try "eĥo" '(point-max)))) 166 | (should (equal "foo" (buffer-try "foo" '(point-min)))) 167 | (should (equal "eĥo" (buffer-try "eĥo" '(point-min)))) 168 | (should (equal "" (buffer-try "" '(point-max)))) 169 | (should (equal "foo" (buffer-try "foo->bar" '(point-min) #'c-mode))) 170 | (should (equal "eĥo" (buffer-try "eĥo->ŝanĝo" '(point-min) #'c-mode))) 171 | (should (equal "foo-" (buffer-try "foo-" '(point-min)))) 172 | (should (equal "eĥo-" (buffer-try "eĥo-" '(point-min)))) 173 | (should (equal "foo" (buffer-try "foo-" '(point-min) #'python-mode))) 174 | (should (equal "eĥo" (buffer-try "eĥo-" '(point-min) #'python-mode))) 175 | ) 176 | 177 | ;; -------------------------------------------------------------------------------- Target all of region 178 | 179 | (defun region-try-inflect (str &optional inflect mode-func) 180 | (with-temp-buffer 181 | (funcall (or mode-func #'fundamental-mode)) 182 | (insert str) 183 | (set-mark (point-min)) 184 | (goto-char (point-max)) 185 | (activate-mark) 186 | (funcall (or inflect #'string-inflection-toggle)) 187 | (buffer-string))) 188 | 189 | (ert-deftest test-inflect-toggle-in-region () 190 | (should (equal "Foo" (region-try-inflect "foo"))) ; It was underscore when old version. 191 | (should (equal "Foo Bar" (region-try-inflect "foo bar"))) ; It was underscore when old version. 192 | (should (equal "Foo Bar Baz" (region-try-inflect "foo bar baz"))) 193 | (should (equal "FooBar BarFoo" (region-try-inflect "foo_bar bar_foo"))) 194 | (should (equal "Foo:Bar" (region-try-inflect "foo:bar"))) ; It was underscore when old version. 195 | (should (equal "Foo::Bar" (region-try-inflect "foo::bar"))) ; It was underscore when old version. 196 | (should (equal "Foo.Bar" (region-try-inflect "foo.bar"))) 197 | (should (equal "Foo().Bar" (region-try-inflect "foo().bar"))) 198 | (should (equal "Foo()->Bar" (region-try-inflect "foo()->bar" #'string-inflection-toggle #'c-mode))) 199 | ) 200 | 201 | (ert-deftest test-inflect-in-region () 202 | (should (equal "FooBar" (region-try-inflect "foo_bar" #'string-inflection-camelcase))) 203 | (should (equal "FooBar BarFoo" (region-try-inflect "foo_bar bar-foo" #'string-inflection-camelcase))) 204 | (should (equal "fooBar barFoo" (region-try-inflect "foo_bar bar-foo" #'string-inflection-lower-camelcase))) 205 | (should (equal "foo_bar bar_foo" (region-try-inflect "FooBar bar-foo" #'string-inflection-underscore))) 206 | (should (equal "Foo_Bar Bar_Foo" (region-try-inflect "FooBar bar-foo" #'string-inflection-capital-underscore))) 207 | (should (equal "FOO_BAR BAR_FOO" (region-try-inflect "FooBar bar-foo" #'string-inflection-upcase))) 208 | (should (equal "foo-bar bar-foo" (region-try-inflect "FooBar bar_foo" #'string-inflection-kebab-case))) 209 | 210 | ;; https://github.com/akicho8/string-inflection/issues/34 211 | (should (equal ":foo-bar bar" (region-try-inflect ":fooBar bar" #'string-inflection-kebab-case))) 212 | 213 | ;; https://github.com/akicho8/string-inflection/issues/31 214 | (should (equal "\nfoo_bar\nbar_foo\n" (region-try-inflect "\nFooBar\nbar-foo\n" #'string-inflection-underscore))) 215 | 216 | ;; https://github.com/akicho8/string-inflection/issues/30 217 | (should (equal "obj_name->meth_name\nobj1_name->meth1_name" 218 | (region-try-inflect "ObjName->MethName\nObj1Name->Meth1Name" #'string-inflection-underscore #'c++-mode))) 219 | ) 220 | 221 | (ert-deftest test-cycle-in-region () 222 | (should (equal "FOO_BAR FooBar foo_bar" 223 | (region-try-inflect "foo_bar FOO_BAR FooBar" #'string-inflection-ruby-style-cycle))) 224 | (should (equal "FooBar foo_bar" 225 | (region-try-inflect "foo_bar FooBar" #'string-inflection-elixir-style-cycle))) 226 | (should (equal "foo_bar FOO_BAR FooBar foo_bar" 227 | (region-try-inflect "fooBar foo_bar FOO_BAR FooBar" #'string-inflection-python-style-cycle))) 228 | (should (equal "FOO_BAR FooBar fooBar" 229 | (region-try-inflect "foo_bar FOO_BAR FooBar" #'string-inflection-java-style-cycle))) 230 | (should (equal "FOO_BAR FooBar fooBar foo-bar Foo_Bar foo_bar" 231 | (region-try-inflect "foo_bar FOO_BAR FooBar fooBar foo-bar Foo_Bar" #'string-inflection-all-cycle))) 232 | ) 233 | 234 | (defun buffer-try-inflect (str inflect) 235 | (with-temp-buffer 236 | (c-mode) 237 | (insert str) 238 | (goto-char (point-min)) 239 | (funcall inflect) 240 | (buffer-string))) 241 | 242 | (ert-deftest test-buffer-toggle () 243 | (should (equal "foo_bar" (buffer-try-inflect "fooBar" 'string-inflection-toggle)))) 244 | 245 | (ert-deftest test-buffer-underscore () 246 | ;; https://github.com/akicho8/string-inflection/issues/30 247 | (should (equal "object_name->method" (buffer-try-inflect "objectName->method" 'string-inflection-underscore))) 248 | (should (equal "object1_name->method" (buffer-try-inflect "object1Name->method" 'string-inflection-underscore))) 249 | (should (equal "eĥo_ŝanĝo->ĉiuĴaŭde" (buffer-try-inflect "eĥoŜanĝo->ĉiuĴaŭde" 'string-inflection-underscore)))) 250 | 251 | (ert-deftest test-buffer-camelcase () 252 | (should (equal "ObjectName->method" (buffer-try-inflect "object_name->method" 'string-inflection-camelcase))) 253 | (should (equal "Object1Name->method" (buffer-try-inflect "object1_name->method" 'string-inflection-camelcase))) 254 | (should (equal "EĥoŜanĝo->ĉiuĴaŭde" (buffer-try-inflect "eĥo_ŝanĝo->ĉiuĴaŭde" 'string-inflection-camelcase)))) 255 | 256 | (ert-deftest test-buffer-lower-camelcase () 257 | (should (equal "objectName->method" (buffer-try-inflect "object_name->method" 'string-inflection-lower-camelcase))) 258 | (should (equal "object1Name->method" (buffer-try-inflect "object1_name->method" 'string-inflection-lower-camelcase))) 259 | (should (equal "eĥoŜanĝo->ĉiuĴaŭde" (buffer-try-inflect "eĥo_ŝanĝo->ĉiuĴaŭde" 'string-inflection-lower-camelcase)))) 260 | 261 | 262 | (defun buffer-try-final-pos (str final-pos inflect initial-pos) 263 | (with-temp-buffer 264 | (setq-local string-inflection-final-position final-pos) 265 | (insert (concat str " fooo")) 266 | (goto-char initial-pos) 267 | (funcall inflect) 268 | (should-not (use-region-p)) 269 | (point))) 270 | 271 | (ert-deftest test-buffer-remain-simple-lengthen () 272 | (should (equal (buffer-try-final-pos "FooBar" 'remain #'string-inflection-underscore 2) 2))) 273 | 274 | (ert-deftest test-buffer-end-simple-lengthen () 275 | (should (equal (buffer-try-final-pos "FooBar" 'end #'string-inflection-underscore 2) 8))) 276 | 277 | (ert-deftest test-buffer-beginning-simple-lengthen () 278 | (should (equal (buffer-try-final-pos "FooBar" 'beginning #'string-inflection-underscore 2) 1))) 279 | 280 | (ert-deftest test-buffer-remain-simple-shorten-not-at-end () 281 | (should (equal (buffer-try-final-pos "foo_bar" 'remain #'string-inflection-camelcase 8) 7))) 282 | 283 | (ert-deftest test-buffer-remain-simple-shorten-at-end () 284 | (should (equal (buffer-try-final-pos "foo_bar" 'remain #'string-inflection-camelcase 2) 2))) 285 | 286 | (ert-deftest test-buffer-end-simple-shorten () 287 | (should (equal (buffer-try-final-pos "foo_bar" 'end #'string-inflection-camelcase 2) 7))) 288 | 289 | (ert-deftest test-buffer-beginning-simple-shorten () 290 | (should (equal (buffer-try-final-pos "foo_bar" 'beginning #'string-inflection-camelcase 2) 1))) 291 | 292 | 293 | (defun region-try-final-pos (str final-pos inverse) 294 | (with-temp-buffer 295 | (setq-local string-inflection-final-position final-pos) 296 | (insert str) 297 | (let ((final-point (point-max))) 298 | (insert " foooo") 299 | (if inverse 300 | (progn (set-mark final-point) (goto-char (point-min))) 301 | (set-mark (point-min)) (goto-char final-point)) 302 | (activate-mark)) 303 | (string-inflection-underscore) 304 | (should (use-region-p)) 305 | (should-not deactivate-mark) 306 | (cons (point) (cons (region-beginning) (region-end))))) 307 | 308 | 309 | (ert-deftest test-buffer-remain-region-straight () 310 | (let* ((state (region-try-final-pos "FooBar" 'remain nil)) 311 | (final-pos (car state)) 312 | (region (cdr state)) 313 | (beginning (car region)) 314 | (end (cdr region))) 315 | (should (equal beginning 1)) 316 | (should (equal end 8)) 317 | (should (equal final-pos 8)))) 318 | 319 | 320 | (ert-deftest test-buffer-remain-region-inversed () 321 | (let* ((state (region-try-final-pos "FooBar" 'remain t)) 322 | (final-pos (car state)) 323 | (region (cdr state)) 324 | (beginning (car region)) 325 | (end (cdr region))) 326 | (should (equal beginning 1)) 327 | (should (equal end 8)) 328 | (should (equal final-pos 1)))) 329 | 330 | 331 | (ert-deftest test-buffer-end-region-straight () 332 | (let* ((state (region-try-final-pos "FooBar" 'end nil)) 333 | (final-pos (car state)) 334 | (region (cdr state)) 335 | (beginning (car region)) 336 | (end (cdr region))) 337 | (should (equal beginning 1)) 338 | (should (equal end 8)) 339 | (should (equal final-pos 8)))) 340 | 341 | 342 | (ert-deftest test-buffer-end-region-inverse () 343 | (let* ((state (region-try-final-pos "FooBar" 'end t)) 344 | (final-pos (car state)) 345 | (region (cdr state)) 346 | (beginning (car region)) 347 | (end (cdr region))) 348 | (should (equal beginning 1)) 349 | (should (equal end 8)) 350 | (should (equal final-pos 8)))) 351 | 352 | 353 | (ert-deftest test-buffer-beginning-region-straight () 354 | (let* ((state (region-try-final-pos "FooBar" 'beginning nil)) 355 | (final-pos (car state)) 356 | (region (cdr state)) 357 | (beginning (car region)) 358 | (end (cdr region))) 359 | (should (equal beginning 1)) 360 | (should (equal end 8)) 361 | (should (equal final-pos 1)))) 362 | 363 | 364 | (ert-deftest test-buffer-beginning-region-inverse () 365 | (let* ((state (region-try-final-pos "FooBar" 'beginning t)) 366 | (final-pos (car state)) 367 | (region (cdr state)) 368 | (beginning (car region)) 369 | (end (cdr region))) 370 | (should (equal beginning 1)) 371 | (should (equal end 8)) 372 | (should (equal final-pos 1)))) 373 | 374 | 375 | (defun mixed-region-cycle-try (start end) 376 | (with-temp-buffer 377 | (text-mode) 378 | (insert "someFunction_to_do_SomeThing FoofooBarbarBarbarFoofoo") 379 | (set-mark start) 380 | (goto-char end) 381 | (activate-mark) 382 | (string-inflection-cycle) 383 | (cons (buffer-string) (cons (region-beginning) (region-end))))) 384 | 385 | 386 | (ert-deftest test-mixed-symbol-cycle-region-1 () 387 | (should (equal (car (mixed-region-cycle-try 1 13)) 388 | "some_function_to_do_SomeThing FoofooBarbarBarbarFoofoo"))) 389 | 390 | 391 | (ert-deftest test-mixed-symbol-cycle-region-2 () 392 | (should (equal (car (mixed-region-cycle-try 14 19)) 393 | "someFunction_TO_DO_SomeThing FoofooBarbarBarbarFoofoo"))) 394 | 395 | 396 | (ert-deftest test-mixed-symbol-cycle-region-3 () 397 | (should (equal (car (mixed-region-cycle-try 20 29)) 398 | "someFunction_to_do_some_thing FoofooBarbarBarbarFoofoo"))) 399 | 400 | 401 | (ert-deftest test-mixed-symbol-cycle-region-4 () 402 | (should (equal (car (mixed-region-cycle-try 20 41)) 403 | "someFunction_to_do_some_thing foofoo_barbarBarbarFoofoo"))) 404 | 405 | 406 | (ert-deftest test-mixed-symbol-cycle-region-restore-region () 407 | (should (equal (cdr (mixed-region-cycle-try 20 41)) (cons 20 43)))) 408 | 409 | 410 | (ert-run-tests-batch t) 411 | --------------------------------------------------------------------------------