Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/ROCKTAKEY/grugru

Rotate text at point in Emacs.
https://github.com/ROCKTAKEY/grugru

emacs emacs-lisp emacs-package emacs-plugin

Last synced: 3 months ago
JSON representation

Rotate text at point in Emacs.

Lists

README

        

[[https://raw.githubusercontent.com/ROCKTAKEY/images/4524403fbcdd9abe6d88197eddb1c4d241046e72/grugru.png]]
[[https://github.com/ROCKTAKEY/grugru][https://img.shields.io/github/tag/ROCKTAKEY/grugru.svg?style=flat-square]]
[[file:LICENSE][https://img.shields.io/github/license/ROCKTAKEY/grugru.svg?style=flat-square]]
[[https://github.com/ROCKTAKEY/grugru/actions][https://img.shields.io/github/actions/workflow/status/ROCKTAKEY/grugru/CI.yml.svg?style=flat-square]]
[[https://codecov.io/gh/ROCKTAKEY/grugru?branch=master][https://img.shields.io/codecov/c/github/ROCKTAKEY/grugru/master.svg?style=flat-square]]
[[https://melpa.org/#/grugru][file:https://melpa.org/packages/grugru-badge.svg]]
* Grugru: Rotate text at point.
With this package, you can rotate things at point.

#+begin_center
[[https://raw.githubusercontent.com/ROCKTAKEY/images/7baf9507a8fb9c20eda7395be1c9d91d0ae61c51/emacs-lisp-mode.gif]]
Fig. 1 demo on =emacs-lisp-mode=

[[https://raw.githubusercontent.com/ROCKTAKEY/images/35e323db33f4da1545c289f2741782c4ac04968b/c++-mode.gif]]
Fig. 2 demo on =c++-mode=

[[https://raw.githubusercontent.com/ROCKTAKEY/images/698f33489645a6e7b0c29d879771dbb15fa3fcd9/grugru-define-local.gif]]
Fig. 3 Use =grugru-define-local= interactively
#+end_center
* How to Use?
You can interactively use the function =grugru=. This function rotate the thing at point
if assigned. You can assign rotated things with
=grugru-define-on-major-mode=, =grugru-define-on-local-major-mode=, and =grugru-define-local=.
If you use ~grugru~, you should assign ~grugru~ to 1 stroke key like ~C-;~, or ~M-g~.
#+begin_src emacs-lisp :tangle yes
(global-set-key (kbd "C-;") #'grugru) ; Or other key.
#+end_src

If you want use default grugru, eval ~grugru-default-setup~. In the other words,
add to your init.el:
#+BEGIN_SRC emacs-lisp :tangle yes
(grugru-default-setup)
#+END_SRC

If you want ~grugru~ to highlight gurgruable thing, add to your init.el:
#+begin_src emacs-lisp :tangle yes
(grugru-highlight-mode)
#+end_src

If you want to change default action at point, you can use ~grugru-edit~,
with which you can edit grugrus at point interactively. The change edited by this
function is saved in ~grugru-edit-save-file~,
and loaded by run ~grugru-edit-load~. So to load the change, you can write
on init.el after ~(grugru-default-setup)~:
#+begin_src emacs-lisp :tangle yes
(grugru-edit-load)
#+end_src

If you want to use ivy or ido as completing-read, set ~grugru-edit-completing-function~.
Or, you can use ~grugru-redefine-\*~ or ~grugru-remove-\*~
for non-interactive editing of default setup.
** Examples
#+BEGIN_SRC emacs-lisp -n
;; Define grugru on major-mode.
(grugru-define-on-major-mode 'c-mode 'symbol '("unsigned" "signed"))
(grugru-define-on-major-mode 'c-mode 'word '("get" "set"))
;; Now, you can toggle unsigned <=> signed and get <=> set
;; by running the command grugru in c-mode.

;; You can pass a list of symbol major-mode instead of one.
(grugru-define-on-major-mode '(java-mode c++-mode) 'word '("get" "set"))

;; Define grugru on current major-mode.
;; Same as (grugru-define-on-major-mode major-mode 'symbol '("red" "green" "yellow"))
;; This should be run in some hook or function,
;; because major-mode is not confirmed if in init.el.
(add-hook 'c-mode-common-hook
(lambda ()
(grugru-define-on-local-major-mode 'symbol '("red" "green" "yellow"))))

;; Define grugru on local. Should be defined in some hook or function,
;; because it is saved buffer local.
(add-hook 'text-mode-hook
(lambda ()
(grugru-define-local 'word '("is" "was"))
(grugru-define-local 'word '("I" "my" "me" "mine"))))

;; Define grugru globally. This is applied in all buffers.
(grugru-define-global 'symbol '("yes" "no"))

;; Define grugru keeping case:
(grugru-define-global 'symbol (grugru-metagenerator-keep-case '("yes" "no")))

;; If you want grugru to define grugru defaultly keeping case:
(customize-set-variable 'grugru-strings-metagenerator #'grugru-metagenerator-simple)

;; You can use function instead of list of strings.
(grugru-define-on-major-mode
'c-mode 'symbol
;; Optional argument `rev' is flag for backward rotation.
;; If the second argument `rev' is ignoreable (for example, rotate two strings),
;; you can just use the function receiving only 1 argument.
(lambda (arg &optional rev)
(if rev
;; backward
(cond
((string-match "a\\(.*\\)b" arg)
;; Rotate axyzb to cxyzd
(concat "c" (match-string 1 arg) "d"))
((string-match "b\\(.*\\)c" arg)
;; Rotate bxyzc to axyzb
(concat "a" (match-string 1 arg) "b"))
((string-match "c\\(.*\\)d" arg)
;; Rotate cxyzd to bxyzc
(concat "b" (match-string 1 arg) "c")))
;; forward
(cond
((string-match "a\\(.*\\)b" arg)
;; Rotate axyzb to bxyzc
(concat "b" (match-string 1 arg) "c"))
((string-match "b\\(.*\\)c" arg)
;; Rotate bxyzc to cxyzd
(concat "c" (match-string 1 arg) "d"))
((string-match "c\\(.*\\)d" arg)
;; Rotate cxyzd to axyzb
(concat "a" (match-string 1 arg) "b"))))))

;; You can indicate which position is valid to grugru in strings.
;; The function can return not only string but also cons cell (BOUNDS . STRING).
;; BOUNDS is a list of cons cell (BEG . END), which is pair of numbers indicating
;; range valid to rotate.
(defun grugru-default@emacs-lisp+nth!aref (str)
"Return STR exchanged `nth' and `aref' with argument permutation."
(cond
((string-match "^(\\_<\\(nth\\)\\_>" str)
(cons
(cons (match-beginning 1) (match-end 1))
;; This function permutate arguments on Lisp.
(grugru-utils-lisp-exchange-args
(replace-match "aref" nil nil str 1)
'(2 1))))
((string-match "^(\\_<\\(aref\\)\\_>" str)
(cons
(cons (match-beginning 1) (match-end 1))
(grugru-utils-lisp-exchange-args
(replace-match "nth" nil nil str 1)
'(2 1))))))

;; You can also write like:
(grugru-define-multiple
(fundamental-mode
. ((word . ("aaa" "bbb" "ccc"))
;; (symbol "xxx" "yyy" "zzz") is same as below.
;; You can use both.
(symbol . ("xxx" "yyy" "zzz"))
(word . ("abc" "def" "ghi"))))
(word . ("aaaa" "bbbb" "cccc"))
(symbol . ("xxxx" "yyyyy" "zzzzz"))
(word . ("abcd" "defd" "ghid")))
;; or
(grugru-define-multiple
(fundamental-mode
(word "aaa" "bbb" "ccc")
(symbol "xxx" "yyy" "zzz")
(word "abc" "def" "ghi"))
(word "aaaa" "bbbb" "cccc")
(symbol "xxxx" "yyyyy" "zzzzz")
(word "abcd" "defd" "ghid"))

;; Above two examples are both expanded to:
(progn
(progn
(grugru-define-on-major-mode 'fundamental-mode 'word '("aaa" "bbb" "ccc"))
(grugru-define-on-major-mode 'fundamental-mode 'symbol '("xxx" "yyy" "zzz"))
(grugru-define-on-major-mode 'fundamental-mode 'word '("abc" "def" "ghi")))
(grugru-define-global 'word '("aaaa" "bbbb" "cccc"))
(grugru-define-global 'symbol '("xxxx" "yyyyy" "zzzzz"))
(grugru-define-global 'word '("abcd" "defd" "ghid")))

;; You can define function which rotate pre-specified texts.
;; For example, three-state can rotate only 2 tuples,
;; ("water" "ice" "vapor") and ("solid" "liquid" "gas"),
;; not any other tuples defined by grugru-define-global and so on.
(grugru-define-function three-state ()
"Docstring. This is optional."
(symbol . ("water" "ice" "vapor"))
(symbol . ("solid" "liquid" "gas")))
;; If you want to find the functions defined by `grugru-define-function'
;; with `describe-function', execute this:
(grugru-find-function-integration-mode +1)
#+END_SRC
* Interactive Functions
** ~grugru~
This function rotates text at point.
Rotated text is defined by ~grugru-define-*~ functions.
If prefix argument is passed, repeatedly executed. Negative prefix arguments means
backward rotation. Also, ~grugru-backward~ can be used for backward rotation.
** ~grugru-select~
This function replace text at point.
You can select grugru and string replaced to.

You can assign completing function to ~grugru-completing-function~.
** ~grugru-edit~
This function edits grugru at point defined by default.

First, select grugru from grugrus available at point.
Then, edit the list in minibuffer.

The change is saved to file ~grugru-edit-save-file~ if it is not ~local~ one.
You can assign completing function to ~grugru-completing-function~.
* Functions Defining grugru
** ~(grugru-define-global GETTER STRINGS-OR-FUNCTION)~
Define global grugru with GETTER and STRINGS-OR-FUNCTION.

GETTER is a function, or a symbol which is alias defined in ~grugru-getter-alist~.
GETTER also can be positive or negative number, which means the number of characters
after point.
By default, symbol, word, char is available.
If it is a function, it should return cons cell ~(begin . end)~
which express things at point, and with no argument.

STRINGS-OR-FUNCTION is list of string or function.

List of string: If it includes string gotten by GETTER,
the things gotten by GETTER is replaced to next string.

Function: It is passed things gotten by GETTER, and should return string
to replace the things to.

You can use like:
#+begin_src emacs-lisp :tangle yes
;; Replace "yes" at point, to "no".
;; Or replace "no" at point, to "yes".
(grugru-define-global 'symbol '("yes" "no"))
#+end_src
** ~(grugru-define-on-major-mode MAJOR GETTER STRINGS-OR-FUNCTION)~
Define major-mode local grugru with GETTER and STRINGS-OR-FUNCTION.

Same as ~grugru-define-global~, but grugru defined with this is applied
only in buffer on MAJOR major-mode. MAJOR can be list of major-modes.
#+begin_src emacs-lisp :tangle yes
;; Replace "yes" at point, to "no", or replace "no" at point, to "yes",
;; only in lisp-interaction-mode.
(grugru-define-on-major-mode lisp-interaction-mode 'symbol '("yes" "no"))
#+end_src
** ~(grugru-define-local GETTER STRINGS-OR-FUNCTION)~
Define buffer-local grugru with GETTER and STRINGS-OR-FUNCTION.

Same as ~grugru-define-global~, but grugru defined with this is applied
only in buffer where eval this expression.
#+begin_src emacs-lisp :tangle yes
;; This should be used in hook or others.
;; Because this definition is buffer-local.
(add-hook 'text-mode-hook
(lambda ()
(grugru-define-local 'word '("is" "was"))
(grugru-define-local 'word '("I" "my" "me" "mine"))))
#+end_src

Also, you can run it interactively (though cannot set STRINGS-OR-FUNCTION to a function).
On interactive usage, by default, GETTER is the length of car of STRINGS-OR-FUNCTION,
and STRINGS-OR-FUNCTION is a list which has 2 elements, constructed interactively.
With prefix argument, you can select GETTER and length of STRINGS-OR-FUNCTION.
Default GETTER is set by ~grugru-local-interactively-default-getter~.

** ~(grugru-define-multiple &rest CLAUSES)~
This function define multiple grugru.

Each ~CLAUSE~ is:
- ~(GETTER . STRINGS-OR-FUNCTION)~: means ~(grugru-define-global GETTER STRINGS-OR-FUNCTION)~.
- ~(MAJOR (GETTER . STRINGS-OR-FUNCTION)...)~: means ~(grugru-define-on-major-mode MAJOR GETTER STRINGS-OR-FUNCTION)...~.
- List of above.

#+begin_src emacs-lisp :tangle yes
(grugru-define-multiple
(fundamental-mode
. ((word . ("aaa" "bbb" "ccc"))
;; (symbol "xxx" "yyy" "zzz") is same as below.
;; You can use both.
(symbol . ("xxx" "yyy" "zzz"))
(word . ("abc" "def" "ghi"))))
(word . ("aaaa" "bbbb" "cccc"))
(symbol . ("xxxx" "yyyyy" "zzzzz"))
(word . ("abcd" "defd" "ghid")))
;; or
(grugru-define-multiple
(fundamental-mode
(word "aaa" "bbb" "ccc")
(symbol "xxx" "yyy" "zzz")
(word "abc" "def" "ghi"))
(word "aaaa" "bbbb" "cccc")
(symbol "xxxx" "yyyyy" "zzzzz")
(word "abcd" "defd" "ghid"))

;; Above two examples are both expanded to:
(progn
(progn
(grugru-define-on-major-mode 'fundamental-mode 'word '("aaa" "bbb" "ccc"))
(grugru-define-on-major-mode 'fundamental-mode 'symbol '("xxx" "yyy" "zzz"))
(grugru-define-on-major-mode 'fundamental-mode 'word '("abc" "def" "ghi")))
(grugru-define-global 'word '("aaaa" "bbbb" "cccc"))
(grugru-define-global 'symbol '("xxxx" "yyyyy" "zzzzz"))
(grugru-define-global 'word '("abcd" "defd" "ghid")))
#+end_src
** ~(grugru-define-function NAME () &optional DOCSTRING &rest BODY)~
Define function which can roate only grugru defined by BODY.
Each element of BODY is ~(GETTER . STRINGS-OR-FUNCTION)~,
which meaning is same as ~grugru-define-*~ functions.
#+begin_src emacs-lisp :tangle yes
;; The function `three-state' rotate like "water"=>"ice"=>"vapor"=>"water",
;; or "solid"=>"liquid"=>"gas"=>"solid".
(grugru-define-function three-state ()
"Docstring. This is optional."
(symbol . ("water" "ice" "vapor"))
(symbol . ("solid" "liquid" "gas")))

;; This sentense do NOT affect to the function `three-state'.
(grugru-define-global 'symbol '("yes" "no"))
#+end_src
* Utilities to define grugru
** ~(grugru-utils-lisp-exchange-args LIST-STRING PERMUTATION)~
Permute argument of sexp read from ~LIST-STRING~ according to ~PERMUTATION~.

For example, ~(grugru-utils-lisp-exchange-args \"(nth 1 '(x y z))\" '(2 1))~
returns ~(nth '(x y z) 1)~. Newlines and whitespaces are also kept.

This function is defined for user to define the function for grugru which rotate
not only fuction's name but also arguments' order.
*** Usage
#+begin_src emacs-lisp :tangle yes
(defun grugru-rotate-nth-aref (str)
(cond
((string-match "^(\\(\\_\\)" str) ;match to "(nth"
(grugru-utils-lisp-exchange-args
(replace-match "aref" nil nil str 1) ;replace function's name to "aref"
'(2 1))) ;exchange arguments' order
((string-match "^(\\(\\_\\)" str) ;match to "(aref"
(grugru-utils-lisp-exchange-args
(replace-match "nth" nil nil str 1) ;replace function's name to "nth"
'(2 1))))) ;exchange arguments' order
(grugru-define-on-major-mode
'emacs-lisp-mode
'list
#'grugru-rotate-nth-aref)

;; Then,
(nth 3 '(foo bar))
;; is rotated to:
(aref '(foo bar) 3)
#+end_src
* Custom Variables
** ~grugru-getter-alist~
Alist of getter.

Each key (car) of element is a symbol, which is regarded as ~GETTER~.

Each value (cdr) of element is a function or sexp.
It should return things at point.

** ~grugru-edit-save-file~
The name of file saved the information by ~grugru-edit~.
Default value is "~/.emacs.d/.grugru".

** ~grugru-completing-function~
Completing function. Default value is ~completing-read~.
If you would like to use ivy or ido, write:
#+begin_src emacs-lisp :tangle yes
;; For ivy:
(setq grugru-completing-function #'ivy-completing-read)
;; For ido:
(setq grugru-completing-function #'ido-completing-read)
#+end_src

** ~grugru-select-function-generate-number~
This variable have how many strings are generated from function
in ~STRINGS-OR-FUNCTION~, on ~grugru-select~.

** ~grugru-local-interactively-default-getter~
Indicate default getter on interactive usage of ~grugru-define-local~.
0 means If 0, gets number from first string, otherwise it should be
symbol in ~grugru-getter-alist~ or a function which gets things at point.
** ~grugru-point-after-rotate~
Where the point is after rotation by ~grugru~.
- ~as-is~ means keeping first position.
- ~beginning~ means beginning of rotated things.
- ~end~ means end of rotated things.
** ~grugru-indent-after-rotate~
Indent rotated text after ~grugru~ or not.
Indent happens only if text after rotation has a newline.
#+begin_src emacs-lisp :tangle yes
(grugru-define-local 'list '("(abc def)" "(ghi\njkl)"))
;; If `grugru-indent-after-rotate' is nil,
(abc def)
;; is rotated to:
(ghi
jkl)

;; If `grugru-indent-after-rotate' is t,
(abc def)
;; is rotated to:
(ghi
jkl)
#+end_src
** ~grugru-strings-metagenerator~
Function which generates default generator from strings on ~grugru-define-*~.
The function should recieve ~STRINGS~, list of string, as one argument,
and return function. Returned function should recieve one or two argument(s),
string ~STRING~ as first one, boolean ~REVERSE~ as second one.

STRING means current string. Returned function (generator) returns string next to STRING.
If REVERSE is non-nil, it returns previous one instead.
* leaf-keyword ~:grugru~
You can use ~:grugru~ keyword on [[https://github.com/conao3/leaf.el][leaf.el]], if you use [[https://github.com/conao3/leaf-keywords.el][leaf-keywords.el]].

By default, ~leaf--name~ is used as major-mode.
Or you can write major-mode obviously.
#+begin_src emacs-lisp :tangle yes
(leaf lisp-mode
:grugru
(symbol "nil" "t")
(emacs-lisp-mode
(word "add" "remove"))
...)
;; The section of `:grugru' means:
(grugru-define-multiple
(lisp-mode
(symbol "nil" "t"))
(emacs-lisp-mode
(word "add" "remove")))
#+end_src
* License
This package is licensed by GPLv3. See [[file:LICENSE][LICENSE]].