(require 'string-inflection)
;; C-q C-u is similar to the keybinding used by Vz Editor.
(global-unset-key (kbd "C-q"))
(global-set-key (kbd "C-q C-u") 'my-string-inflection-cycle-auto)
(defun my-string-inflection-cycle-auto ()
"switching by major-mode"
(interactive)
(cond
;; for emacs-lisp-mode
((eq major-mode 'emacs-lisp-mode)
(string-inflection-all-cycle))
;; for python
((eq major-mode 'python-mode)
(string-inflection-python-style-cycle))
;; for java
((eq major-mode 'java-mode)
(string-inflection-java-style-cycle))
;; for elixir
((eq major-mode 'elixir-mode)
(string-inflection-elixir-style-cycle))
(t
;; default
(string-inflection-ruby-style-cycle))))
(require 'string-inflection)
;; default
(global-set-key (kbd "C-c C-u") 'string-inflection-all-cycle)
;; for ruby
(add-hook 'ruby-mode-hook
'(lambda ()
(local-set-key (kbd "C-c C-u") 'string-inflection-ruby-style-cycle)))
;; for elixir
(add-hook 'elixir-mode-hook
'(lambda ()
(local-set-key (kbd "C-c C-u") 'string-inflection-elixir-style-cycle)))
;; for java
(add-hook 'java-mode-hook
'(lambda ()
(local-set-key (kbd "C-c C-u") 'string-inflection-java-style-cycle)))
;; for python
(add-hook 'python-mode-hook
'(lambda ()
(local-set-key (kbd "C-c C-u") 'string-inflection-python-style-cycle)))
For each of the following, place the point at emacs_lisp
and type C-q C-u
, the results will be as follows:
In the case of string-inflection-ruby-style-cycle
emacs_lisp => EMACS_LISP => EmacsLisp => emacs_lisp
In the case of string-inflection-elixir-style-cycle
emacs_lisp => EmacsLisp => emacs_lisp
In the case of string-inflection-python-style-cycle
emacs_lisp => EMACS_LISP => EmacsLisp => emacs_lisp
In the case of string-inflection-java-style-cycle
emacsLisp => EMACS_LISP => EmacsLisp => emacsLisp
In the case of string-inflection-all-cycle
emacs_lisp => EMACS_LISP => EmacsLisp => emacsLisp => emacs-lisp => Emacs_Lisp => emacs_lisp
It is recommended that the major mode functions are used instead of string-inflection-all-cycle
.
(string-inflection-snake-case-function "EmacsLisp") ; => "emacs_lisp"
(string-inflection-pascal-case-function "emacs_lisp") ; => "EmacsLisp"
(string-inflection-camel-case-function "emacs_lisp") ; => "emacsLisp"
(string-inflection-upcase-function "emacs_lisp") ; => "EMACS_LISP"
(string-inflection-kebab-case-function "emacs_lisp") ; => "emacs-lisp"
(string-inflection-capital-snake-case-function "emacs_lisp") ; => "Emacs_Lisp"
(string-inflection-pascal-case-p "EmacsLisp") ; => t
(string-inflection-pascal-case-p "emacs_lisp") ; => nil
; etc...
You can also use this library to convert a region’s casing. That applies the operation to all symbols of the region. If a symbol is only partially covered by the region, the operation is performed only on that part.
For that, simply select a region and perform M-x string-inflection-kebab-case
(or any such other function).
You can configure where the point shall finish after the inflection operation
using the string-inflection-final-position
customization option.
At first glance, this method may seem convenient, but in reality, it was created solely for testing purposes during development. Its role is to verify that all transformation patterns are properly traversed, and it was never intended for regular use. In fact, the developers themselves do not use it at all and strongly discourage its use.
Using this method in practice leads to unnecessary stress, as it forces traversal through every possible transformation pattern, making the conversion process excessively long. Moreover, under the current default settings, the method may not even complete a full cycle depending on the mode in use.
For example, in modes where hyphens are not considered part of variable names, a string like foo-bar
will be split into foo
and bar
, and the transformation will only proceed on bar
. This means the intended conversion process can be interrupted midway depending on the context.
For these reasons, this method should not be used as part of your regular workflow. It is strictly meant for internal verification during development, and we advise against using it in day-to-day usage.
In the past, the transformation target was determined based on character syntax alone, regardless of major mode. Specifically, it would act on a “chunk” near the point that looked like an English-style variable name.
Now, however, the behavior has been improved: the transformation target is determined by the symbol boundaries defined by each major mode. This means the scope of what is considered a variable name is now more precise and language-aware.
Additionally, this abstraction allows the transformation of words containing non-ASCII characters, such as umlauts.
That said, there are cases where the old, mode-agnostic behavior is still more convenient. If you prefer the previous approach, you can restore it by setting the following:
(setq string-inflection-bounds-function
(lambda ()
(cons
(progn (skip-chars-forward "a-zA-Z0-9_-")
(skip-chars-backward "_-")
(point))
(progn (skip-chars-backward "a-zA-Z0-9_-")
(skip-chars-forward "_-")
(point)))))
or
(setq string-inflection-bounds-function 'string-inflection-bounds-of-mode-independent-chunk)
This method is quite useful and recommended for certain use cases.