Personal emacs config
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

367 lines
12 KiB

  1. ;;; string-inflection.el --- underscore -> UPCASE -> CamelCase -> lowerCamelCase conversion of names -*- lexical-binding: t -*-
  2. ;; Copyright (C) 2004,2014,2016,2017,2018,2020 Free Software Foundation, Inc.
  3. ;; Author: akicho8 <akicho8@gmail.com>
  4. ;; Keywords: elisp
  5. ;; Package-Version: 1.0.12
  6. ;; Package-Commit: c4a519be102cb99dd86be3ee8c387f008d097635
  7. ;; Version: 1.0.11
  8. ;; This file is free software; you can redistribute it and/or modify
  9. ;; it under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation; either version 2, or (at your option)
  11. ;; any later version.
  12. ;; This file is distributed in the hope that it will be useful,
  13. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;; GNU General Public License for more details.
  16. ;; You should have received a copy of the GNU General Public License
  17. ;; along with GNU Emacs; see the file COPYING. If not, write to
  18. ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19. ;; Boston, MA 02111-1307, USA.
  20. ;;; Commentary:
  21. ;; Main functions are three
  22. ;;
  23. ;; 1. For Ruby -> string-inflection-ruby-style-cycle (foo_bar => FOO_BAR => FooBar => foo_bar)
  24. ;; 2. For Python -> string-inflection-python-style-cycle (foo_bar => FOO_BAR => FooBar => foo_bar)
  25. ;; 3. For Java -> string-inflection-java-style-cycle (fooBar => FOO_BAR => FooBar => fooBar)
  26. ;; 4. For All -> string-inflection-all-cycle (foo_bar => FOO_BAR => FooBar => fooBar => foo-bar => Foo_Bar => foo_bar)
  27. ;;
  28. ;;
  29. ;; Setting Example 1
  30. ;;
  31. ;; (require 'string-inflection)
  32. ;; (global-unset-key (kbd "C-q"))
  33. ;; ;; C-q C-u is the key bindings similar to Vz Editor.
  34. ;; (global-set-key (kbd "C-q C-u") 'my-string-inflection-cycle-auto)
  35. ;;
  36. ;; (defun my-string-inflection-cycle-auto ()
  37. ;; "switching by major-mode"
  38. ;; (interactive)
  39. ;; (cond
  40. ;; ;; for emacs-lisp-mode
  41. ;; ((eq major-mode 'emacs-lisp-mode)
  42. ;; (string-inflection-all-cycle))
  43. ;; ;; for java
  44. ;; ((eq major-mode 'java-mode)
  45. ;; (string-inflection-java-style-cycle))
  46. ;; ;; for python
  47. ;; ((eq major-mode 'python-mode)
  48. ;; (string-inflection-python-style-cycle))
  49. ;; (t
  50. ;; ;; default
  51. ;; (string-inflection-ruby-style-cycle))))
  52. ;;
  53. ;;
  54. ;; Setting Example 2
  55. ;;
  56. ;; (require 'string-inflection)
  57. ;;
  58. ;; ;; default
  59. ;; (global-set-key (kbd "C-c C-u") 'string-inflection-all-cycle)
  60. ;;
  61. ;; ;; for ruby
  62. ;; (add-hook 'ruby-mode-hook
  63. ;; '(lambda ()
  64. ;; (local-set-key (kbd "C-c C-u") 'string-inflection-ruby-style-cycle)))
  65. ;;
  66. ;; ;; for python
  67. ;; (add-hook 'python-mode-hook
  68. ;; '(lambda ()
  69. ;; (local-set-key (kbd "C-c C-u") 'string-inflection-python-style-cycle)))
  70. ;;
  71. ;; ;; for java
  72. ;; (add-hook 'java-mode-hook
  73. ;; '(lambda ()
  74. ;; (local-set-key (kbd "C-c C-u") 'string-inflection-java-style-cycle)))
  75. ;;
  76. ;; You may also consider setting `string-inflection-skip-backward-when-done' to
  77. ;; `t' if you don't like `string-inflect' moving your point to the end of the
  78. ;; word
  79. ;;; Code:
  80. (defconst string-inflection-word-chars "a-zA-Z0-9_-")
  81. (defvar string-inflection-skip-backward-when-done nil
  82. "Whether point just move backward to the beginning of the word after inflecting.")
  83. ;; --------------------------------------------------------------------------------
  84. ;;;###autoload
  85. (defun string-inflection-ruby-style-cycle ()
  86. "foo_bar => FOO_BAR => FooBar => foo_bar"
  87. (interactive)
  88. (string-inflection-insert
  89. (string-inflection-ruby-style-cycle-function (string-inflection-get-current-word))))
  90. (fset 'string-inflection-cycle 'string-inflection-ruby-style-cycle)
  91. ;;;###autoload
  92. (defun string-inflection-python-style-cycle ()
  93. "foo_bar => FOO_BAR => FooBar => foo_bar"
  94. (interactive)
  95. (string-inflection-insert
  96. (string-inflection-python-style-cycle-function (string-inflection-get-current-word))))
  97. ;;;###autoload
  98. (defun string-inflection-java-style-cycle ()
  99. "fooBar => FOO_BAR => FooBar => fooBar"
  100. (interactive)
  101. (string-inflection-insert
  102. (string-inflection-java-style-cycle-function (string-inflection-get-current-word))))
  103. ;;;###autoload
  104. (defun string-inflection-all-cycle ()
  105. "foo_bar => FOO_BAR => FooBar => fooBar => foo-bar => Foo_Bar => foo_bar"
  106. (interactive)
  107. (string-inflection-insert
  108. (string-inflection-all-cycle-function (string-inflection-get-current-word))))
  109. ;;;###autoload
  110. (defun string-inflection-toggle ()
  111. "toggle foo_bar <=> FooBar"
  112. (interactive)
  113. (string-inflection-insert
  114. (string-inflection-toggle-function (string-inflection-get-current-word))))
  115. ;;;###autoload
  116. (defun string-inflection-camelcase ()
  117. "FooBar format"
  118. (interactive)
  119. (string-inflection-insert
  120. (string-inflection-pascal-case-function (string-inflection-get-current-word))))
  121. ;;;###autoload
  122. (defun string-inflection-lower-camelcase ()
  123. "fooBar format"
  124. (interactive)
  125. (string-inflection-insert
  126. (string-inflection-camelcase-function (string-inflection-get-current-word))))
  127. ;;;###autoload
  128. (defun string-inflection-underscore ()
  129. "foo_bar format"
  130. (interactive)
  131. (string-inflection-insert
  132. (string-inflection-underscore-function (string-inflection-get-current-word))))
  133. ;;;###autoload
  134. (defun string-inflection-capital-underscore ()
  135. "Foo_Bar format"
  136. (interactive)
  137. (string-inflection-insert
  138. (string-inflection-capital-underscore-function (string-inflection-get-current-word))))
  139. ;;;###autoload
  140. (defun string-inflection-upcase ()
  141. "FOO_BAR format"
  142. (interactive)
  143. (string-inflection-insert
  144. (string-inflection-upcase-function (string-inflection-get-current-word))))
  145. ;;;###autoload
  146. (defun string-inflection-kebab-case ()
  147. "foo-bar format"
  148. (interactive)
  149. (string-inflection-insert
  150. (string-inflection-kebab-case-function (string-inflection-get-current-word))))
  151. (fset 'string-inflection-lisp 'string-inflection-kebab-case)
  152. ;; --------------------------------------------------------------------------------
  153. (defun string-inflection-insert (s)
  154. (insert s)
  155. (when string-inflection-skip-backward-when-done (skip-chars-backward string-inflection-word-chars)))
  156. (defun string-inflection-non-word-chars ()
  157. (concat "^" string-inflection-word-chars))
  158. (defun string-inflection-get-current-word ()
  159. "Gets the symbol near the cursor"
  160. (interactive)
  161. (let* ((start (if (use-region-p)
  162. (region-end)
  163. (progn
  164. (skip-chars-forward string-inflection-word-chars)
  165. ;; https://github.com/akicho8/string-inflection/issues/30
  166. ;;
  167. ;; objectName->method --> "objectName-" NG
  168. ;; --> "objectName" OK
  169. (when (and (not (eobp)) (not (bobp)))
  170. (when (string= (buffer-substring (1- (point)) (1+ (point))) "->")
  171. (forward-char -1)))
  172. (point))))
  173. (end (if (use-region-p)
  174. (region-beginning)
  175. (progn
  176. (skip-chars-backward string-inflection-word-chars)
  177. (point))))
  178. (str (buffer-substring start end)))
  179. (prog1
  180. (if (use-region-p)
  181. (replace-regexp-in-string "[[:space:].:/]+" "_" str) ; 'aa::bb.cc dd/ee' => 'aa_bb_cc_dd_ee'
  182. str)
  183. (delete-region start end))))
  184. ;; --------------------------------------------------------------------------------
  185. (defun string-inflection-pascal-case-function (str)
  186. "foo_bar => FooBar"
  187. (setq str (string-inflection-underscore-function str))
  188. (mapconcat 'capitalize (split-string str "_") ""))
  189. (fset 'string-inflection-upper-camelcase-function 'string-inflection-pascal-case-function)
  190. (defun string-inflection-camelcase-function (str)
  191. "foo_bar => fooBar"
  192. (setq str (split-string (string-inflection-underscore-function str) "_"))
  193. (concat (downcase (car str))
  194. (mapconcat 'capitalize (cdr str) "")))
  195. (fset 'string-inflection-lower-camelcase-function 'string-inflection-camelcase-function)
  196. (defun string-inflection-upcase-function (str)
  197. "FooBar => FOO_BAR"
  198. (upcase (string-inflection-underscore-function str)))
  199. (defun string-inflection-underscore-function (str)
  200. "FooBar => foo_bar"
  201. (let ((case-fold-search nil))
  202. (setq str (replace-regexp-in-string "\\([a-z0-9]\\)\\([A-Z]\\)" "\\1_\\2" str))
  203. (setq str (replace-regexp-in-string "\\([A-Z]+\\)\\([A-Z][a-z]\\)" "\\1_\\2" str))
  204. (setq str (replace-regexp-in-string "-" "_" str)) ; FOO-BAR => FOO_BAR
  205. (setq str (replace-regexp-in-string "_+" "_" str))
  206. (downcase str)))
  207. (defun string-inflection-capital-underscore-function (str)
  208. "foo_bar => Foo_Bar"
  209. (setq str (string-inflection-underscore-function str))
  210. (mapconcat 'capitalize (split-string str "_") "_"))
  211. (defun string-inflection-kebab-case-function (str)
  212. "foo_bar => foo-bar"
  213. (let ((case-fold-search nil))
  214. (setq str (string-inflection-underscore-function str))
  215. (setq str (replace-regexp-in-string "_" "-" str))))
  216. (defun string-inflection-all-cycle-function (str)
  217. "foo_bar => FOO_BAR => FooBar => fooBar => foo-bar => Foo_Bar => foo_bar
  218. foo => FOO => Foo => foo"
  219. (cond
  220. ;; foo => FOO
  221. ((string-inflection-word-p str)
  222. (string-inflection-upcase-function str))
  223. ;; foo_bar => FOO_BAR
  224. ((string-inflection-underscore-p str)
  225. (string-inflection-upcase-function str))
  226. ;; FOO_BAR => FooBar
  227. ((string-inflection-upcase-p str)
  228. (string-inflection-pascal-case-function str))
  229. ;; FooBar => fooBar
  230. ;; Foo => foo
  231. ((string-inflection-pascal-case-p str)
  232. (string-inflection-camelcase-function str))
  233. ;; fooBar => foo-bar
  234. ((string-inflection-camelcase-p str)
  235. (string-inflection-kebab-case-function str))
  236. ;; foo-bar => Foo_Bar
  237. ((string-inflection-kebab-case-p str)
  238. (string-inflection-capital-underscore-function str))
  239. ;; foo-bar => foo_bar
  240. (t
  241. (string-inflection-underscore-function str))))
  242. (defun string-inflection-ruby-style-cycle-function (str)
  243. "foo_bar => FOO_BAR => FooBar => foo_bar"
  244. (cond
  245. ((string-inflection-underscore-p str)
  246. (string-inflection-upcase-function str))
  247. ((string-inflection-upcase-p str)
  248. (string-inflection-pascal-case-function str))
  249. (t
  250. (string-inflection-underscore-function str))))
  251. (defalias 'string-inflection-python-style-cycle-function
  252. 'string-inflection-ruby-style-cycle-function)
  253. (defun string-inflection-java-style-cycle-function (str)
  254. "fooBar => FOO_BAR => FooBar => fooBar"
  255. (cond
  256. ((string-inflection-underscore-p str)
  257. (string-inflection-upcase-function str))
  258. ((string-inflection-camelcase-p str)
  259. (string-inflection-upcase-function str))
  260. ((string-inflection-upcase-p str)
  261. (string-inflection-pascal-case-function str))
  262. (t
  263. (string-inflection-camelcase-function str))))
  264. ;; Toggle function. But cycle function.
  265. (defun string-inflection-toggle-function (str)
  266. "Not so much the case that in all caps when using normal foo_bar <--> FooBar"
  267. (cond
  268. ((string-inflection-underscore-p str)
  269. (string-inflection-pascal-case-function str))
  270. ((string-inflection-pascal-case-p str)
  271. (string-inflection-camelcase-function str))
  272. (t
  273. (string-inflection-underscore-function str))))
  274. ;; --------------------------------------------------------------------------------
  275. (defun string-inflection-word-p (str)
  276. "if foo => t"
  277. (let ((case-fold-search nil))
  278. (string-match "\\`[a-z0-9]+\\'" str)))
  279. (defun string-inflection-underscore-p (str)
  280. "if foo_bar => t"
  281. (let ((case-fold-search nil))
  282. (string-match "\\`[a-z0-9_]+\\'" str)))
  283. (defun string-inflection-upcase-p (str)
  284. "if FOO_BAR => t"
  285. (let ((case-fold-search nil))
  286. (string-match "\\`[A-Z0-9_]+\\'" str)))
  287. (defun string-inflection-pascal-case-p (str)
  288. "if FooBar => t"
  289. (let ((case-fold-search nil))
  290. (and
  291. (string-match "[a-z]" str)
  292. (string-match "\\`[A-Z][a-zA-Z0-9]+\\'" str))))
  293. (fset 'string-inflection-upper-camelcase-p 'string-inflection-pascal-case-p)
  294. (defun string-inflection-camelcase-p (str)
  295. "if fooBar => t"
  296. (let ((case-fold-search nil))
  297. (and
  298. (string-match "[A-Z]" str)
  299. (string-match "\\`[a-z][a-zA-Z0-9]+\\'" str))))
  300. (fset 'string-inflection-lower-camelcase-p 'string-inflection-camelcase-p)
  301. (defun string-inflection-kebab-case-p (str)
  302. "if foo-bar => t"
  303. (string-match "-" str))
  304. (defun string-inflection-capital-underscore-p (str)
  305. "if Foo_Bar => t"
  306. (let ((case-fold-search nil))
  307. (and
  308. (string-match "[A-Z]" str)
  309. (string-match "_" str)
  310. (string-match "\\`[A-Z][a-zA-Z0-9_]+\\'" str))))
  311. (provide 'string-inflection)
  312. ;;; string-inflection.el ends here