unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* [NonGNU ELPA] New package: devil
@ 2023-05-09  1:57 Susam Pal
  2023-05-09  8:42 ` Philip Kaludercic
  0 siblings, 1 reply; 36+ messages in thread
From: Susam Pal @ 2023-05-09  1:57 UTC (permalink / raw)
  To: emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 880 bytes --]

Hello!

I am the author and maintainer of a new package named Devil. This package
intercepts keystrokes entered by the user and applies translation rules to
translate the keystrokes into Emacs key sequences. It supports three types
of rules: special keys that map to custom commands that are invoked
immediately prior to any translations, translation rules to translate Devil
key sequences to regular Emacs key sequences, and repeatable keys to allow
a Devil key sequence to be repeated by typing the last keystroke over and
over again using a transient map.

See the README at https://github.com/susam/devil for more details.

Also, see https://www.reddit.com/r/emacs/comments/13aj99j/ for some
discussion on this new package.

Please let me know if this package can be added to NonGNU ELPA. If there
are any questions or feedback about this, please let me know.

Regards,
Susam

[-- Attachment #1.2: Type: text/html, Size: 1061 bytes --]

[-- Attachment #2: 0001-elpa-packages-devil-New-package.patch --]
[-- Type: application/octet-stream, Size: 669 bytes --]

From 3499d93502b130b1dcb8a648e73e7a614cd24abd Mon Sep 17 00:00:00 2001
From: Susam Pal <susam@susam.net>
Date: Tue, 9 May 2023 02:36:08 +0100
Subject: [PATCH] * elpa-packages (devil): New package

---
 elpa-packages | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/elpa-packages b/elpa-packages
index c333cc8bb3..f6fd68edaf 100644
--- a/elpa-packages
+++ b/elpa-packages
@@ -112,6 +112,8 @@
 
  (devhelp               :url "https://codeberg.org/akib/emacs-devhelp")
 
+ (devil                 :url "https://github.com/susam/devil")
+
  (diff-ansi		:url "https://codeberg.org/ideasman42/emacs-diff-ansi"
   :ignored-files ("LICENSE"))
 
-- 
2.32.0 (Apple Git-132)


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-09  1:57 [NonGNU ELPA] New package: devil Susam Pal
@ 2023-05-09  8:42 ` Philip Kaludercic
  2023-05-09  8:52   ` Eli Zaretskii
  2023-05-09 20:56   ` Susam Pal
  0 siblings, 2 replies; 36+ messages in thread
From: Philip Kaludercic @ 2023-05-09  8:42 UTC (permalink / raw)
  To: Susam Pal; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 747 bytes --]

Susam Pal <susam.pal@gmail.com> writes:

> Hello!
>
> I am the author and maintainer of a new package named Devil. This package
> intercepts keystrokes entered by the user and applies translation rules to
> translate the keystrokes into Emacs key sequences. It supports three types
> of rules: special keys that map to custom commands that are invoked
> immediately prior to any translations, translation rules to translate Devil
> key sequences to regular Emacs key sequences, and repeatable keys to allow
> a Devil key sequence to be repeated by typing the last keystroke over and
> over again using a transient map.
>
> See the README at https://github.com/susam/devil for more details.

Looks interesting, here is a diff with a few comments:


[-- Attachment #2: Type: text/plain, Size: 14413 bytes --]

diff -u /home/philip/devil.el.1 /home/philip/devil.el
--- /home/philip/devil.el.1	2023-05-09 10:37:55.243222106 +0200
+++ /home/philip/devil.el	2023-05-09 10:39:50.110922443 +0200
@@ -36,34 +36,42 @@
 ;; key sequences without using modifier keys.
 
 ;;; Code:
+
+(defgroup devil '()
+  "Minor mode for Devil-like command entering." ;is there a clearer description?
+  :prefix "devil-"
+  :group 'editing)
+
 (defconst devil-version "0.2.0"
   "Devil version number.")
 
-(defun devil-show-version ()
+(defun devil-show-version ()		;is this really needed?
   "Show Devil version number in the echo area."
   (interactive)
   (message "Devil %s" devil-version))
 
-(defvar devil-key ","
+(defcustom devil-key ","
   "The key sequence that begins Devil input.
 
 The key sequence must be specified in the format returned by `C-h
-k' (`describe-key'). This variable should be set before enabling
-Devil mode for it to take effect.")
-
-(defvar devil-lighter " Devil"
-  "String displayed on the mode line when Devil mode is enabled.")
+k' (`describe-key').  This variable should be set before enabling
+Devil mode for it to take effect."
+  :type 'key-sequence)
+
+(defcustom devil-lighter " Devil"
+  "String displayed on the mode line when Devil mode is enabled."
+  :type 'string)
 
 (defvar devil-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map (kbd devil-key) #'devil)
+    (define-key map devil-key #'devil)
     map)
   "Keymap to wake up Devil when `devil-key' is typed.
 
 By default, only `devil-key' is added to this keymap so that
-Devil can be activated using it. To support multiple activation
+Devil can be activated using it.  To support multiple activation
 keys, this variable may be modified to a new keymap that defines
-multiple different keys to activate Devil. This variable should
+multiple different keys to activate Devil.  This variable should
 be modified before loading Devil for it to take effect.")
 
 ;;;###autoload
@@ -74,15 +82,16 @@
 
 ;;;###autoload
 (define-globalized-minor-mode
-  global-devil-mode devil-mode devil--on :group 'devil
+  global-devil-mode devil-mode devil--on ;; :group 'devil (not needed with the defgroup above)
   (if global-devil-mode (devil-add-extra-keys) (devil-remove-extra-keys)))
 
 (defun devil--on ()
   "Turn Devil mode on."
   (devil-mode 1))
 
-(defvar devil-logging nil
-  "Non-nil if and only if Devil should print log messages.")
+(defcustom devil-logging nil
+  "Non-nil if and only if Devil should print log messages."
+  :type 'boolean)
 
 (defvar devil-special-keys
   (list (cons "%k %k" (lambda () (interactive) (devil-run-key "%k")))
@@ -91,12 +100,12 @@
   "Special Devil keys that are executed as soon as they are typed.
 
 The value of this variable is an alist where each key represents
-a Devil key sequence. If a Devil key sequence matches any key in
+a Devil key sequence.  If a Devil key sequence matches any key in
 this alist, the function or lambda in the corresponding value is
-invoked. The format control specifier `%k' may be used to
+invoked.  The format control specifier `%k' may be used to
 represent `devil-key' in the keys.")
 
-(defvar devil-translations
+(defcustom devil-translations
   (list (cons "%k z" "C-")
         (cons "%k %k" "%k")
         (cons "%k m m" "M-")
@@ -108,12 +117,13 @@
 a translation rule that is applied on the Devil key sequence read
 from the user to obtain the Emacs key sequence to be executed.
 The translation rules are applied in the sequence they occur in
-the alist. For each rule, if the key occurs anywhere in the Devil
+the alist.  For each rule, if the key occurs anywhere in the Devil
 key sequence, it is replaced with the corresponding value in the
-translation rule. The format control specifier `%k' may be used
-to represent `devil-key' in the keys.")
+translation rule.  The format control specifier `%k' may be used
+to represent `devil-key' in the keys."
+  :type '(alist :key-type string :value-type string))
 
-(defvar devil-repeatable-keys
+(defcustom devil-repeatable-keys
   (list "%k p"
         "%k n"
         "%k f"
@@ -128,8 +138,9 @@
 
 The value of this variable is a list where each item represents a
 key sequence that may be repeated merely by typing the last
-character in the key sequence. The format control specified `%k'
-may be used to represent `devil-key' in the keys.")
+character in the key sequence.  The format control specified `%k'
+may be used to represent `devil-key' in the keys."
+  :type '(repeat string))
 
 (defun devil-run-key (key)
   "Execute the given key sequence KEY.
@@ -140,7 +151,7 @@
   (dolist (key (split-string key))
     (if (string= key "%k") (insert devil-key) (execute-kbd-macro (kbd key)))))
 
-(defvar devil--saved-keys
+(defvar devil--saved-keys nil		;otherwise `devil--saved-keys' is assigned a string
   "Original key bindings saved by Devil.")
 
 (defun devil-add-extra-keys ()
@@ -160,8 +171,9 @@
 
 (defun devil--original-keys-to-be-saved ()
   "Return an alist of keys that will be modified by Devil."
-  (list (cons 'isearch-comma (lookup-key isearch-mode-map (kbd devil-key)))
-        (cons 'universal-u (lookup-key universal-argument-map (kbd "u")))))
+  ;; Weak suggestions
+  `((isearch-comma . ,(lookup-key isearch-mode-map (kbd devil-key)))
+    universal-u . ,(lookup-key universal-argument-map (kbd "u"))))
 
 (defun devil ()
   "Wake up Devil to read and translate Devil key sequences."
@@ -178,27 +190,30 @@
 after translation to Emacs key sequence.
 
 The argument KEY is a vector that represents the key sequence
-read so far. This function reads a new key from the user, appends
+read so far.  This function reads a new key from the user, appends
 it to KEY, and then checks if the result is a valid key sequence
-or an undefined key sequence. If the result is a valid key
+or an undefined key sequence.  If the result is a valid key
 sequence for a special key command or an Emacs command, then the
-command is executed. Otherwise, this function calls itself
+command is executed.  Otherwise, this function calls itself
 recursively to read yet another key from the user."
   (setq key (vconcat key (vector (read-key (devil--make-prompt key)))))
   (unless (devil--run-command key)
     (devil--read-key key)))
 
-(defvar devil-prompt "Devil: %t"
+(defcustom devil-prompt "Devil: %t"
   "A format control string that determines the Devil prompt.
 
 The following format control sequences are supported:
 
 %k - Devil key sequence read by Devil so far.
 %t - Emacs key sequence translated from Devil key sequence read so far.
-%% - The percent sign.")
+%% - The percent sign."
+  :type 'string)
 
 (defun devil--make-prompt (key)
   "Create Devil prompt based on the given KEY."
+  ;; If you are interested in adding Compat as a dependency, you can
+  ;; make use of `format-spec' without raining the minimum version.
   (let ((result devil-prompt)
         (controls (list (cons "%k" (key-description key))
                         (cons "%t" (devil-translate key))
@@ -210,16 +225,16 @@
 (defun devil--run-command (key)
   "Try running the command bound to the key sequence in KEY.
 
-KEY is a vector that represents a sequence of keystrokes. If KEY
+KEY is a vector that represents a sequence of keystrokes.  If KEY
 is found to be a special key in `devil-special-keys', the
 corresponding special command is executed immediately and t is
 returned.
 
 Otherwise, it is translated to an Emacs key sequence using
-`devil-translations'. If the resulting Emacs key sequence is
+`devil-translations'.  If the resulting Emacs key sequence is
 found to be a complete key sequence, the command it is bound to
-is executed interactively and t is returned. If it is found to be
-an undefined key sequence, then t is returned. If the resulting
+is executed interactively and t is returned.  If it is found to be
+an undefined key sequence, then t is returned.  If the resulting
 Emacs key sequence is found to be an incomplete key sequence,
 then nil is returned."
   (devil--log "Trying to execute key: %s" (key-description key))
@@ -231,7 +246,7 @@
 
 If the given key sequence KEY is found to be a special key in
 `devil-special-keys', the corresponding special command is
-executed, and t is returned. Otherwise nil is returned."
+executed, and t is returned.  Otherwise nil is returned."
   (catch 'break
     (dolist (entry devil-special-keys)
       (when (string= (key-description key) (devil-format (car entry)))
@@ -245,14 +260,14 @@
 
 After translating KEY to an Emacs key sequence, if the resulting
 key sequence turns out to be an incomplete key, then nil is
-returned. If it turns out to be a complete key sequence, the
-corresponding Emacs command is executed, and t is returned. If it
-turns out to be an undefined key sequence, t is returned. The
+returned.  If it turns out to be a complete key sequence, the
+corresponding Emacs command is executed, and t is returned.  If it
+turns out to be an undefined key sequence, t is returned.  The
 return value t indicates to the caller that no more Devil key
 sequences should be read from the user."
   (let* ((described-key (key-description key))
          (translated-key (devil-translate key))
-         (parsed-key (condition-case nil (kbd translated-key) (error nil)))
+         (parsed-key (condition-case nil (kbd translated-key) (error nil))) ;or `ignore-errors'
          (binding (when parsed-key (key-binding parsed-key))))
     (cond ((string-match "[ACHMSs]-$" translated-key)
            (devil--log "Ignoring incomplete key: %s => %s"
@@ -307,27 +322,27 @@
   "Update variables that maintain command loop information.
 
 The given KEY and BINDING is used to update variables that
-maintain command loop information. This allows the commands that
+maintain command loop information.  This allows the commands that
 depend on them behave as if they were being invoked directly with
 the original Emacs key sequence."
   ;;
   ;; Set `last-command-event' so that `digit-argument' can determine
-  ;; the correct digit for key sequences like , 5 (C-5). See M-x
+  ;; the correct digit for key sequences like , 5 (C-5).  See M-x
   ;; find-function RET digit-argument RET for details.
   (setq last-command-event (aref key (- (length key) 1)))
   ;;
   ;; Set `this-command' to make several commands like , z SPC , z SPC
-  ;; (C-SPC C-SPC) and , p (C-p) work correctly. Emacs copies
-  ;; `this-command' to `last-command'. Both variables are used by
+  ;; (C-SPC C-SPC) and , p (C-p) work correctly.  Emacs copies
+  ;; `this-command' to `last-command'.  Both variables are used by
   ;; `set-mark-command' to decide whether to activate/deactivate the
-  ;; current mark. The first variable is used by vertical motion
-  ;; commands to keep the cursor at the `temporary-goal-column'. There
+  ;; current mark.  The first variable is used by vertical motion
+  ;; commands to keep the cursor at the `temporary-goal-column'.  There
   ;; may be other commands too that depend on this variable.
   (setq this-command binding)
   ;;
   ;; Set `real-this-command' to make , x z (C-x z) work correctly.
   ;; Emacs copies it to `last-repeatable-command' which is then used
-  ;; by repeat. See the following for more details:
+  ;; by repeat.  See the following for more details:
   ;;
   ;;   - M-x find-function RET repeat RET
   ;;   - C-h v last-repeatable-command RET
@@ -337,11 +352,12 @@
 (defun devil--log-command-loop-info ()
   "Log command loop information for debugging purpose."
   (devil--log
-   (concat "Found "
-           (format "current-prefix-arg: %s; " current-prefix-arg)
-           (format "this-command: %s; " this-command)
-           (format "last-command: %s; " last-command)
-           (format "last-repeatable-command: %s" last-repeatable-command))))
+   (format "Found current-prefix-arg: %s; \
+this-command: %s; last-command: %s; last-repeatable-command: %s"
+	   current-prefix-arg
+	   this-command
+	   last-command
+	   last-repeatable-command)))
 
 (defun devil--repeatable-key-p (described-key)
   "Return t iff DESCRIBED-KEY belongs to `devil-repeatable-keys'."
@@ -379,28 +395,25 @@
   (when devil-logging
     (apply #'message (concat "Devil: " format-string) args)))
 
-(defmacro devil--assert (form)
-  "Evaluate FORM and cause error if the result is nil."
-  `(unless ,form
-     (error "Assertion failed: %s" ',form)))
-
-(defun devil--tests ()
-  "Test Devil functions assuming Devil has not been customized."
-  (devil--assert (devil--invalid-key-p ""))
-  (devil--assert (devil--invalid-key-p "C-x-C-f"))
-  (devil--assert (devil--invalid-key-p "C-x CC-f"))
-  (devil--assert (not (devil--invalid-key-p "C-x C-f")))
-  (devil--assert (not (devil--invalid-key-p "C-M-x")))
-  (devil--assert (string= (devil-translate (vconcat ",")) "C-"))
-  (devil--assert (string= (devil-translate (vconcat ",x")) "C-x"))
-  (devil--assert (string= (devil-translate (vconcat ",x,")) "C-x C-"))
-  (devil--assert (string= (devil-translate (vconcat ",x,f")) "C-x C-f"))
-  (devil--assert (string= (devil-translate (vconcat ",,")) ","))
-  (devil--assert (string= (devil-translate (vconcat ",,,,")) ", ,"))
-  (devil--assert (string= (devil-translate (vconcat ",mx")) "C-M-x"))
-  (devil--assert (string= (devil-translate (vconcat ",mmx")) "M-x"))
-  (devil--assert (string= (devil-translate (vconcat ",mmm")) "M-m"))
-  (message "Done"))
+(ert-deftest devil-invalid-key-p ()
+  "Test if `devil--invalid-key-p' words as expected."
+  (should (devil--invalid-key-p ""))
+  (should (devil--invalid-key-p "C-x-C-f"))
+  (should (devil--invalid-key-p "C-x CC-f"))
+  (should (not (devil--invalid-key-p "C-x C-f")))
+  (should (not (devil--invalid-key-p "C-M-x"))))
+
+(ert-deftest devil-translate ()
+  "Test if `devil-translate' works as expected."
+  (should (string= (devil-translate (vconcat ",")) "C-"))
+  (should (string= (devil-translate (vconcat ",x")) "C-x"))
+  (should (string= (devil-translate (vconcat ",x,")) "C-x C-"))
+  (should (string= (devil-translate (vconcat ",x,f")) "C-x C-f"))
+  (should (string= (devil-translate (vconcat ",,")) ","))
+  (should (string= (devil-translate (vconcat ",,,,")) ", ,"))
+  (should (string= (devil-translate (vconcat ",mx")) "C-M-x"))
+  (should (string= (devil-translate (vconcat ",mmx")) "M-x"))
+  (should (string= (devil-translate (vconcat ",mmm")) "M-m")))
 
 (provide 'devil)
 

Diff finished.  Tue May  9 10:39:57 2023

[-- Attachment #3: Type: text/plain, Size: 1285 bytes --]


> Also, see https://www.reddit.com/r/emacs/comments/13aj99j/ for some
> discussion on this new package.
>
> Please let me know if this package can be added to NonGNU ELPA. If there
> are any questions or feedback about this, please let me know.

I see no reason why not.  Thanks for contributing.

One point I have already mentioned on IRC is that a separate manual and
a shorter README would be nice.  We can generate a TeXinfo manual from
either .texi or .org files, would you be interested in setting that up?

> Regards,
> Susam
> From 3499d93502b130b1dcb8a648e73e7a614cd24abd Mon Sep 17 00:00:00 2001
> From: Susam Pal <susam@susam.net>
> Date: Tue, 9 May 2023 02:36:08 +0100
> Subject: [PATCH] * elpa-packages (devil): New package
>
> ---
>  elpa-packages | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/elpa-packages b/elpa-packages
> index c333cc8bb3..f6fd68edaf 100644
> --- a/elpa-packages
> +++ b/elpa-packages
> @@ -112,6 +112,8 @@
>  
>   (devhelp               :url "https://codeberg.org/akib/emacs-devhelp")
>  
> + (devil                 :url "https://github.com/susam/devil")

As you have a CHANGES.md file, we can add a :news entry here as well.

> +
>   (diff-ansi		:url "https://codeberg.org/ideasman42/emacs-diff-ansi"
>    :ignored-files ("LICENSE"))

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-09  8:42 ` Philip Kaludercic
@ 2023-05-09  8:52   ` Eli Zaretskii
  2023-05-09  8:58     ` Philip Kaludercic
  2023-05-09 20:56   ` Susam Pal
  1 sibling, 1 reply; 36+ messages in thread
From: Eli Zaretskii @ 2023-05-09  8:52 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: susam.pal, emacs-devel

> From: Philip Kaludercic <philipk@posteo.net>
> Cc: emacs-devel@gnu.org
> Date: Tue, 09 May 2023 08:42:20 +0000
> 
> > Hello!
> >
> > I am the author and maintainer of a new package named Devil. This package
> > intercepts keystrokes entered by the user and applies translation rules to
> > translate the keystrokes into Emacs key sequences. It supports three types
> > of rules: special keys that map to custom commands that are invoked
> > immediately prior to any translations, translation rules to translate Devil
> > key sequences to regular Emacs key sequences, and repeatable keys to allow
> > a Devil key sequence to be repeated by typing the last keystroke over and
> > over again using a transient map.
> >
> > See the README at https://github.com/susam/devil for more details.
> 
> Looks interesting, here is a diff with a few comments:

Why call this package by such a strange name?  It says nothing at all
about the package's purpose.  Would it be possible to rename it,
please?

Thanks.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-09  8:52   ` Eli Zaretskii
@ 2023-05-09  8:58     ` Philip Kaludercic
  2023-05-09 18:19       ` chad
  0 siblings, 1 reply; 36+ messages in thread
From: Philip Kaludercic @ 2023-05-09  8:58 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: susam.pal, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Philip Kaludercic <philipk@posteo.net>
>> Cc: emacs-devel@gnu.org
>> Date: Tue, 09 May 2023 08:42:20 +0000
>> 
>> > Hello!
>> >
>> > I am the author and maintainer of a new package named Devil. This package
>> > intercepts keystrokes entered by the user and applies translation rules to
>> > translate the keystrokes into Emacs key sequences. It supports three types
>> > of rules: special keys that map to custom commands that are invoked
>> > immediately prior to any translations, translation rules to translate Devil
>> > key sequences to regular Emacs key sequences, and repeatable keys to allow
>> > a Devil key sequence to be repeated by typing the last keystroke over and
>> > over again using a transient map.
>> >
>> > See the README at https://github.com/susam/devil for more details.
>> 
>> Looks interesting, here is a diff with a few comments:
>
> Why call this package by such a strange name?  It says nothing at all
> about the package's purpose.  Would it be possible to rename it,
> please?

I am guessing that this is a pun on "evil-mode", but I am inclined to
agree.  At least "evil" stands for "extensible vi layer for Emacs".

> Thanks.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-09  8:58     ` Philip Kaludercic
@ 2023-05-09 18:19       ` chad
  2023-05-09 22:07         ` Susam Pal
  0 siblings, 1 reply; 36+ messages in thread
From: chad @ 2023-05-09 18:19 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: Eli Zaretskii, susam.pal, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 536 bytes --]

>
> I am guessing that this is a pun on "evil-mode", but I am inclined to
> agree.  At least "evil" stands for "extensible vi layer for Emacs".
>

Semantically, it's something of a cross between the popular packages "evil
mode" and "god mode". I do understand that it's pretty strongly 'inside
baseball'[1], but it's also (IMHO) the sort of idiosyncratic package that
one would usually not expect new-to-emacs users to pick up right out of the
gate.

Hope that helps,
~Chad

[1] https://en.wikipedia.org/wiki/Inside_baseball_(metaphor)

[-- Attachment #2: Type: text/html, Size: 969 bytes --]

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-09  8:42 ` Philip Kaludercic
  2023-05-09  8:52   ` Eli Zaretskii
@ 2023-05-09 20:56   ` Susam Pal
  2023-05-10  6:09     ` Philip Kaludercic
  1 sibling, 1 reply; 36+ messages in thread
From: Susam Pal @ 2023-05-09 20:56 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 18237 bytes --]

Philip Kaludercic <philipk@posteo.net> wrote:
> Susam Pal <susam.pal@gmail.com> writes:
>
> > Hello!
> >
> > I am the author and maintainer of a new package named Devil. This package
> > intercepts keystrokes entered by the user and applies translation rules to
> > translate the keystrokes into Emacs key sequences. It supports three types
> > of rules: special keys that map to custom commands that are invoked
> > immediately prior to any translations, translation rules to translate Devil
> > key sequences to regular Emacs key sequences, and repeatable keys to allow
> > a Devil key sequence to be repeated by typing the last keystroke over and
> > over again using a transient map.
> >
> > See the README at https://github.com/susam/devil for more details.
>
> Looks interesting, here is a diff with a few comments:

Thanks for the review and the diff! The code looks much better with
these changes. Like we discussed a little while ago in the #emacs
channel, if you send me the patches, I'll apply it to the code.

>
> diff -u /home/philip/devil.el.1 /home/philip/devil.el
> --- /home/philip/devil.el.1    2023-05-09 10:37:55.243222106 +0200
> +++ /home/philip/devil.el    2023-05-09 10:39:50.110922443 +0200
> @@ -36,34 +36,42 @@
>  ;; key sequences without using modifier keys.
>
>  ;;; Code:
> +
> +(defgroup devil '()
> +  "Minor mode for Devil-like command entering." ;is there a clearer description?
> +  :prefix "devil-"
> +  :group 'editing)
> +
>  (defconst devil-version "0.2.0"
>    "Devil version number.")

Yes, a possible description could be:

"Minor mode for intercepting and translating key sequences."

>
> -(defun devil-show-version ()
> +(defun devil-show-version ()        ;is this really needed?
>    "Show Devil version number in the echo area."
>    (interactive)
>    (message "Devil %s" devil-version))

Picked this style from markdown-mode:
https://github.com/jrblevin/markdown-mode/blob/master/markdown-mode.el#L9762-L9765

Although not strictly necessary, I thought it does not hurt to provide
a convenient command here.

> -(defvar devil-key ","
> +(defcustom devil-key ","
>    "The key sequence that begins Devil input.
>
>  The key sequence must be specified in the format returned by `C-h
> -k' (`describe-key'). This variable should be set before enabling
> -Devil mode for it to take effect.")
> -
> -(defvar devil-lighter " Devil"
> -  "String displayed on the mode line when Devil mode is enabled.")
> +k' (`describe-key').  This variable should be set before enabling
> +Devil mode for it to take effect."
> +  :type 'key-sequence)
> +
> +(defcustom devil-lighter " Devil"
> +  "String displayed on the mode line when Devil mode is enabled."
> +  :type 'string)
>
>  (defvar devil-mode-map
>    (let ((map (make-sparse-keymap)))
> -    (define-key map (kbd devil-key) #'devil)
> +    (define-key map devil-key #'devil)
>      map)
>    "Keymap to wake up Devil when `devil-key' is typed.
>
>  By default, only `devil-key' is added to this keymap so that
> -Devil can be activated using it. To support multiple activation
> +Devil can be activated using it.  To support multiple activation
>  keys, this variable may be modified to a new keymap that defines
> -multiple different keys to activate Devil. This variable should
> +multiple different keys to activate Devil.  This variable should
>  be modified before loading Devil for it to take effect.")
>
>  ;;;###autoload
> @@ -74,15 +82,16 @@
>
>  ;;;###autoload
>  (define-globalized-minor-mode
> -  global-devil-mode devil-mode devil--on :group 'devil
> +  global-devil-mode devil-mode devil--on ;; :group 'devil (not needed with the defgroup above)
>    (if global-devil-mode (devil-add-extra-keys) (devil-remove-extra-keys)))
>
>  (defun devil--on ()
>    "Turn Devil mode on."
>    (devil-mode 1))
>
> -(defvar devil-logging nil
> -  "Non-nil if and only if Devil should print log messages.")
> +(defcustom devil-logging nil
> +  "Non-nil if and only if Devil should print log messages."
> +  :type 'boolean)
>
>  (defvar devil-special-keys
>    (list (cons "%k %k" (lambda () (interactive) (devil-run-key "%k")))
> @@ -91,12 +100,12 @@
>    "Special Devil keys that are executed as soon as they are typed.
>
>  The value of this variable is an alist where each key represents
> -a Devil key sequence. If a Devil key sequence matches any key in
> +a Devil key sequence.  If a Devil key sequence matches any key in
>  this alist, the function or lambda in the corresponding value is
> -invoked. The format control specifier `%k' may be used to
> +invoked.  The format control specifier `%k' may be used to
>  represent `devil-key' in the keys.")
>
> -(defvar devil-translations
> +(defcustom devil-translations
>    (list (cons "%k z" "C-")
>          (cons "%k %k" "%k")
>          (cons "%k m m" "M-")
> @@ -108,12 +117,13 @@
>  a translation rule that is applied on the Devil key sequence read
>  from the user to obtain the Emacs key sequence to be executed.
>  The translation rules are applied in the sequence they occur in
> -the alist. For each rule, if the key occurs anywhere in the Devil
> +the alist.  For each rule, if the key occurs anywhere in the Devil
>  key sequence, it is replaced with the corresponding value in the
> -translation rule. The format control specifier `%k' may be used
> -to represent `devil-key' in the keys.")
> +translation rule.  The format control specifier `%k' may be used
> +to represent `devil-key' in the keys."
> +  :type '(alist :key-type string :value-type string))
>
> -(defvar devil-repeatable-keys
> +(defcustom devil-repeatable-keys
>    (list "%k p"
>          "%k n"
>          "%k f"
> @@ -128,8 +138,9 @@
>
>  The value of this variable is a list where each item represents a
>  key sequence that may be repeated merely by typing the last
> -character in the key sequence. The format control specified `%k'
> -may be used to represent `devil-key' in the keys.")
> +character in the key sequence.  The format control specified `%k'
> +may be used to represent `devil-key' in the keys."
> +  :type '(repeat string))
>
>  (defun devil-run-key (key)
>    "Execute the given key sequence KEY.
> @@ -140,7 +151,7 @@
>    (dolist (key (split-string key))
>      (if (string= key "%k") (insert devil-key) (execute-kbd-macro (kbd key)))))
>
> -(defvar devil--saved-keys
> +(defvar devil--saved-keys nil        ;otherwise `devil--saved-keys' is assigned a string
>    "Original key bindings saved by Devil.")
>
>  (defun devil-add-extra-keys ()
> @@ -160,8 +171,9 @@
>
>  (defun devil--original-keys-to-be-saved ()
>    "Return an alist of keys that will be modified by Devil."
> -  (list (cons 'isearch-comma (lookup-key isearch-mode-map (kbd devil-key)))
> -        (cons 'universal-u (lookup-key universal-argument-map (kbd "u")))))
> +  ;; Weak suggestions
> +  `((isearch-comma . ,(lookup-key isearch-mode-map (kbd devil-key)))
> +    universal-u . ,(lookup-key universal-argument-map (kbd "u"))))
>
>  (defun devil ()
>    "Wake up Devil to read and translate Devil key sequences."
> @@ -178,27 +190,30 @@
>  after translation to Emacs key sequence.
>
>  The argument KEY is a vector that represents the key sequence
> -read so far. This function reads a new key from the user, appends
> +read so far.  This function reads a new key from the user, appends
>  it to KEY, and then checks if the result is a valid key sequence
> -or an undefined key sequence. If the result is a valid key
> +or an undefined key sequence.  If the result is a valid key
>  sequence for a special key command or an Emacs command, then the
> -command is executed. Otherwise, this function calls itself
> +command is executed.  Otherwise, this function calls itself
>  recursively to read yet another key from the user."
>    (setq key (vconcat key (vector (read-key (devil--make-prompt key)))))
>    (unless (devil--run-command key)
>      (devil--read-key key)))
>
> -(defvar devil-prompt "Devil: %t"
> +(defcustom devil-prompt "Devil: %t"
>    "A format control string that determines the Devil prompt.
>
>  The following format control sequences are supported:
>
>  %k - Devil key sequence read by Devil so far.
>  %t - Emacs key sequence translated from Devil key sequence read so far.
> -%% - The percent sign.")
> +%% - The percent sign."
> +  :type 'string)
>
>  (defun devil--make-prompt (key)
>    "Create Devil prompt based on the given KEY."
> +  ;; If you are interested in adding Compat as a dependency, you can
> +  ;; make use of `format-spec' without raining the minimum version.
>    (let ((result devil-prompt)
>          (controls (list (cons "%k" (key-description key))
>                          (cons "%t" (devil-translate key))
> @@ -210,16 +225,16 @@
>  (defun devil--run-command (key)
>    "Try running the command bound to the key sequence in KEY.
>
> -KEY is a vector that represents a sequence of keystrokes. If KEY
> +KEY is a vector that represents a sequence of keystrokes.  If KEY
>  is found to be a special key in `devil-special-keys', the
>  corresponding special command is executed immediately and t is
>  returned.
>
>  Otherwise, it is translated to an Emacs key sequence using
> -`devil-translations'. If the resulting Emacs key sequence is
> +`devil-translations'.  If the resulting Emacs key sequence is
>  found to be a complete key sequence, the command it is bound to
> -is executed interactively and t is returned. If it is found to be
> -an undefined key sequence, then t is returned. If the resulting
> +is executed interactively and t is returned.  If it is found to be
> +an undefined key sequence, then t is returned.  If the resulting
>  Emacs key sequence is found to be an incomplete key sequence,
>  then nil is returned."
>    (devil--log "Trying to execute key: %s" (key-description key))
> @@ -231,7 +246,7 @@
>
>  If the given key sequence KEY is found to be a special key in
>  `devil-special-keys', the corresponding special command is
> -executed, and t is returned. Otherwise nil is returned."
> +executed, and t is returned.  Otherwise nil is returned."
>    (catch 'break
>      (dolist (entry devil-special-keys)
>        (when (string= (key-description key) (devil-format (car entry)))
> @@ -245,14 +260,14 @@
>
>  After translating KEY to an Emacs key sequence, if the resulting
>  key sequence turns out to be an incomplete key, then nil is
> -returned. If it turns out to be a complete key sequence, the
> -corresponding Emacs command is executed, and t is returned. If it
> -turns out to be an undefined key sequence, t is returned. The
> +returned.  If it turns out to be a complete key sequence, the
> +corresponding Emacs command is executed, and t is returned.  If it
> +turns out to be an undefined key sequence, t is returned.  The
>  return value t indicates to the caller that no more Devil key
>  sequences should be read from the user."
>    (let* ((described-key (key-description key))
>           (translated-key (devil-translate key))
> -         (parsed-key (condition-case nil (kbd translated-key) (error nil)))
> +         (parsed-key (condition-case nil (kbd translated-key) (error nil))) ;or `ignore-errors'
>           (binding (when parsed-key (key-binding parsed-key))))
>      (cond ((string-match "[ACHMSs]-$" translated-key)
>             (devil--log "Ignoring incomplete key: %s => %s"
> @@ -307,27 +322,27 @@
>    "Update variables that maintain command loop information.
>
>  The given KEY and BINDING is used to update variables that
> -maintain command loop information. This allows the commands that
> +maintain command loop information.  This allows the commands that
>  depend on them behave as if they were being invoked directly with
>  the original Emacs key sequence."
>    ;;
>    ;; Set `last-command-event' so that `digit-argument' can determine
> -  ;; the correct digit for key sequences like , 5 (C-5). See M-x
> +  ;; the correct digit for key sequences like , 5 (C-5).  See M-x
>    ;; find-function RET digit-argument RET for details.
>    (setq last-command-event (aref key (- (length key) 1)))
>    ;;
>    ;; Set `this-command' to make several commands like , z SPC , z SPC
> -  ;; (C-SPC C-SPC) and , p (C-p) work correctly. Emacs copies
> -  ;; `this-command' to `last-command'. Both variables are used by
> +  ;; (C-SPC C-SPC) and , p (C-p) work correctly.  Emacs copies
> +  ;; `this-command' to `last-command'.  Both variables are used by
>    ;; `set-mark-command' to decide whether to activate/deactivate the
> -  ;; current mark. The first variable is used by vertical motion
> -  ;; commands to keep the cursor at the `temporary-goal-column'. There
> +  ;; current mark.  The first variable is used by vertical motion
> +  ;; commands to keep the cursor at the `temporary-goal-column'.  There
>    ;; may be other commands too that depend on this variable.
>    (setq this-command binding)
>    ;;
>    ;; Set `real-this-command' to make , x z (C-x z) work correctly.
>    ;; Emacs copies it to `last-repeatable-command' which is then used
> -  ;; by repeat. See the following for more details:
> +  ;; by repeat.  See the following for more details:
>    ;;
>    ;;   - M-x find-function RET repeat RET
>    ;;   - C-h v last-repeatable-command RET
> @@ -337,11 +352,12 @@
>  (defun devil--log-command-loop-info ()
>    "Log command loop information for debugging purpose."
>    (devil--log
> -   (concat "Found "
> -           (format "current-prefix-arg: %s; " current-prefix-arg)
> -           (format "this-command: %s; " this-command)
> -           (format "last-command: %s; " last-command)
> -           (format "last-repeatable-command: %s" last-repeatable-command))))
> +   (format "Found current-prefix-arg: %s; \
> +this-command: %s; last-command: %s; last-repeatable-command: %s"
> +       current-prefix-arg
> +       this-command
> +       last-command
> +       last-repeatable-command)))
>
>  (defun devil--repeatable-key-p (described-key)
>    "Return t iff DESCRIBED-KEY belongs to `devil-repeatable-keys'."
> @@ -379,28 +395,25 @@
>    (when devil-logging
>      (apply #'message (concat "Devil: " format-string) args)))
>
> -(defmacro devil--assert (form)
> -  "Evaluate FORM and cause error if the result is nil."
> -  `(unless ,form
> -     (error "Assertion failed: %s" ',form)))
> -
> -(defun devil--tests ()
> -  "Test Devil functions assuming Devil has not been customized."
> -  (devil--assert (devil--invalid-key-p ""))
> -  (devil--assert (devil--invalid-key-p "C-x-C-f"))
> -  (devil--assert (devil--invalid-key-p "C-x CC-f"))
> -  (devil--assert (not (devil--invalid-key-p "C-x C-f")))
> -  (devil--assert (not (devil--invalid-key-p "C-M-x")))
> -  (devil--assert (string= (devil-translate (vconcat ",")) "C-"))
> -  (devil--assert (string= (devil-translate (vconcat ",x")) "C-x"))
> -  (devil--assert (string= (devil-translate (vconcat ",x,")) "C-x C-"))
> -  (devil--assert (string= (devil-translate (vconcat ",x,f")) "C-x C-f"))
> -  (devil--assert (string= (devil-translate (vconcat ",,")) ","))
> -  (devil--assert (string= (devil-translate (vconcat ",,,,")) ", ,"))
> -  (devil--assert (string= (devil-translate (vconcat ",mx")) "C-M-x"))
> -  (devil--assert (string= (devil-translate (vconcat ",mmx")) "M-x"))
> -  (devil--assert (string= (devil-translate (vconcat ",mmm")) "M-m"))
> -  (message "Done"))
> +(ert-deftest devil-invalid-key-p ()
> +  "Test if `devil--invalid-key-p' words as expected."
> +  (should (devil--invalid-key-p ""))
> +  (should (devil--invalid-key-p "C-x-C-f"))
> +  (should (devil--invalid-key-p "C-x CC-f"))
> +  (should (not (devil--invalid-key-p "C-x C-f")))
> +  (should (not (devil--invalid-key-p "C-M-x"))))
> +
> +(ert-deftest devil-translate ()
> +  "Test if `devil-translate' works as expected."
> +  (should (string= (devil-translate (vconcat ",")) "C-"))
> +  (should (string= (devil-translate (vconcat ",x")) "C-x"))
> +  (should (string= (devil-translate (vconcat ",x,")) "C-x C-"))
> +  (should (string= (devil-translate (vconcat ",x,f")) "C-x C-f"))
> +  (should (string= (devil-translate (vconcat ",,")) ","))
> +  (should (string= (devil-translate (vconcat ",,,,")) ", ,"))
> +  (should (string= (devil-translate (vconcat ",mx")) "C-M-x"))
> +  (should (string= (devil-translate (vconcat ",mmx")) "M-x"))
> +  (should (string= (devil-translate (vconcat ",mmm")) "M-m")))
>
>  (provide 'devil)
>
>
> Diff finished.  Tue May  9 10:39:57 2023
>
> --=-=-=
> Content-Type: text/plain
>
>
> > Also, see https://www.reddit.com/r/emacs/comments/13aj99j/ for some
> > discussion on this new package.
> >
> > Please let me know if this package can be added to NonGNU ELPA. If there
> > are any questions or feedback about this, please let me know.
>
> I see no reason why not.  Thanks for contributing.
>
> One point I have already mentioned on IRC is that a separate manual and
> a shorter README would be nice.  We can generate a TeXinfo manual from
> either .texi or .org files, would you be interested in setting that up?

This is a great idea. I have a busy schedule coming up in the next few
weeks, so it may take me a while to do this though. In the meantime,
if someone is willing to help with this, I will gladly accept the
changes.

>
> > Regards,
> > Susam
> > From 3499d93502b130b1dcb8a648e73e7a614cd24abd Mon Sep 17 00:00:00 2001
> > From: Susam Pal <susam@susam.net>
> > Date: Tue, 9 May 2023 02:36:08 +0100
> > Subject: [PATCH] * elpa-packages (devil): New package
> >
> > ---
> >  elpa-packages | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/elpa-packages b/elpa-packages
> > index c333cc8bb3..f6fd68edaf 100644
> > --- a/elpa-packages
> > +++ b/elpa-packages
> > @@ -112,6 +112,8 @@
> >
> >   (devhelp               :url "https://codeberg.org/akib/emacs-devhelp")
> >
> > + (devil                 :url "https://github.com/susam/devil")
>
> As you have a CHANGES.md file, we can add a :news entry here as well.

Attached an updated patch.

>
> > +
> >   (diff-ansi        :url "https://codeberg.org/ideasman42/emacs-diff-ansi"
> >    :ignored-files ("LICENSE"))

I believe we can continue working on the proposed improvements and
make them available in new versions. Is there anything that is
currently a blocker to include this package into NonGNU ELPA?

Regards,
Susam

[-- Attachment #2: 0001-elpa-packages-devil-New-package.patch --]
[-- Type: application/octet-stream, Size: 705 bytes --]

From ef362139ad57f54ab0b672b3900ca57ba363431f Mon Sep 17 00:00:00 2001
From: Susam Pal <susam@susam.net>
Date: Tue, 9 May 2023 21:53:09 +0100
Subject: [PATCH] * elpa-packages (devil): New package

---
 elpa-packages | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/elpa-packages b/elpa-packages
index c333cc8bb3..c8e4486a2a 100644
--- a/elpa-packages
+++ b/elpa-packages
@@ -112,6 +112,11 @@
 
  (devhelp               :url "https://codeberg.org/akib/emacs-devhelp")
 
+ (devil
+  :url "https://github.com/susam/devil"
+  :readme "README.md"
+  :news "CHANGES.md")
+
  (diff-ansi		:url "https://codeberg.org/ideasman42/emacs-diff-ansi"
   :ignored-files ("LICENSE"))
 
-- 
2.32.0 (Apple Git-132)


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-09 18:19       ` chad
@ 2023-05-09 22:07         ` Susam Pal
  0 siblings, 0 replies; 36+ messages in thread
From: Susam Pal @ 2023-05-09 22:07 UTC (permalink / raw)
  To: chad; +Cc: Philip Kaludercic, Eli Zaretskii, emacs-devel

chad <yandros@gmail.com> wrote:
>> I am guessing that this is a pun on "evil-mode", but I am inclined to
>> agree.  At least "evil" stands for "extensible vi layer for Emacs".
>
>
> Semantically, it's something of a cross between the popular packages
> "evil mode" and "god mode". I do understand that it's pretty
> strongly 'inside baseball'[1], but it's also (IMHO) the sort of
> idiosyncratic package that one would usually not expect new-to-emacs
> users to pick up right out of the gate.
>
> Hope that helps,
> ~Chad
>
> [1] https://en.wikipedia.org/wiki/Inside_baseball_(metaphor)
>

Yes, the name is meant to be a humorous reference to both god-mode and
evil-mode.

If the name needs to reflect its purpose, then we could say that Devil
stands for the *Devil's Eccentrically Versatile Interception Layer*.

Regards,
Susam



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-09 20:56   ` Susam Pal
@ 2023-05-10  6:09     ` Philip Kaludercic
  2023-05-10 21:00       ` Susam Pal
  2023-05-10 21:56       ` Richard Stallman
  0 siblings, 2 replies; 36+ messages in thread
From: Philip Kaludercic @ 2023-05-10  6:09 UTC (permalink / raw)
  To: Susam Pal; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1163 bytes --]

Susam Pal <susam.pal@gmail.com> writes:

> Philip Kaludercic <philipk@posteo.net> wrote:
>> Susam Pal <susam.pal@gmail.com> writes:
>>
>> > Hello!
>> >
>> > I am the author and maintainer of a new package named Devil. This package
>> > intercepts keystrokes entered by the user and applies translation rules to
>> > translate the keystrokes into Emacs key sequences. It supports three types
>> > of rules: special keys that map to custom commands that are invoked
>> > immediately prior to any translations, translation rules to translate Devil
>> > key sequences to regular Emacs key sequences, and repeatable keys to allow
>> > a Devil key sequence to be repeated by typing the last keystroke over and
>> > over again using a transient map.
>> >
>> > See the README at https://github.com/susam/devil for more details.
>>
>> Looks interesting, here is a diff with a few comments:
>
> Thanks for the review and the diff! The code looks much better with
> these changes. Like we discussed a little while ago in the #emacs
> channel, if you send me the patches, I'll apply it to the code.

Here are the patches, feel free to modify or leave out whatever you
want:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-devil.el-Update-header-with-more-information.patch --]
[-- Type: text/x-diff, Size: 769 bytes --]

From e1757d9005f82624a1db435f53f250291e177519 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk@posteo.net>
Date: Wed, 10 May 2023 07:36:54 +0200
Subject: [PATCH 1/8] * devil.el: Update header with more information

---
 devil.el | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/devil.el b/devil.el
index 7c5d4ca..5bfb848 100644
--- a/devil.el
+++ b/devil.el
@@ -2,10 +2,11 @@
 
 ;; Copyright (c) 2022-2023 Susam Pal
 
-;; Author: Susam Pal
+;; Author: Susam Pal <susam@susam.net>
+;; Maintainer: Susam Pal <susam@susam.net>
 ;; Version: 0.2.0
 ;; Package-Requires: ((emacs "24.4"))
-;; Keywords: convenience
+;; Keywords: convenience, abbrev
 ;; URL: https://github.com/susam/devil
 
 ;; This file is not part of GNU Emacs.
-- 
2.39.2


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-Remove-custom-version-command.patch --]
[-- Type: text/x-diff, Size: 851 bytes --]

From a2d9b22fe60ec8cdf78c69ea873d3d299c4c42d2 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk@posteo.net>
Date: Wed, 10 May 2023 07:38:34 +0200
Subject: [PATCH 2/8] Remove custom version command.

* devil.el (devil-version, devil-show-version): Remove.

The version of a package can be generically inspected with C-h P devil
RET.
---
 devil.el | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/devil.el b/devil.el
index 5bfb848..fa08c5f 100644
--- a/devil.el
+++ b/devil.el
@@ -37,13 +37,7 @@
 ;; key sequences without using modifier keys.
 
 ;;; Code:
-(defconst devil-version "0.2.0"
-  "Devil version number.")
 
-(defun devil-show-version ()
-  "Show Devil version number in the echo area."
-  (interactive)
-  (message "Devil %s" devil-version))
 
 (defvar devil-key ","
   "The key sequence that begins Devil input.
-- 
2.39.2


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: 0003-Add-devil-customisation-group.patch --]
[-- Type: text/x-diff, Size: 4120 bytes --]

From 324e6f8655a7cad7ca0c9a15fb1f8a119484b292 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk@posteo.net>
Date: Wed, 10 May 2023 07:49:26 +0200
Subject: [PATCH 3/8] Add 'devil' customisation group

* devil.el (devil-key, devil-translations, devil-repeatable-keys,
devil-prompt): Convert to user options.
(global-devil-mode): Remove unnecessary :group tag.
---
 devil.el | 38 ++++++++++++++++++++++++--------------
 1 file changed, 24 insertions(+), 14 deletions(-)

diff --git a/devil.el b/devil.el
index fa08c5f..461537e 100644
--- a/devil.el
+++ b/devil.el
@@ -38,20 +38,26 @@
 
 ;;; Code:
 
+(defgroup devil '()
+  "Minor mode for Devil-like command entering." ;is there a clearer description?
+  :prefix "devil-"
+  :group 'editing)
 
-(defvar devil-key ","
+(defcustom devil-key ","
   "The key sequence that begins Devil input.
 
 The key sequence must be specified in the format returned by `C-h
 k' (`describe-key'). This variable should be set before enabling
-Devil mode for it to take effect.")
+Devil mode for it to take effect."
+  :type 'key-sequence)
 
-(defvar devil-lighter " Devil"
-  "String displayed on the mode line when Devil mode is enabled.")
+(defcustom devil-lighter " Devil"
+  "String displayed on the mode line when Devil mode is enabled."
+  :type 'string)
 
 (defvar devil-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map (kbd devil-key) #'devil)
+    (define-key map devil-key #'devil)
     map)
   "Keymap to wake up Devil when `devil-key' is typed.
 
@@ -69,15 +75,16 @@ be modified before loading Devil for it to take effect.")
 
 ;;;###autoload
 (define-globalized-minor-mode
-  global-devil-mode devil-mode devil--on :group 'devil
+  global-devil-mode devil-mode devil--on
   (if global-devil-mode (devil-add-extra-keys) (devil-remove-extra-keys)))
 
 (defun devil--on ()
   "Turn Devil mode on."
   (devil-mode 1))
 
-(defvar devil-logging nil
-  "Non-nil if and only if Devil should print log messages.")
+(defcustom devil-logging nil
+  "Non-nil if and only if Devil should print log messages."
+  :type 'boolean)
 
 (defvar devil-special-keys
   (list (cons "%k %k" (lambda () (interactive) (devil-run-key "%k")))
@@ -91,7 +98,7 @@ this alist, the function or lambda in the corresponding value is
 invoked. The format control specifier `%k' may be used to
 represent `devil-key' in the keys.")
 
-(defvar devil-translations
+(defcustom devil-translations
   (list (cons "%k z" "C-")
         (cons "%k %k" "%k")
         (cons "%k m m" "M-")
@@ -106,9 +113,10 @@ The translation rules are applied in the sequence they occur in
 the alist. For each rule, if the key occurs anywhere in the Devil
 key sequence, it is replaced with the corresponding value in the
 translation rule. The format control specifier `%k' may be used
-to represent `devil-key' in the keys.")
+to represent `devil-key' in the keys."
+  :type '(alist :key-type string :value-type string))
 
-(defvar devil-repeatable-keys
+(defcustom devil-repeatable-keys
   (list "%k p"
         "%k n"
         "%k f"
@@ -124,7 +132,8 @@ to represent `devil-key' in the keys.")
 The value of this variable is a list where each item represents a
 key sequence that may be repeated merely by typing the last
 character in the key sequence. The format control specified `%k'
-may be used to represent `devil-key' in the keys.")
+may be used to represent `devil-key' in the keys."
+  :type '(repeat string))
 
 (defun devil-run-key (key)
   "Execute the given key sequence KEY.
@@ -183,14 +192,15 @@ recursively to read yet another key from the user."
   (unless (devil--run-command key)
     (devil--read-key key)))
 
-(defvar devil-prompt "Devil: %t"
+(defcustom devil-prompt "Devil: %t"
   "A format control string that determines the Devil prompt.
 
 The following format control sequences are supported:
 
 %k - Devil key sequence read by Devil so far.
 %t - Emacs key sequence translated from Devil key sequence read so far.
-%% - The percent sign.")
+%% - The percent sign."
+  :type 'string)
 
 (defun devil--make-prompt (key)
   "Create Devil prompt based on the given KEY."
-- 
2.39.2


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #5: 0004-Fix-spacing-in-documentation-strings.patch --]
[-- Type: text/x-diff, Size: 8487 bytes --]

From 5896bfa8061709e14a6fd3a94f7039a6b0978d26 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk@posteo.net>
Date: Wed, 10 May 2023 08:00:19 +0200
Subject: [PATCH 4/8] Fix spacing in documentation strings

---
 devil.el | 54 ++++++++++++++++++++++++++++--------------------------
 1 file changed, 28 insertions(+), 26 deletions(-)

diff --git a/devil.el b/devil.el
index 461537e..5f8ecfa 100644
--- a/devil.el
+++ b/devil.el
@@ -47,7 +47,7 @@
   "The key sequence that begins Devil input.
 
 The key sequence must be specified in the format returned by `C-h
-k' (`describe-key'). This variable should be set before enabling
+k' (`describe-key').  This variable should be set before enabling
 Devil mode for it to take effect."
   :type 'key-sequence)
 
@@ -62,9 +62,9 @@ Devil mode for it to take effect."
   "Keymap to wake up Devil when `devil-key' is typed.
 
 By default, only `devil-key' is added to this keymap so that
-Devil can be activated using it. To support multiple activation
+Devil can be activated using it.  To support multiple activation
 keys, this variable may be modified to a new keymap that defines
-multiple different keys to activate Devil. This variable should
+multiple different keys to activate Devil.  This variable should
 be modified before loading Devil for it to take effect.")
 
 ;;;###autoload
@@ -93,9 +93,9 @@ be modified before loading Devil for it to take effect.")
   "Special Devil keys that are executed as soon as they are typed.
 
 The value of this variable is an alist where each key represents
-a Devil key sequence. If a Devil key sequence matches any key in
+a Devil key sequence.  If a Devil key sequence matches any key in
 this alist, the function or lambda in the corresponding value is
-invoked. The format control specifier `%k' may be used to
+invoked.  The format control specifier `%k' may be used to
 represent `devil-key' in the keys.")
 
 (defcustom devil-translations
@@ -110,9 +110,9 @@ The value of this variable is an alist where each item represents
 a translation rule that is applied on the Devil key sequence read
 from the user to obtain the Emacs key sequence to be executed.
 The translation rules are applied in the sequence they occur in
-the alist. For each rule, if the key occurs anywhere in the Devil
+the alist.  For each rule, if the key occurs anywhere in the Devil
 key sequence, it is replaced with the corresponding value in the
-translation rule. The format control specifier `%k' may be used
+translation rule.  The format control specifier `%k' may be used
 to represent `devil-key' in the keys."
   :type '(alist :key-type string :value-type string))
 
@@ -131,7 +131,7 @@ to represent `devil-key' in the keys."
 
 The value of this variable is a list where each item represents a
 key sequence that may be repeated merely by typing the last
-character in the key sequence. The format control specified `%k'
+character in the key sequence.  The format control specified `%k'
 may be used to represent `devil-key' in the keys."
   :type '(repeat string))
 
@@ -182,11 +182,11 @@ translation to Emacs key sequence, or an undefined key sequence
 after translation to Emacs key sequence.
 
 The argument KEY is a vector that represents the key sequence
-read so far. This function reads a new key from the user, appends
+read so far.  This function reads a new key from the user, appends
 it to KEY, and then checks if the result is a valid key sequence
-or an undefined key sequence. If the result is a valid key
+or an undefined key sequence.  If the result is a valid key
 sequence for a special key command or an Emacs command, then the
-command is executed. Otherwise, this function calls itself
+command is executed.  Otherwise, this function calls itself
 recursively to read yet another key from the user."
   (setq key (vconcat key (vector (read-key (devil--make-prompt key)))))
   (unless (devil--run-command key)
@@ -204,6 +204,8 @@ The following format control sequences are supported:
 
 (defun devil--make-prompt (key)
   "Create Devil prompt based on the given KEY."
+  ;; If you are interested in adding Compat as a dependency, you can
+  ;; make use of `format-spec' without raining the minimum version.
   (let ((result devil-prompt)
         (controls (list (cons "%k" (key-description key))
                         (cons "%t" (devil-translate key))
@@ -215,16 +217,16 @@ The following format control sequences are supported:
 (defun devil--run-command (key)
   "Try running the command bound to the key sequence in KEY.
 
-KEY is a vector that represents a sequence of keystrokes. If KEY
+KEY is a vector that represents a sequence of keystrokes.  If KEY
 is found to be a special key in `devil-special-keys', the
 corresponding special command is executed immediately and t is
 returned.
 
 Otherwise, it is translated to an Emacs key sequence using
-`devil-translations'. If the resulting Emacs key sequence is
+`devil-translations'.  If the resulting Emacs key sequence is
 found to be a complete key sequence, the command it is bound to
-is executed interactively and t is returned. If it is found to be
-an undefined key sequence, then t is returned. If the resulting
+is executed interactively and t is returned.  If it is found to be
+an undefined key sequence, then t is returned.  If the resulting
 Emacs key sequence is found to be an incomplete key sequence,
 then nil is returned."
   (devil--log "Trying to execute key: %s" (key-description key))
@@ -236,7 +238,7 @@ then nil is returned."
 
 If the given key sequence KEY is found to be a special key in
 `devil-special-keys', the corresponding special command is
-executed, and t is returned. Otherwise nil is returned."
+executed, and t is returned.  Otherwise nil is returned."
   (catch 'break
     (dolist (entry devil-special-keys)
       (when (string= (key-description key) (devil-format (car entry)))
@@ -250,9 +252,9 @@ executed, and t is returned. Otherwise nil is returned."
 
 After translating KEY to an Emacs key sequence, if the resulting
 key sequence turns out to be an incomplete key, then nil is
-returned. If it turns out to be a complete key sequence, the
-corresponding Emacs command is executed, and t is returned. If it
-turns out to be an undefined key sequence, t is returned. The
+returned.  If it turns out to be a complete key sequence, the
+corresponding Emacs command is executed, and t is returned.  If it
+turns out to be an undefined key sequence, t is returned.  The
 return value t indicates to the caller that no more Devil key
 sequences should be read from the user."
   (let* ((described-key (key-description key))
@@ -312,27 +314,27 @@ read so far."
   "Update variables that maintain command loop information.
 
 The given KEY and BINDING is used to update variables that
-maintain command loop information. This allows the commands that
+maintain command loop information.  This allows the commands that
 depend on them behave as if they were being invoked directly with
 the original Emacs key sequence."
   ;;
   ;; Set `last-command-event' so that `digit-argument' can determine
-  ;; the correct digit for key sequences like , 5 (C-5). See M-x
+  ;; the correct digit for key sequences like , 5 (C-5).  See M-x
   ;; find-function RET digit-argument RET for details.
   (setq last-command-event (aref key (- (length key) 1)))
   ;;
   ;; Set `this-command' to make several commands like , z SPC , z SPC
-  ;; (C-SPC C-SPC) and , p (C-p) work correctly. Emacs copies
-  ;; `this-command' to `last-command'. Both variables are used by
+  ;; (C-SPC C-SPC) and , p (C-p) work correctly.  Emacs copies
+  ;; `this-command' to `last-command'.  Both variables are used by
   ;; `set-mark-command' to decide whether to activate/deactivate the
-  ;; current mark. The first variable is used by vertical motion
-  ;; commands to keep the cursor at the `temporary-goal-column'. There
+  ;; current mark.  The first variable is used by vertical motion
+  ;; commands to keep the cursor at the `temporary-goal-column'.  There
   ;; may be other commands too that depend on this variable.
   (setq this-command binding)
   ;;
   ;; Set `real-this-command' to make , x z (C-x z) work correctly.
   ;; Emacs copies it to `last-repeatable-command' which is then used
-  ;; by repeat. See the following for more details:
+  ;; by repeat.  See the following for more details:
   ;;
   ;;   - M-x find-function RET repeat RET
   ;;   - C-h v last-repeatable-command RET
-- 
2.39.2


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #6: 0005-devil.el-devil-saved-keys-Assign-nil-by-default.patch --]
[-- Type: text/x-diff, Size: 829 bytes --]

From 48510c49d7792915826c9cd5930120b62932b9d6 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk@posteo.net>
Date: Wed, 10 May 2023 08:02:43 +0200
Subject: [PATCH 5/8] * devil.el (devil--saved-keys): Assign nil by default

Otherwise the variable is assigned a string.
---
 devil.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/devil.el b/devil.el
index 5f8ecfa..d67c9da 100644
--- a/devil.el
+++ b/devil.el
@@ -144,7 +144,7 @@ occurrence `devil-key' is inserted into the buffer."
   (dolist (key (split-string key))
     (if (string= key "%k") (insert devil-key) (execute-kbd-macro (kbd key)))))
 
-(defvar devil--saved-keys
+(defvar devil--saved-keys nil		;otherwise `devil--saved-keys' is assigned a string
   "Original key bindings saved by Devil.")
 
 (defun devil-add-extra-keys ()
-- 
2.39.2


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #7: 0006-devil.el-devil-log-command-loop-info-Use-a-single-fo.patch --]
[-- Type: text/x-diff, Size: 1193 bytes --]

From 303fb740e80348ff6e44dba3c87b49edcd3842ff Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk@posteo.net>
Date: Wed, 10 May 2023 08:03:03 +0200
Subject: [PATCH 6/8] * devil.el (devil--log-command-loop-info): Use a single
 'format'

---
 devil.el | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/devil.el b/devil.el
index d67c9da..04229aa 100644
--- a/devil.el
+++ b/devil.el
@@ -344,11 +344,12 @@ the original Emacs key sequence."
 (defun devil--log-command-loop-info ()
   "Log command loop information for debugging purpose."
   (devil--log
-   (concat "Found "
-           (format "current-prefix-arg: %s; " current-prefix-arg)
-           (format "this-command: %s; " this-command)
-           (format "last-command: %s; " last-command)
-           (format "last-repeatable-command: %s" last-repeatable-command))))
+   (format "Found current-prefix-arg: %s; \
+this-command: %s; last-command: %s; last-repeatable-command: %s"
+	   current-prefix-arg
+	   this-command
+	   last-command
+	   last-repeatable-command)))
 
 (defun devil--repeatable-key-p (described-key)
   "Return t iff DESCRIBED-KEY belongs to `devil-repeatable-keys'."
-- 
2.39.2


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #8: 0007-Move-tests-to-separate-file-using-ERT.patch --]
[-- Type: text/x-diff, Size: 3374 bytes --]

From bfbd718aa266244b19c05d98c57d14f1eab41456 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk@posteo.net>
Date: Wed, 10 May 2023 08:05:52 +0200
Subject: [PATCH 7/8] Move tests to separate file using ERT

* devil.el: (devil--assert, devil--tests) Remove.
* devil-tests.el: Create new file.
---
 devil-tests.el | 34 ++++++++++++++++++++++++++++++++++
 devil.el       | 24 ------------------------
 2 files changed, 34 insertions(+), 24 deletions(-)
 create mode 100644 devil-tests.el

diff --git a/devil-tests.el b/devil-tests.el
new file mode 100644
index 0000000..22e7071
--- /dev/null
+++ b/devil-tests.el
@@ -0,0 +1,34 @@
+;;; devil-tests.el --- Tests for devil  -*- lexical-binding: t; -*-
+
+;;; Commentary:
+
+;; Unit tests for the internal devil logic.  Run these with M-x ert
+;; RET devil- RET.
+
+;;; Code:
+
+(require 'ert)
+(require 'devil)
+
+(ert-deftest devil-invalid-key-p ()
+  "Test if `devil--invalid-key-p' words as expected."
+  (should (devil--invalid-key-p ""))
+  (should (devil--invalid-key-p "C-x-C-f"))
+  (should (devil--invalid-key-p "C-x CC-f"))
+  (should (not (devil--invalid-key-p "C-x C-f")))
+  (should (not (devil--invalid-key-p "C-M-x"))))
+
+(ert-deftest devil-translate ()
+  "Test if `devil-translate' works as expected."
+  (should (string= (devil-translate (vconcat ",")) "C-"))
+  (should (string= (devil-translate (vconcat ",x")) "C-x"))
+  (should (string= (devil-translate (vconcat ",x,")) "C-x C-"))
+  (should (string= (devil-translate (vconcat ",x,f")) "C-x C-f"))
+  (should (string= (devil-translate (vconcat ",,")) ","))
+  (should (string= (devil-translate (vconcat ",,,,")) ", ,"))
+  (should (string= (devil-translate (vconcat ",mx")) "C-M-x"))
+  (should (string= (devil-translate (vconcat ",mmx")) "M-x"))
+  (should (string= (devil-translate (vconcat ",mmm")) "M-m")))
+
+(provide 'devil-tests)
+;;; devil-tests.el ends here
diff --git a/devil.el b/devil.el
index 04229aa..e037a3c 100644
--- a/devil.el
+++ b/devil.el
@@ -387,29 +387,5 @@ this-command: %s; last-command: %s; last-repeatable-command: %s"
   (when devil-logging
     (apply #'message (concat "Devil: " format-string) args)))
 
-(defmacro devil--assert (form)
-  "Evaluate FORM and cause error if the result is nil."
-  `(unless ,form
-     (error "Assertion failed: %s" ',form)))
-
-(defun devil--tests ()
-  "Test Devil functions assuming Devil has not been customized."
-  (devil--assert (devil--invalid-key-p ""))
-  (devil--assert (devil--invalid-key-p "C-x-C-f"))
-  (devil--assert (devil--invalid-key-p "C-x CC-f"))
-  (devil--assert (not (devil--invalid-key-p "C-x C-f")))
-  (devil--assert (not (devil--invalid-key-p "C-M-x")))
-  (devil--assert (string= (devil-translate (vconcat ",")) "C-"))
-  (devil--assert (string= (devil-translate (vconcat ",x")) "C-x"))
-  (devil--assert (string= (devil-translate (vconcat ",x,")) "C-x C-"))
-  (devil--assert (string= (devil-translate (vconcat ",x,f")) "C-x C-f"))
-  (devil--assert (string= (devil-translate (vconcat ",,")) ","))
-  (devil--assert (string= (devil-translate (vconcat ",,,,")) ", ,"))
-  (devil--assert (string= (devil-translate (vconcat ",mx")) "C-M-x"))
-  (devil--assert (string= (devil-translate (vconcat ",mmx")) "M-x"))
-  (devil--assert (string= (devil-translate (vconcat ",mmm")) "M-m"))
-  (message "Done"))
-
 (provide 'devil)
-
 ;;; devil.el ends here
-- 
2.39.2


[-- Attachment #9: 0008-Extract-most-of-the-README-into-a-separate-manual.patch --]
[-- Type: text/x-diff, Size: 50315 bytes --]

From f78844cec4a23abe4ebdf4cab82f17b585f524b8 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk@posteo.net>
Date: Wed, 10 May 2023 08:08:21 +0200
Subject: [PATCH 8/8] Extract most of the README into a separate manual

---
 MANUAL.org | 564 ++++++++++++++++++++++++++++++++++++++++++++++++++
 README.md  | 594 +----------------------------------------------------
 2 files changed, 565 insertions(+), 593 deletions(-)
 create mode 100644 MANUAL.org

diff --git a/MANUAL.org b/MANUAL.org
new file mode 100644
index 0000000..3cd3ca9
--- /dev/null
+++ b/MANUAL.org
@@ -0,0 +1,564 @@
+#+title:                Devil Mode
+#+author:               Susam Pal
+#+email:                susam@susam.net
+#+language:             en
+#+options:              ':t toc:nil author:t email:t num:t
+#+texinfo_dir_category: Emacs misc features
+#+texinfo_dir_title:    Devil: (devil-mode)
+#+texinfo_dir_desc:     Minor mode for Devil-like command entering
+
+#+texinfo: @insertcopying
+
+Devil mode intercepts our keystrokes and translates them to Emacs key
+sequences according to a configurable set of translation rules. For
+example, with the default translation rules, when we type =, x , f=,
+Devil translates it to =C-x C-f=.
+
+The choice of the comma key (=,=) to mean the control modifier key
+(=C-=) may seem outrageous. After all, the comma is a very important
+punctuation both in prose as well as in code. Can we really get away
+with using =,= to mean the =C-= modifier? It turns out, this terrible
+idea can be made to work without too much of a hassle. At least it works
+for me! It might work for you too. If it does not, Devil can be
+configured to use another key instead of =,= to mean the =C-= modifier.
+See the section [[#custom-devil-key][Custom Devil Key]] for an example.
+
+A sceptical reader may rightfully ask: If =,= is translated to =C-=, how
+on earth are we going to insert a literal =,= into the text when we need
+to? The section [[#typing-commas][Typing Commas]] answers this. But
+before we get there, we have some fundamentals to cover. Take the plunge
+and see what unfolds! Maybe you will like this! Maybe you will not! If
+you do not like this, you can always retreat to God mode, Evil mode, the
+vanilla key bindings, or whatever piques your fancy!
+
+* Notation
+:PROPERTIES:
+:CUSTOM_ID: notation
+:END:
+A quick note about the notation used in the document: The previous
+example shows that =, x , f= is translated to =C-x C-f=. What this
+really means is that the key sequence ,x,f is translated to ctrl+x
+ctrl+f. We do not really type any space after the commas. The key , is
+directly followed by the key x. However, the key sequence notation used
+in this document contains spaces between each keystroke. This is
+consistent with how key sequences are represented in Emacs in general
+and how Emacs functions like =key-description=, =describe-key=, etc.
+represent key sequences. When we really need to type a space, it is
+represented as =SPC=.
+
+* Install
+:PROPERTIES:
+:CUSTOM_ID: install
+:END:
+** Install Interactively from MELPA
+:PROPERTIES:
+:CUSTOM_ID: install-interactively-from-melpa
+:END:
+Devil is available via [[https://melpa.org/][MELPA]]. You may already
+have a preferred way of installing packages from MELPA. If so, install
+the package named =devil= to get Devil. For the sake of completeness,
+here is a very basic way of installing Devil from MELPA:
+
+1. Add the following to the Emacs initialization file (i.e., =~/.emacs=
+   or =~/.emacs.d/init.el= or =~/.config/emacs/init.el=):
+
+   #+begin_src sh
+     (require 'package)
+     (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
+     (package-initialize)
+   #+end_src
+
+2. Start Emacs with the updated initialization file and then type these
+   commands:
+
+   #+begin_example
+   M-x package-refresh-contents RET
+   M-x package-install RET devil RET
+   #+end_example
+
+3. Confirm that Devil is installed successfully with this command:
+
+   #+begin_example
+   M-x devil-show-version RET
+   #+end_example
+
+4. Enable Devil mode with this command:
+
+   #+begin_example
+   M-x global-devil-mode RET
+   #+end_example
+
+5. Type =, x , f= and watch Devil translate it to =C-x C-f= and invoke
+   the corresponding command.
+
+** Install Automatically from MELPA
+:PROPERTIES:
+:CUSTOM_ID: install-automatically-from-melpa
+:END:
+Here is yet another basic way to install and enable Devil using Elisp:
+
+#+begin_example
+(require 'package)
+(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
+(package-initialize)
+(unless package-archive-contents
+  (package-refresh-contents))
+(unless (package-installed-p 'devil)
+  (package-install 'devil))
+(global-devil-mode)
+(global-set-key (kbd "C-,") 'global-devil-mode)
+#+end_example
+
+Now type =, x , f= and watch Devil translate it to =C-x C-f= and invoke
+the corresponding command. Type =C-,= to disable Devil mode. Type =C-,=
+again to enable it.
+
+** Install from Git Source
+:PROPERTIES:
+:CUSTOM_ID: install-from-git-source
+:END:
+If you prefer obtaining Devil from its Git repository, follow these
+steps:
+
+1. Clone Devil to your system:
+
+   #+begin_src sh
+   git clone https://github.com/susam/devil.git
+   #+end_src
+
+2. Add the following to your Emacs initialization:
+
+   #+begin_example
+   (add-to-list 'load-path "/path/to/devil/")
+   (require 'devil)
+   (global-devil-mode)
+   (global-set-key (kbd "C-,") 'global-devil-mode)
+   #+end_example
+
+3. Start the Emacs editor. Devil mode should now be enabled in all
+   buffers. The modeline of each buffer should show the =Devil= lighter.
+
+4. Type =, x , f= and watch Devil translate it to =C-x C-f= and invoke
+   the corresponding command. Type =C-,= to disable Devil mode. Type
+   =C-,= again to enable it.
+
+* Use Devil
+   :PROPERTIES:
+   :CUSTOM_ID: use-devil
+   :END:
+Assuming vanilla Emacs key bindings have not been changed and Devil has
+not been customised, here are some examples that demonstrate how Devil
+may be used:
+
+1. Type =, x , f= and watch Devil translate it to =C-x C-f= and invoke
+   the find file functionality.
+
+2. Type =, p= to move up one line.
+
+3. To move up multiple lines, type =, p p p= and so on. Some Devil key
+   sequences are repeatable keys. The repeatable Devil key sequences can
+   be repeated by typing the last key of the Devil key sequence over and
+   over again.
+
+4. Another example of a repeatable Devil key sequence is =, f f f= which
+   moves the cursor word by multiple characters. A few other examples of
+   repeatable keys are =, k k k= to kill lines, =, / / /= to undo
+   changs, etc. Type =C-h v devil-repeatable-keys RET= to see the
+   complete list of repeatable keys.
+
+5. Type =, s= and watch Devil translate it to =C-s= and invoke
+   incremental search.
+
+6. Type =, m s= and watch Devil translate it to =C-M-s= and invoke
+   regular-expression-based incremental search. Yes, =m= is translated
+   to =M-=.
+
+7. Type =, m m x= and watch Devil translate it to =M-x= and invoke the
+   corresponding command.
+
+8. Type =, u , f= and watch Devil translate it to =C-u C-f= and move the
+   cursor forward by 4 characters.
+
+9. Type =, u u , f= and the cursor moves forward by 16 characters. Devil
+   uses its translation rules and an additional keymap to make the input
+   key sequence behave like =C-u C-u C-f= which moves the cursor forward
+   by 16 characters.
+
+10. Type =, SPC= to type a comma followed by space. This is a special
+    key sequence to make it convenient to type a comma in the text. Note
+    that this sacrifices the use of =, SPC= to mean =C-SPC= which could
+    have been a convenient way to set a mark.
+
+11. Type =, z SPC= and watch Devil translate it to =C-SPC= and set a
+    mark. Yes, =, z= is translated to =C-= too.
+
+12. Similarly, type =, RET= to type a comma followed by the return key.
+    This is another special key.
+
+13. Type =, ,= to type a single comma. This special key is useful for
+    cases when you really need to type a single literal comma.
+
+* Typing Commas
+   :PROPERTIES:
+   :CUSTOM_ID: typing-commas
+   :END:
+Devil makes the questionable choice of using the comma as its activation
+key. As illustrated in the previous section, typing =, x , f= produces
+the same effect as typing =C-x C-f=. One might naturally wonder how then
+we are supposed to type literal commas.
+
+Most often when we edit text, we do not really type a comma in
+isolation. Often we immediately follow the comma with a space or a
+newline. This assumption usually holds good while editing regular text.
+However, this assumption may not hold in some situations, like while
+working with code when we need to add a single comma at the end of an
+existing line.
+
+In scenarios where the above assumption holds good, typing =, SPC=
+inserts a comma and a space. Similarly, typing =, RET= inserts a comma
+and a newline.
+
+In scenarios, when we do need to type a single comma, type =, ,=
+instead.
+
+Also, it is worth mentioning here that if all this fiddling with the
+comma key feels clumsy, we could always customise the Devil key to
+something else that feels better. We could also disable Devil mode
+temporarily and enable it again later with =C-,= as explained in section
+[[#use-devil][Use Devil]].
+
+* Devil Reader
+   :PROPERTIES:
+   :CUSTOM_ID: devil-reader
+   :END:
+The following points briefly describe how Devil reads Devil key
+sequences, translates them to Emacs key sequences, and runs commands
+bound to the key sequences:
+
+1. As soon as the Devil key is typed (which is =,= by default), Devil
+   wakes up and starts reading Devil key sequences. Type
+   =C-h v     devil-key RET= to see the current Devil key.
+
+2. After each keystroke is read, Devil checks if the key sequence
+   accumulated is a special key. If it is, then the special command
+   bound to the special key is executed immediately. Note that this step
+   is performed before any translation rules are applied to the input
+   key sequence. This is how the Devil special key sequence =,     SPC=
+   inserts a comma and a space. Type =C-h v     devil-special-keys RET=
+   to see the list of special keys and the commands bound to them.
+
+3. If the key sequence accumulated so far is not a special key, then
+   Devil translates the Devil key sequence to a regular Emacs key
+   sequence. If the regular Emacs key sequence turns out to be a
+   complete key sequence and some command is found to be bound to it,
+   then that command is executed immediately. This is how the Devil key
+   sequence =, x , f= is translated to =C-x C-f= and the corresponding
+   binding is executed. If the translated key sequence is a complete key
+   sequence but no command is bound to it, then Devil displays a message
+   that the key sequence is undefined. Type
+   =C-h v devil-translations RET= to see the list of translation rules.
+
+4. After successfully translating a Devil key sequence to an Emacs key
+   sequence and executing the command bound to it, Devil checks if the
+   key sequence is a repeatable key sequence. If it is found to be a
+   repeatable key sequence, then Devil sets a transient map so that the
+   command can be repeated merely by typing the last keystroke of the
+   input key sequence. This is how =, p p p= moves the cursor up by
+   three lines. Type =C-h v devil-repeatable-keys     RET= to see the
+   list of repeatable Devil key sequences.
+
+The variables =devil-special-keys=, =devil-translations=, and
+=devil-repeatable-keys= may contain keys or values with the string =%k=
+in them. This is a placeholder for =devil-key=. While applying the
+special keys, translation rules, or repeat rules, each =%k= is replaced
+with the actual value of =devil-key= before applying the rules.
+
+* Translation Rules
+   :PROPERTIES:
+   :CUSTOM_ID: translation-rules
+   :END:
+The following points provide an account of the translation rules that
+Devil follows in order to convert a Devil key sequence entered by the
+user to an Emacs key sequence:
+
+1. The input key vector read from the user is converted to a key
+   description (i.e., the string functions like =describe-key=,
+   =key-description=, produce). For example, if the user types ,x,f, it
+   is converted to =, x , f=.
+
+2. Now the resulting key description is translated with simple string
+   replacements. If any part of the string matches a key in
+   =devil-translations=, then it is replaced with the corresponding
+   value. For example, =, x , f= is translated to =C- x C- f=. Then
+   Devil normalises the result to =C-x C-f= by removing superfluous
+   spaces after the modifier keys.
+
+3. However, if the simple string based replacement leads to an invalid
+   Emacs key sequence, it skips the replacement that causes the
+   resulting Emacs key sequence to become invalid. For example
+   =,     m ,= results in =C-M-C-= after the simple string replacement
+   because the default translation rules replace =,= with =C-= and =m=
+   with =M-=. However, =C-M-C-= is an invalid key sequence, so the
+   replacement of the second =,= to =C-= is skipped. Therefore, the
+   input =, m ,= is translated to =C-M-,= instead.
+
+* Translation Examples
+   :PROPERTIES:
+   :CUSTOM_ID: translation-examples
+   :END:
+By default, Devil supports a small but peculiar set of translation rules
+that can be used to avoid modifier keys while typing various types of
+key sequences. See =C-h v devil-translations RET= for the translation
+rules. Here are some examples that demonstrate the default translation
+rules. The obvious ones are shown first first. The more peculiar
+translations come later in the table.
+
+| Input     | Translated | Remarks                           |
+|-----------+------------+-----------------------------------|
+| =, s=     | =C-s=      | =,= is replaced with =C-=         |
+| =, m s=   | =C-M-s=    | =m= is replaced with =M-=         |
+| =, z s=   | =C-SPC=    | =, z= is replaced with =C-= too   |
+| =, z z=   | =C-z=      | ditto                             |
+| =, m m x= | =M-x=      | =, m m= is replaced with =M-= too |
+| =, c , ,= | =C-c ,=    | =, ,= is replaced with =,=        |
+
+Note how we cannot use =, SPC= to set a mark because that key sequence
+is already reserved as a special key sequence in =devil-special-keys=,
+so Devil translates =, z= to =C-= too, so that we can still type =C-SPC=
+using =, z s= and set a mark.
+
+Also, note how the translation of =, m m= to =M-= allows us to enter a
+key sequence that begins with the =M-= modifier key.
+
+* Bonus Key Bindings
+   :PROPERTIES:
+   :CUSTOM_ID: bonus-key-bindings
+   :END:
+Devil adds the following additional key bindings only when Devil is
+enabled globally with =global-devil-mode=:
+
+- Adds the Devil key to =isearch-mode-map=, so that Devil key sequences
+  work in incremental search too.
+
+- Adds =u= to =universal-argument-more= to allow repeating the universal
+  argument command =C-u= simply by repeating =u=.
+
+As mentioned before these features are available only when Devil is
+enabled globally with =global-devil-mode=. If Devil is enabled locally
+with =devil-mode=, then these features are not available.
+
+* Custom Configuration Examples
+   :PROPERTIES:
+   :CUSTOM_ID: custom-configuration-examples
+   :END:
+In the examples presented below, the =(require 'devil)= calls may be
+omitted if Devil has been installed from MELPA. There are appropriate
+autoloads in place in the Devil package that would ensure that it is
+loaded automatically on enabling Devil mode. However, the =require=
+calls have been included in the examples below for the sake of
+completeness.
+
+** Local Mode
+    :PROPERTIES:
+    :CUSTOM_ID: local-mode
+    :END:
+While the section [[#use-devil][Use Devil]] shows how we enable Devil mode globally,
+this section shows how we can enable it locally.  Here is an example
+initialization code that enables Devil locally only in text buffers.
+
+#+begin_example
+(require 'devil)
+(add-hook 'text-mode-hook 'devil-mode)
+(global-set-key (kbd "C-,") 'devil-mode)
+#+end_example
+
+This is not recommended though because this does not provide a seamless
+Devil experience. For example, with Devil enabled locally in a text
+buffer like this, although we can type =, x , f= to launch the find-file
+minibuffer, we cannot use Devil key sequences in the minibuffer. Further
+the special keymaps described in the previous section work only when
+Devil is enabled globally.
+
+** Custom Appearance
+    :PROPERTIES:
+    :CUSTOM_ID: custom-appearance
+    :END:
+The following initialization code shows how we can customise Devil to
+show a Devil smiley (😈) in the modeline and the echo area.
+
+#+begin_example
+(require 'devil)
+(setq devil-lighter " \U0001F608")
+(setq devil-prompt "\U0001F608 %t")
+(global-devil-mode)
+(global-set-key (kbd "C-,") 'global-devil-mode)
+#+end_example
+
+This is how Emacs may look if emojis are rendered correctly:
+
+[[https://i.imgur.com/oYtwnGi.png][[[https://i.imgur.com/oYtwnGi.png]]]]
+
+** Custom Devil Key
+    :PROPERTIES:
+    :CUSTOM_ID: custom-devil-key
+    :END:
+The following initialization code shows how we can customise Devil to
+use a different Devil key.
+
+#+begin_example
+(defvar devil-key "<left>")
+(defvar devil-special-keys '(("%k %k" . (lambda () (interactive) (devil-run-key "%k")))))
+(require 'devil)
+(global-devil-mode)
+(global-set-key (kbd "C-<left>") 'global-devil-mode)
+#+end_example
+
+The above example sets the Devil key to the left arrow key, perhaps
+another dubious choice for the Devil key. With this configuration, we
+can use =<left> x <left> f= and have Devil translate it to =C-x C-f=.
+
+Additionally, the above example defines the =devil-special-keys=
+variable to have a single entry that allows typing =<left> <left>= to
+produce the same effect as the original =<left>=. It removes the other
+entries, so that =<left> SPC= is no longer reserved as a special key.
+Thus =<left> SPC= can now be used to set a mark like one would normally
+expect.
+
+** Multiple Devil Keys
+    :PROPERTIES:
+    :CUSTOM_ID: multiple-devil-keys
+    :END:
+While this package provides the comma (=,=) as the default and the only
+Devil key, nothing stops you from extending the mode map to support
+multiple Devil keys. Say, you decide that in addition to activating
+Devil with =,= which also plays the role of =C-=, you also want to
+activate Devil with =.= which must now play the role of =M-=. To achieve
+such a result, you could use this initialization code as a starting
+point and then customise it further based on your requirements:
+
+#+begin_example
+(defvar devil-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map (kbd ",") #'devil)
+    (define-key map (kbd ".") #'devil)
+    map))
+(defvar devil-special-keys '((", ," . (lambda () (insert ",")))
+                             (". ." . (lambda () (insert ".")))))
+(defvar devil-translations '(("," . "C-")
+                             ("." . "M-")))
+(require 'devil)
+(global-devil-mode)
+#+end_example
+
+With this configuration, we can type =, x , f= for =C-x C-f= like
+before. But now we can also type =. x= for =M-x=. Similarly, we can type
+=, . s= for =C-M-s= and so on. Further, =, ,= inserts a literal comma
+and =. .= inserts a literal dot.
+
+Note that by default Devil configures only one activation key (=,=)
+because the more activation keys we add, the more intrusive Devil
+becomes during regular editing tasks. Every key that we reserve for
+activating Devil loses its default function and then we need workarounds
+to somehow invoke the default function associated with that key (like
+repeating =.= twice to insert a single =.= in the above example).
+Therefore, it is a good idea to keep the number of Devil keys as small
+as possible.
+
+* Why?
+   :PROPERTIES:
+   :CUSTOM_ID: why
+   :END:
+Why go to the trouble of creating and using something like this? Why not
+just remap caps lock to ctrl like every other sane person does? Or if it
+is so important to avoid modifier keys, why not use something like God
+mode or Evil mode?
+
+Well, for one, both God mode and Evil mode are modal editing modes.
+Devil, on the other hand, provides a modeless editing experience of
+Emacs as possible.
+
+Devil mode began as a fun little tiny experiment. From the outset, it
+was clear that using something as crucial as the comma for specifying
+the modifier key is asking for trouble. However, I still wanted to see
+how far I could go with it. It turned out that in a matter of days, I
+was using it full-time for all of my Emacs usage.
+
+This experiment was partly motivated by Macbook keyboards which do not
+have a right ctrl key. Being a touch-typist myself, I found it
+inconvenient to type key combinations like =C-x=, =C-a=, =C-w=, =C-s=,
+etc. where both the modifier key and the modified key need to be pressed
+with the left hand fingers. I am not particularly fond of remapping caps
+lock to behave like ctrl because that still suffers from the problem
+that key combinations like =C-x=, =C-a= require pressing both the
+modifier key and the modified key with the left hand fingers. I know
+many people remap both their caps lock and enter to behave like ctrl.
+While I think that is a fine solution, I was not willing to put up with
+the work required to make that work seamlessly across all the various
+operating systems I work on.
+
+What began as a tiny whimsical experiment a few years ago turned out to
+be quite effective, at least to me. I like that this solution is
+implemented purely as Elisp and therefore does not have any external
+dependency. I am sharing this solution here in the form of a minor mode,
+just in case, there is someone out there who might find this useful too.
+
+* Comparison with God Mode
+   :PROPERTIES:
+   :CUSTOM_ID: comparison-with-god-mode
+   :END:
+God mode provides a modal editing experience but Devil does not. Devil
+has the same underlying philosophy as that of God mode, i.e., the user
+should not have to learn new key bindings. However, Devil does not have
+a hard separation between insert mode and command mode like God mode
+has. Instead, Devil waits for an activation key (=,= by default) and as
+soon as it is activated, it intercepts and translates keys, runs the
+corresponding command, and then gets out of the way. So Devil tries to
+retain the modeless editing experience of vanilla Emacs as much as
+possible.
+
+Now it is worth mentioning that some of this modeless editing experience
+can be reproduced in god-mode too using its
+=god-execute-with-current-bindings= function. Here is an example:
+
+#+begin_example
+(global-set-key (kbd ",") #'god-execute-with-current-bindings)
+#+end_example
+
+With this configuration, God mode translates =, x f= to =C-x C-f=.
+Similarly =, g x= invokes =M-x= and =, G s= invokes =C-M-x=. This
+provides a modeless editing experience in God mode too. However, this
+experience does not extend seamlessly to minibuffers. Devil does extend
+its Devil key translation to minibuffers.
+
+Further note that in God mode the ctrl modifier has sticky behaviour,
+i.e., the modifier remains active automatically for the entire key
+sequence. Therefore in the above example, we type =,= only once while
+typing =, x f= to invoke =C-x C-f=. However, this sticky behaviour
+implies that we need some way to disambiguate between key sequences like
+=C-x C-o= (delete blank lines) and =C-x o= (other window). God mode
+solves this by introducing =SPC= to deactivate the modifier, e.g.,
+=, x o= translates to =C-x C-o= but =, x SPC o= translates to =C-x o=.
+Devil does not treat the modifier key as sticky which leads to simpler
+key sequences at the cost of a little additional typing, i.e., =, x , o=
+translates to =C-x C-o= and =, x o= translates to =C-x o=.
+
+To summarize, there are primarily three things that Devil does
+differently:
+
+- Provide a modeless editing experience from the outset.
+- Seamlessly extend the same editing experience to minibuffer,
+  incremental search, etc.
+- Translate key sequences using string replacements. This allows for
+  arbitrary and sophisticated key translations for the adventurous.
+- Choose non-sticky behaviour for the modifier keys.
+
+These differences could make Devil easier to use than God mode for some
+people but clumsy for other people. It depends on one's tastes and
+preferences.
+
+* Support
+   :PROPERTIES:
+   :CUSTOM_ID: support
+   :END:
+To report bugs, suggest improvements, or ask questions,
+[[https://github.com/susam/devil/issues][create issues]].
diff --git a/README.md b/README.md
index 749508c..39ef57e 100644
--- a/README.md
+++ b/README.md
@@ -13,599 +13,7 @@ charm the Devil! But beware, for in this sinister domain, you must
 relinquish your comma key and embrace an editing experience that
 whispers wicked secrets into your fingertips!
 
-
-Contents
---------
-
-* [Introduction](#introduction)
-* [Notation](#notation)
-* [Install](#install)
-  * [Install Interactively from MELPA](#install-interactively-from-melpa)
-  * [Install Automatically from MELPA](#install-automatically-from-melpa)
-  * [Install from Git Source](#install-from-git-source)
-* [Use Devil](#use-devil)
-* [Typing Commas](#typing-commas)
-* [Devil Reader](#devil-reader)
-* [Translation Rules](#translation-rules)
-* [Translation Examples](#translation-examples)
-* [Bonus Key Bindings](#bonus-key-bindings)
-* [Custom Configuration Examples](#custom-configuration-examples)
-  * [Local Mode](#local-mode)
-  * [Custom Appearance](#custom-appearance)
-  * [Custom Devil Key](#custom-devil-key)
-  * [Multiple Devil Keys](#multiple-devil-keys)
-* [Why?](#why)
-* [Comparison with God Mode](#comparison-with-god-mode)
-* [Support](#support)
-* [Channels](#channels)
-* [More](#more)
-
-
-Introduction
-------------
-
-Devil mode intercepts our keystrokes and translates them to Emacs key
-sequences according to a configurable set of translation rules. For
-example, with the default translation rules, when we type `, x , f`,
-Devil translates it to `C-x C-f`.
-
-The choice of the comma key (`,`) to mean the control modifier key
-(`C-`) may seem outrageous. After all, the comma is a very important
-punctuation both in prose as well as in code. Can we really get away
-with using `,` to mean the `C-` modifier? It turns out, this terrible
-idea can be made to work without too much of a hassle. At least it
-works for me! It might work for you too. If it does not, Devil can be
-configured to use another key instead of `,` to mean the `C-`
-modifier. See the section [Custom Devil Key](#custom-devil-key) for an
-example.
-
-A sceptical reader may rightfully ask: If `,` is translated to `C-`,
-how on earth are we going to insert a literal `,` into the text when
-we need to? The section [Typing Commas](#typing-commas) answers this.
-But before we get there, we have some fundamentals to cover. Take the
-plunge and see what unfolds! Maybe you will like this! Maybe you will
-not! If you do not like this, you can always retreat to God mode, Evil
-mode, the vanilla key bindings, or whatever piques your fancy!
-
-
-Notation
---------
-
-A quick note about the notation used in the document: The previous
-example shows that `, x , f` is translated to `C-x C-f`. What this
-really means is that the key sequence
-<kbd>,</kbd><kbd>x</kbd><kbd>,</kbd><kbd>f</kbd> is translated to
-<kbd>ctrl</kbd>+<kbd>x</kbd> <kbd>ctrl</kbd>+<kbd>f</kbd>. We do not
-really type any space after the commas. The key <kbd>,</kbd> is
-directly followed by the key <kbd>x</kbd>. However, the key sequence
-notation used in this document contains spaces between each keystroke.
-This is consistent with how key sequences are represented in Emacs in
-general and how Emacs functions like `key-description`,
-`describe-key`, etc. represent key sequences. When we really need to
-type a space, it is represented as `SPC`.
-
-
-Install
--------
-
-### Install Interactively from MELPA
-
-Devil is available via [MELPA](https://melpa.org/). You may already
-have a preferred way of installing packages from MELPA. If so, install
-the package named `devil` to get Devil. For the sake of completeness,
-here is a very basic way of installing Devil from MELPA:
-
- 1. Add the following to the Emacs initialization file (i.e.,
-    `~/.emacs` or `~/.emacs.d/init.el` or `~/.config/emacs/init.el`):
-
-    ```sh
-    (require 'package)
-    (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
-    (package-initialize)
-    ```
-
- 2. Start Emacs with the updated initialization file and then type
-    these commands:
-
-    ```
-    M-x package-refresh-contents RET
-    M-x package-install RET devil RET
-    ```
-
- 3. Confirm that Devil is installed successfully with this command:
-
-    ```
-    M-x devil-show-version RET
-    ```
-
- 4. Enable Devil mode with this command:
-
-    ```
-    M-x global-devil-mode RET
-    ```
-
- 4. Type `, x , f` and watch Devil translate it to `C-x C-f` and
-    invoke the corresponding command.
-
-
-### Install Automatically from MELPA
-
-Here is yet another basic way to install and enable Devil using Elisp:
-
-```elisp
-(require 'package)
-(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
-(package-initialize)
-(unless package-archive-contents
-  (package-refresh-contents))
-(unless (package-installed-p 'devil)
-  (package-install 'devil))
-(global-devil-mode)
-(global-set-key (kbd "C-,") 'global-devil-mode)
-```
-
-Now type `, x , f` and watch Devil translate it to `C-x C-f` and
-invoke the corresponding command. Type `C-,` to disable Devil mode.
-Type `C-,` again to enable it.
-
-
-### Install from Git Source
-
-If you prefer obtaining Devil from its Git repository, follow these
-steps:
-
- 1. Clone Devil to your system:
-
-    ```sh
-    git clone https://github.com/susam/devil.git
-    ```
-
- 2. Add the following to your Emacs initialization:
-
-    ```elisp
-    (add-to-list 'load-path "/path/to/devil/")
-    (require 'devil)
-    (global-devil-mode)
-    (global-set-key (kbd "C-,") 'global-devil-mode)
-    ```
-
- 3. Start the Emacs editor. Devil mode should now be enabled in all
-    buffers. The modeline of each buffer should show the `Devil`
-    lighter.
-
- 4. Type `, x , f` and watch Devil translate it to `C-x C-f` and
-    invoke the corresponding command. Type `C-,` to disable Devil
-    mode. Type `C-,` again to enable it.
-
-
-Use Devil
----------
-
-Assuming vanilla Emacs key bindings have not been changed and Devil
-has not been customised, here are some examples that demonstrate how
-Devil may be used:
-
- 1. Type `, x , f` and watch Devil translate it to `C-x C-f` and
-    invoke the find file functionality.
-
- 2. Type `, p` to move up one line.
-
- 3. To move up multiple lines, type `, p p p` and so on. Some Devil
-    key sequences are repeatable keys. The repeatable Devil key
-    sequences can be repeated by typing the last key of the Devil key
-    sequence over and over again.
-
- 4. Another example of a repeatable Devil key sequence is `, f f f`
-    which moves the cursor word by multiple characters. A few other
-    examples of repeatable keys are `, k k k` to kill lines, `, / / /`
-    to undo changs, etc. Type `C-h v devil-repeatable-keys RET` to see
-    the complete list of repeatable keys.
-
- 5. Type `, s` and watch Devil translate it to `C-s` and invoke
-    incremental search.
-
- 6. Type `, m s` and watch Devil translate it to `C-M-s` and invoke
-    regular-expression-based incremental search. Yes, `m` is
-    translated to `M-`.
-
- 7. Type `, m m x` and watch Devil translate it to `M-x` and invoke
-    the corresponding command.
-
- 8. Type `, u , f` and watch Devil translate it to `C-u C-f` and move
-    the cursor forward by 4 characters.
-
- 9. Type `, u u , f` and the cursor moves forward by 16 characters.
-    Devil uses its translation rules and an additional keymap to make
-    the input key sequence behave like `C-u C-u C-f` which moves the
-    cursor forward by 16 characters.
-
-10. Type `, SPC` to type a comma followed by space. This is a special
-    key sequence to make it convenient to type a comma in the text.
-    Note that this sacrifices the use of `, SPC` to mean `C-SPC` which
-    could have been a convenient way to set a mark.
-
-11. Type `, z SPC` and watch Devil translate it to `C-SPC` and set a
-    mark. Yes, `, z` is translated to `C-` too.
-
-12. Similarly, type `, RET` to type a comma followed by the return
-    key. This is another special key.
-
-13. Type `, ,` to type a single comma. This special key is useful for
-    cases when you really need to type a single literal comma.
-
-
-Typing Commas
--------------
-
-Devil makes the questionable choice of using the comma as its
-activation key. As illustrated in the previous section, typing
-`, x , f` produces the same effect as typing `C-x C-f`. One might
-naturally wonder how then we are supposed to type literal commas.
-
-Most often when we edit text, we do not really type a comma in
-isolation. Often we immediately follow the comma with a space or a
-newline. This assumption usually holds good while editing regular
-text. However, this assumption may not hold in some situations, like
-while working with code when we need to add a single comma at the end
-of an existing line.
-
-In scenarios where the above assumption holds good, typing `, SPC`
-inserts a comma and a space. Similarly, typing `, RET` inserts a comma
-and a newline.
-
-In scenarios, when we do need to type a single comma, type `, ,` instead.
-
-Also, it is worth mentioning here that if all this fiddling with the
-comma key feels clumsy, we could always customise the Devil key to
-something else that feels better. We could also disable Devil mode
-temporarily and enable it again later with `C-,` as explained in
-section [Get Started](#get-started).
-
-
-Devil Reader
-------------
-
-The following points briefly describe how Devil reads Devil key
-sequences, translates them to Emacs key sequences, and runs commands
-bound to the key sequences:
-
- 1. As soon as the Devil key is typed (which is `,` by default), Devil
-    wakes up and starts reading Devil key sequences. Type `C-h v
-    devil-key RET` to see the current Devil key.
-
- 2. After each keystroke is read, Devil checks if the key sequence
-    accumulated is a special key. If it is, then the special command
-    bound to the special key is executed immediately. Note that this
-    step is performed before any translation rules are applied to the
-    input key sequence. This is how the Devil special key sequence `,
-    SPC` inserts a comma and a space. Type `C-h v
-    devil-special-keys RET` to see the list of special keys and
-    the commands bound to them.
-
- 3. If the key sequence accumulated so far is not a special key, then
-    Devil translates the Devil key sequence to a regular Emacs key
-    sequence. If the regular Emacs key sequence turns out to be a
-    complete key sequence and some command is found to be bound to it,
-    then that command is executed immediately. This is how the Devil
-    key sequence `, x , f` is translated to `C-x C-f` and the
-    corresponding binding is executed. If the translated key sequence
-    is a complete key sequence but no command is bound to it, then
-    Devil displays a message that the key sequence is undefined. Type
-    `C-h v devil-translations RET` to see the list of translation
-    rules.
-
- 4. After successfully translating a Devil key sequence to an Emacs
-    key sequence and executing the command bound to it, Devil checks
-    if the key sequence is a repeatable key sequence. If it is found
-    to be a repeatable key sequence, then Devil sets a transient map
-    so that the command can be repeated merely by typing the last
-    keystroke of the input key sequence. This is how `, p p p` moves
-    the cursor up by three lines. Type `C-h v devil-repeatable-keys
-    RET` to see the list of repeatable Devil key sequences.
-
-The variables `devil-special-keys`, `devil-translations`, and
-`devil-repeatable-keys` may contain keys or values with the string
-`%k` in them. This is a placeholder for `devil-key`. While applying
-the special keys, translation rules, or repeat rules, each `%k` is
-replaced with the actual value of `devil-key` before applying the
-rules.
-
-
-Translation Rules
------------------
-
-The following points provide an account of the translation rules that
-Devil follows in order to convert a Devil key sequence entered by the
-user to an Emacs key sequence:
-
- 1. The input key vector read from the user is converted to a key
-    description (i.e., the string functions like `describe-key`,
-    `key-description`, produce). For example, if the user types
-    <kbd>,</kbd><kbd>x</kbd><kbd>,</kbd><kbd>f</kbd>, it is converted
-    to `, x , f`.
-
- 2. Now the resulting key description is translated with simple string
-    replacements. If any part of the string matches a key in
-    `devil-translations`, then it is replaced with the corresponding
-    value. For example, `, x , f` is translated to `C- x C- f`. Then
-    Devil normalises the result to `C-x C-f` by removing superfluous
-    spaces after the modifier keys.
-
- 3. However, if the simple string based replacement leads to an
-    invalid Emacs key sequence, it skips the replacement that causes
-    the resulting Emacs key sequence to become invalid. For example `,
-    m ,` results in `C-M-C-` after the simple string replacement
-    because the default translation rules replace `,` with `C-` and
-    `m` with `M-`. However, `C-M-C-` is an invalid key sequence, so
-    the replacement of the second `,` to `C-` is skipped. Therefore,
-    the input `, m ,` is translated to `C-M-,` instead.
-
-
-Translation Examples
---------------------
-
-By default, Devil supports a small but peculiar set of translation
-rules that can be used to avoid modifier keys while typing various
-types of key sequences. See `C-h v devil-translations RET` for the
-translation rules. Here are some examples that demonstrate the default
-translation rules. The obvious ones are shown first first. The more
-peculiar translations come later in the table.
-
-| Input     | Translated | Remarks                            |
-|-----------|------------|------------------------------------|
-| `, s`     | `C-s`      | `,` is replaced with `C-`          |
-| `, m s`   | `C-M-s`    | `m` is replaced with `M-`          |
-| `, z s`   | `C-SPC`    | `, z` is replaced with `C-` too    |
-| `, z z`   | `C-z`      | ditto                              |
-| `, m m x` | `M-x`      | `, m m`  is replaced with `M-` too |
-| `, c , ,` | `C-c ,`    | `, ,` is replaced with `,`         |
-
-Note how we cannot use `, SPC` to set a mark because that key sequence
-is already reserved as a special key sequence in `devil-special-keys`,
-so Devil translates `, z` to `C-` too, so that we can still type
-`C-SPC` using `, z s` and set a mark.
-
-Also, note how the translation of `, m m` to `M-` allows us to enter a
-key sequence that begins with the `M-` modifier key.
-
-
-Bonus Key Bindings
-------------------
-
-Devil adds the following additional key bindings only when Devil is
-enabled globally with `global-devil-mode`:
-
-- Adds the Devil key to `isearch-mode-map`, so that Devil key
-  sequences work in incremental search too.
-
-- Adds `u` to `universal-argument-more` to allow repeating the
-  universal argument command `C-u` simply by repeating `u`.
-
-As mentioned before these features are available only when Devil is
-enabled globally with `global-devil-mode`. If Devil is enabled locally
-with `devil-mode`, then these features are not available.
-
-
-Custom Configuration Examples
------------------------------
-
-In the examples presented below, the `(require 'devil)` calls may be
-omitted if Devil has been installed from MELPA. There are appropriate
-autoloads in place in the Devil package that would ensure that it is
-loaded automatically on enabling Devil mode. However, the `require`
-calls have been included in the examples below for the sake of
-completeness.
-
-
-### Local Mode
-
-While the section [Get Started](#get-started) shows how we enable
-Devil mode globally, this section shows how we can enable it locally.
-Here is an example initialization code that enables Devil locally only
-in text buffers.
-
-```elisp
-(require 'devil)
-(add-hook 'text-mode-hook 'devil-mode)
-(global-set-key (kbd "C-,") 'devil-mode)
-```
-
-This is not recommended though because this does not provide a
-seamless Devil experience. For example, with Devil enabled locally in
-a text buffer like this, although we can type `, x , f` to launch the
-find-file minibuffer, we cannot use Devil key sequences in the
-minibuffer. Further the special keymaps described in the previous
-section work only when Devil is enabled globally.
-
-
-### Custom Appearance
-
-The following initialization code shows how we can customise Devil to
-show a Devil smiley (😈) in the modeline and the echo area.
-
-```elisp
-(require 'devil)
-(setq devil-lighter " \U0001F608")
-(setq devil-prompt "\U0001F608 %t")
-(global-devil-mode)
-(global-set-key (kbd "C-,") 'global-devil-mode)
-```
-
-This is how Emacs may look if emojis are rendered correctly:
-
-[![Screenshot of Emacs with Devil smiley][smiley-screenshot]][smiley-screenshot]
-
-[smiley-screenshot]: https://i.imgur.com/oYtwnGi.png
-
-
-### Custom Devil Key
-
-The following initialization code shows how we can customise Devil to
-use a different Devil key.
-
-```elisp
-(defvar devil-key "<left>")
-(defvar devil-special-keys '(("%k %k" . (lambda () (interactive) (devil-run-key "%k")))))
-(require 'devil)
-(global-devil-mode)
-(global-set-key (kbd "C-<left>") 'global-devil-mode)
-```
-
-The above example sets the Devil key to the left arrow key, perhaps
-another dubious choice for the Devil key. With this configuration, we
-can use `<left> x <left> f` and have Devil translate it to `C-x C-f`.
-
-Additionally, the above example defines the `devil-special-keys`
-variable to have a single entry that allows typing `<left> <left>` to
-produce the same effect as the original `<left>`. It removes the other
-entries, so that `<left> SPC` is no longer reserved as a special key.
-Thus `<left> SPC` can now be used to set a mark like one would
-normally expect.
-
-
-### Multiple Devil Keys
-
-While this package provides the comma (`,`) as the default and the
-only Devil key, nothing stops you from extending the mode map to
-support multiple Devil keys. Say, you decide that in addition to
-activating Devil with `,` which also plays the role of `C-`, you also
-want to activate Devil with `.` which must now play the role of `M-`.
-To achieve such a result, you could use this initialization code as a
-starting point and then customise it further based on your
-requirements:
-
-```elisp
-(defvar devil-mode-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map (kbd ",") #'devil)
-    (define-key map (kbd ".") #'devil)
-    map))
-(defvar devil-special-keys '((", ," . (lambda () (insert ",")))
-                             (". ." . (lambda () (insert ".")))))
-(defvar devil-translations '(("," . "C-")
-                             ("." . "M-")))
-(require 'devil)
-(global-devil-mode)
-```
-
-With this configuration, we can type `, x , f` for `C-x C-f` like
-before. But now we can also type `. x` for `M-x`. Similarly, we can
-type `, . s` for `C-M-s` and so on. Further, `, ,` inserts a literal
-comma and `. .` inserts a literal dot.
-
-Note that by default Devil configures only one activation key (`,`)
-because the more activation keys we add, the more intrusive Devil
-becomes during regular editing tasks. Every key that we reserve for
-activating Devil loses its default function and then we need
-workarounds to somehow invoke the default function associated with
-that key (like repeating `.` twice to insert a single `.` in the above
-example). Therefore, it is a good idea to keep the number of Devil
-keys as small as possible.
-
-
-Why?
-----
-
-Why go to the trouble of creating and using something like this? Why
-not just remap <kbd>caps lock</kbd> to <kbd>ctrl</kbd> like every
-other sane person does? Or if it is so important to avoid modifier
-keys, why not use something like God mode or Evil mode?
-
-Well, for one, both God mode and Evil mode are modal editing modes.
-Devil, on the other hand, provides a modeless editing experience of
-Emacs as possible.
-
-Devil mode began as a fun little tiny experiment. From the outset, it
-was clear that using something as crucial as the comma for specifying
-the modifier key is asking for trouble. However, I still wanted to see
-how far I could go with it. It turned out that in a matter of days, I
-was using it full-time for all of my Emacs usage.
-
-This experiment was partly motivated by Macbook keyboards which do not
-have a right <kbd>ctrl</kbd> key. Being a touch-typist myself, I found
-it inconvenient to type key combinations like `C-x`, `C-a`, `C-w`,
-`C-s`, etc. where both the modifier key and the modified key need to
-be pressed with the left hand fingers. I am not particularly fond of
-remapping <kbd>caps lock</kbd> to behave like <kbd>ctrl</kbd> because
-that still suffers from the problem that key combinations like `C-x`,
-`C-a` require pressing both the modifier key and the modified key with
-the left hand fingers. I know many people remap both their <kbd>caps
-lock</kbd> and <kbd>enter</kbd> to behave like <kbd>ctrl</kbd>. While
-I think that is a fine solution, I was not willing to put up with the
-work required to make that work seamlessly across all the various
-operating systems I work on.
-
-What began as a tiny whimsical experiment a few years ago turned out
-to be quite effective, at least to me. I like that this solution is
-implemented purely as Elisp and therefore does not have any external
-dependency. I am sharing this solution here in the form of a minor
-mode, just in case, there is someone out there who might find this
-useful too.
-
-
-Comparison with God Mode
-------------------------
-
-God mode provides a modal editing experience but Devil does not. Devil
-has the same underlying philosophy as that of God mode, i.e., the user
-should not have to learn new key bindings. However, Devil does not
-have a hard separation between insert mode and command mode like God
-mode has. Instead, Devil waits for an activation key (`,` by default)
-and as soon as it is activated, it intercepts and translates keys,
-runs the corresponding command, and then gets out of the way. So Devil
-tries to retain the modeless editing experience of vanilla Emacs as
-much as possible.
-
-Now it is worth mentioning that some of this modeless editing
-experience can be reproduced in god-mode too using its
-`god-execute-with-current-bindings` function. Here is an example:
-
-```elisp
-(global-set-key (kbd ",") #'god-execute-with-current-bindings)
-```
-
-With this configuration, God mode translates `, x f` to `C-x C-f`.
-Similarly `, g x` invokes `M-x` and `, G s` invokes `C-M-x`. This
-provides a modeless editing experience in God mode too. However, this
-experience does not extend seamlessly to minibuffers. Devil does
-extend its Devil key translation to minibuffers.
-
-Further note that in God mode the <kbd>ctrl</kbd> modifier has sticky
-behaviour, i.e., the modifier remains active automatically for the
-entire key sequence. Therefore in the above example, we type `,` only
-once while typing `, x f` to invoke `C-x C-f`. However, this sticky
-behaviour implies that we need some way to disambiguate between key
-sequences like `C-x C-o` (delete blank lines) and `C-x o` (other
-window). God mode solves this by introducing `SPC` to deactivate the
-modifier, e.g., `, x o` translates to `C-x C-o` but `, x SPC o`
-translates to `C-x o`. Devil does not treat the modifier key as sticky
-which leads to simpler key sequences at the cost of a little
-additional typing, i.e., `, x , o` translates to `C-x C-o` and `, x o`
-translates to `C-x o`.
-
-To summarize, there are primarily three things that Devil does
-differently:
-
-  - Provide a modeless editing experience from the outset.
-  - Seamlessly extend the same editing experience to minibuffer,
-    incremental search, etc.
-  - Translate key sequences using string replacements. This allows for
-    arbitrary and sophisticated key translations for the adventurous.
-  - Choose non-sticky behaviour for the modifier keys.
-
-These differences could make Devil easier to use than God mode for
-some people but clumsy for other people. It depends on one's tastes
-and preferences.
-
-
-Support
--------
-
-To report bugs, suggest improvements, or ask questions,
-[create issues][ISSUES].
-
-[ISSUES]: https://github.com/susam/devil/issues
-
+Read the [manual](./MANUAL.org) for more details on how to use Devil.
 
 Channels
 --------
-- 
2.39.2


[-- Attachment #10: Type: text/plain, Size: 80 bytes --]


I'll add the package to NonGNU ELPA in a day, unless there are any objections?

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-10  6:09     ` Philip Kaludercic
@ 2023-05-10 21:00       ` Susam Pal
  2023-05-10 21:56       ` Richard Stallman
  1 sibling, 0 replies; 36+ messages in thread
From: Susam Pal @ 2023-05-10 21:00 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1536 bytes --]

Philip Kaludercic <philipk@posteo.net> wrote:
>
> Susam Pal <susam.pal@gmail.com> writes:
>
> > Philip Kaludercic <philipk@posteo.net> wrote:
> >> Susam Pal <susam.pal@gmail.com> writes:
> >>
> >> > Hello!
> >> >
> >> > I am the author and maintainer of a new package named Devil. This package
> >> > intercepts keystrokes entered by the user and applies translation rules to
> >> > translate the keystrokes into Emacs key sequences. It supports three types
> >> > of rules: special keys that map to custom commands that are invoked
> >> > immediately prior to any translations, translation rules to translate Devil
> >> > key sequences to regular Emacs key sequences, and repeatable keys to allow
> >> > a Devil key sequence to be repeated by typing the last keystroke over and
> >> > over again using a transient map.
> >> >
> >> > See the README at https://github.com/susam/devil for more details.
> >>
> >> Looks interesting, here is a diff with a few comments:
> >
> > Thanks for the review and the diff! The code looks much better with
> > these changes. Like we discussed a little while ago in the #emacs
> > channel, if you send me the patches, I'll apply it to the code.
>
> Here are the patches, feel free to modify or leave out whatever you
> want:

Thank you for preparing and sending all the patches. I have applied
them to the code.

>
>
> I'll add the package to NonGNU ELPA in a day, unless there are any objections?

Thank you. I have renamed the remaining .md files to .org. Attached an
updated patch.

Regards,
Susam

[-- Attachment #2: 0001-elpa-packages-devil-New-package.patch --]
[-- Type: application/octet-stream, Size: 692 bytes --]

From c8728a587130b430da95bcdddfc6bfe8bb79c73a Mon Sep 17 00:00:00 2001
From: Susam Pal <susam@susam.net>
Date: Wed, 10 May 2023 21:51:47 +0100
Subject: [PATCH] * elpa-packages (devil): New package

---
 elpa-packages | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/elpa-packages b/elpa-packages
index c333cc8bb3..9a58976bcb 100644
--- a/elpa-packages
+++ b/elpa-packages
@@ -112,6 +112,11 @@
 
  (devhelp               :url "https://codeberg.org/akib/emacs-devhelp")
 
+ (devil
+  :url "https://github.com/susam/devil"
+  :readme "README.org"
+  :news "CHANGES.org")
+
  (diff-ansi		:url "https://codeberg.org/ideasman42/emacs-diff-ansi"
   :ignored-files ("LICENSE"))
 
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-10  6:09     ` Philip Kaludercic
  2023-05-10 21:00       ` Susam Pal
@ 2023-05-10 21:56       ` Richard Stallman
  1 sibling, 0 replies; 36+ messages in thread
From: Richard Stallman @ 2023-05-10 21:56 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: susam.pal, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

Why use the name "Devil" for this?  It doesn't seen to explain anything
about the package's purpose.  It is likely to put some people off.

If there is no clear reason why "Devil" is a good name, let's choose
a better name now.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
@ 2023-05-11  5:23 Payas Relekar
  2023-05-11  6:26 ` Po Lu
  2023-05-11  6:33 ` Eli Zaretskii
  0 siblings, 2 replies; 36+ messages in thread
From: Payas Relekar @ 2023-05-11  5:23 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Philip Kaludercic, susam.pal, emacs-devel

Richard Stallman <rms@gnu.org> writes:

> Why use the name "Devil" for this?  It doesn't seen to explain anything
> about the package's purpose.  It is likely to put some people off.

Every name is going to put someone or another off, can't really help it.
OpenBSD has their daemon and there are already funny anecdotes about it,
but it doesn't hurt anyone.

> If there is no clear reason why "Devil" is a good name, let's choose
> a better name now.

As mentioned by Susam in previous mail, as well as the repo README, the
name refers both to 'eVil' (extensible Vi Layer) as well as 'God-mode'.

The name is distinct, and I like it for what it is.
--



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  5:23 Payas Relekar
@ 2023-05-11  6:26 ` Po Lu
  2023-05-11  6:33 ` Eli Zaretskii
  1 sibling, 0 replies; 36+ messages in thread
From: Po Lu @ 2023-05-11  6:26 UTC (permalink / raw)
  To: Payas Relekar; +Cc: Richard Stallman, Philip Kaludercic, susam.pal, emacs-devel

Payas Relekar <relekarpayas@gmail.com> writes:

> Richard Stallman <rms@gnu.org> writes:
>
>> Why use the name "Devil" for this?  It doesn't seen to explain anything
>> about the package's purpose.  It is likely to put some people off.
>
> Every name is going to put someone or another off, can't really help it.
> OpenBSD has their daemon and there are already funny anecdotes about it,
> but it doesn't hurt anyone.
>
>> If there is no clear reason why "Devil" is a good name, let's choose
>> a better name now.
>
> As mentioned by Susam in previous mail, as well as the repo README, the
> name refers both to 'eVil' (extensible Vi Layer) as well as 'God-mode'.
>
> The name is distinct, and I like it for what it is.

What the package does is not obvious from its name.  That's the main
problem with it.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  5:23 Payas Relekar
  2023-05-11  6:26 ` Po Lu
@ 2023-05-11  6:33 ` Eli Zaretskii
  2023-05-11  6:52   ` Philip Kaludercic
  2023-05-12 16:19   ` Jim Porter
  1 sibling, 2 replies; 36+ messages in thread
From: Eli Zaretskii @ 2023-05-11  6:33 UTC (permalink / raw)
  To: Payas Relekar; +Cc: rms, philipk, susam.pal, emacs-devel

> From: Payas Relekar <relekarpayas@gmail.com>
> Cc: Philip Kaludercic <philipk@posteo.net>,  susam.pal@gmail.com,
>  emacs-devel@gnu.org
> Date: Thu, 11 May 2023 10:53:15 +0530
> 
> Richard Stallman <rms@gnu.org> writes:
> 
> > Why use the name "Devil" for this?  It doesn't seen to explain anything
> > about the package's purpose.  It is likely to put some people off.
> 
> Every name is going to put someone or another off, can't really help it.
> OpenBSD has their daemon and there are already funny anecdotes about it,
> but it doesn't hurt anyone.

"daemon" is a term whose meaning in computing context is widely
accepted for many years.  "Devil' isn't.

> > If there is no clear reason why "Devil" is a good name, let's choose
> > a better name now.
> 
> As mentioned by Susam in previous mail, as well as the repo README, the
> name refers both to 'eVil' (extensible Vi Layer) as well as 'God-mode'.

People are extremely unlikely to understand that, even if they know
about Evil in Emacs.  And even if they do figure out this is related
to Evil, the truth is that the package is not meant to be used by
users of Evil.

> The name is distinct, and I like it for what it is.

Please reconsider, I think this name is very unfortunate, because it
gives users no clue whatsoever about the package's purpose.

Thanks.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  6:33 ` Eli Zaretskii
@ 2023-05-11  6:52   ` Philip Kaludercic
  2023-05-11  7:07     ` Eli Zaretskii
  2023-05-11  8:09     ` Susam Pal
  2023-05-12 16:19   ` Jim Porter
  1 sibling, 2 replies; 36+ messages in thread
From: Philip Kaludercic @ 2023-05-11  6:52 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Payas Relekar, rms, susam.pal, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Payas Relekar <relekarpayas@gmail.com>
>> Cc: Philip Kaludercic <philipk@posteo.net>,  susam.pal@gmail.com,
>>  emacs-devel@gnu.org
>> Date: Thu, 11 May 2023 10:53:15 +0530
>> 
>> Richard Stallman <rms@gnu.org> writes:
>> 
>> > Why use the name "Devil" for this?  It doesn't seen to explain anything
>> > about the package's purpose.  It is likely to put some people off.
>> 
>> Every name is going to put someone or another off, can't really help it.
>> OpenBSD has their daemon and there are already funny anecdotes about it,
>> but it doesn't hurt anyone.

Also, "daemon" is not just an OpenBSD thing.

> "daemon" is a term whose meaning in computing context is widely
> accepted for many years.  "Devil' isn't.

I agree.

>> > If there is no clear reason why "Devil" is a good name, let's choose
>> > a better name now.
>> 
>> As mentioned by Susam in previous mail, as well as the repo README, the
>> name refers both to 'eVil' (extensible Vi Layer) as well as 'God-mode'.
>
> People are extremely unlikely to understand that, even if they know
> about Evil in Emacs.  And even if they do figure out this is related
> to Evil, the truth is that the package is not meant to be used by
> users of Evil.

I think it is more likely than you assume if you ask enthusiasts, but if
we consider the average user who doesn't hang around in Emacs-related
forums, chats, etc. then this is very true.

>> The name is distinct, and I like it for what it is.
>
> Please reconsider, I think this name is very unfortunate, because it
> gives users no clue whatsoever about the package's purpose.

Susam, what do you say?  Do you have any ideas?  A few names I can think
of might be:

- no-modifier-mode
- prefixless-mode
- implicit-ctrl-mode
- comma->control-mode

but I'm not really convinced by any of these (haven't really used the
package yet either).  Perhaps this might inspire someone else to come up
with a better suggestion?

If you really insist, then I think we really have to come up with a
better description, because "Minor mode for Devil-like command entering"
is really confusing.

> Thanks.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  6:52   ` Philip Kaludercic
@ 2023-05-11  7:07     ` Eli Zaretskii
  2023-05-12 15:02       ` Brian Cully via Emacs development discussions.
  2023-05-11  8:09     ` Susam Pal
  1 sibling, 1 reply; 36+ messages in thread
From: Eli Zaretskii @ 2023-05-11  7:07 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: relekarpayas, rms, susam.pal, emacs-devel

> From: Philip Kaludercic <philipk@posteo.net>
> Cc: Payas Relekar <relekarpayas@gmail.com>,  rms@gnu.org,
>   susam.pal@gmail.com,  emacs-devel@gnu.org
> Date: Thu, 11 May 2023 06:52:18 +0000
> 
> Susam, what do you say?  Do you have any ideas?  A few names I can think
> of might be:
> 
> - no-modifier-mode
> - prefixless-mode
> - implicit-ctrl-mode
> - comma->control-mode

How about comma-modifiers ?

> If you really insist, then I think we really have to come up with a
> better description, because "Minor mode for Devil-like command entering"
> is really confusing.

Agreed.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  6:52   ` Philip Kaludercic
  2023-05-11  7:07     ` Eli Zaretskii
@ 2023-05-11  8:09     ` Susam Pal
  2023-05-11  8:45       ` Philip Kaludercic
  2023-05-11  8:56       ` Eli Zaretskii
  1 sibling, 2 replies; 36+ messages in thread
From: Susam Pal @ 2023-05-11  8:09 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: Eli Zaretskii, Payas Relekar, rms, emacs-devel

Philip Kaludercic <philipk@posteo.net> wrote:
> Eli Zaretskii <eliz@gnu.org> writes:
>
> >> From: Payas Relekar <relekarpayas@gmail.com>
> >> Cc: Philip Kaludercic <philipk@posteo.net>,  susam.pal@gmail.com,
> >>  emacs-devel@gnu.org
> >> Date: Thu, 11 May 2023 10:53:15 +0530
> >>
> >> Richard Stallman <rms@gnu.org> writes:
> >>
> >> > Why use the name "Devil" for this?  It doesn't seen to explain anything
> >> > about the package's purpose.  It is likely to put some people off.
> >>
> >> Every name is going to put someone or another off, can't really help it.
> >> OpenBSD has their daemon and there are already funny anecdotes about it,
> >> but it doesn't hurt anyone.
>
> Also, "daemon" is not just an OpenBSD thing.
>
> > "daemon" is a term whose meaning in computing context is widely
> > accepted for many years.  "Devil' isn't.
>
> I agree.
>
> >> > If there is no clear reason why "Devil" is a good name, let's choose
> >> > a better name now.
> >>
> >> As mentioned by Susam in previous mail, as well as the repo README, the
> >> name refers both to 'eVil' (extensible Vi Layer) as well as 'God-mode'.
> >
> > People are extremely unlikely to understand that, even if they know
> > about Evil in Emacs.  And even if they do figure out this is related
> > to Evil, the truth is that the package is not meant to be used by
> > users of Evil.
>
> I think it is more likely than you assume if you ask enthusiasts, but if
> we consider the average user who doesn't hang around in Emacs-related
> forums, chats, etc. then this is very true.
>
> >> The name is distinct, and I like it for what it is.
> >
> > Please reconsider, I think this name is very unfortunate, because it
> > gives users no clue whatsoever about the package's purpose.
>
> Susam, what do you say?  Do you have any ideas?  A few names I can think
> of might be:
>
> - no-modifier-mode
> - prefixless-mode
> - implicit-ctrl-mode
> - comma->control-mode
>
> but I'm not really convinced by any of these (haven't really used the
> package yet either).  Perhaps this might inspire someone else to come up
> with a better suggestion?

Although the default translation rules in Devil translates comma to
ctrl, m to meta, etc., Devil is very configurable and one is free to
configure Devil in other ways that may or may not involve the comma
key or the modifier keys.

For example, I am aware that there are users of Devil who use the
semicolon as the Devil activation key and translate semicolon to
control. There are also users who only translate some activation key
to control key but regular alt modifier key on their keyboard for the
meta modifier.

> If you really insist, then I think we really have to come up with a
> better description, because "Minor mode for Devil-like command entering"
> is really confusing.
>
> > Thanks.

While I understand the desire for a more descriptive name, I believe
that "Devil" is a suitable choice due to its humorous reference to
both God mode and Evil mode. Some people like the name. Some do not. I
like this name.

If it is essential for the package's name to reflect its purpose, I
propose "Devil" to stand for "Devil's Extremely Versatile Interception
Layer".

I agree that the current description of the package needs improvement.
I have now updated it to "Minor mode for intercepting and translating
key sequences."

Regards,
Susam



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  8:09     ` Susam Pal
@ 2023-05-11  8:45       ` Philip Kaludercic
  2023-05-11  8:58         ` Eli Zaretskii
  2023-05-11  8:56       ` Eli Zaretskii
  1 sibling, 1 reply; 36+ messages in thread
From: Philip Kaludercic @ 2023-05-11  8:45 UTC (permalink / raw)
  To: Susam Pal; +Cc: Eli Zaretskii, Payas Relekar, rms, emacs-devel

Susam Pal <susam.pal@gmail.com> writes:

> Philip Kaludercic <philipk@posteo.net> wrote:
>> Eli Zaretskii <eliz@gnu.org> writes:
>>
>> >> From: Payas Relekar <relekarpayas@gmail.com>
>> >> Cc: Philip Kaludercic <philipk@posteo.net>,  susam.pal@gmail.com,
>> >>  emacs-devel@gnu.org
>> >> Date: Thu, 11 May 2023 10:53:15 +0530
>> >>
>> >> Richard Stallman <rms@gnu.org> writes:
>> >>
>> >> > Why use the name "Devil" for this?  It doesn't seen to explain anything
>> >> > about the package's purpose.  It is likely to put some people off.
>> >>
>> >> Every name is going to put someone or another off, can't really help it.
>> >> OpenBSD has their daemon and there are already funny anecdotes about it,
>> >> but it doesn't hurt anyone.
>>
>> Also, "daemon" is not just an OpenBSD thing.
>>
>> > "daemon" is a term whose meaning in computing context is widely
>> > accepted for many years.  "Devil' isn't.
>>
>> I agree.
>>
>> >> > If there is no clear reason why "Devil" is a good name, let's choose
>> >> > a better name now.
>> >>
>> >> As mentioned by Susam in previous mail, as well as the repo README, the
>> >> name refers both to 'eVil' (extensible Vi Layer) as well as 'God-mode'.
>> >
>> > People are extremely unlikely to understand that, even if they know
>> > about Evil in Emacs.  And even if they do figure out this is related
>> > to Evil, the truth is that the package is not meant to be used by
>> > users of Evil.
>>
>> I think it is more likely than you assume if you ask enthusiasts, but if
>> we consider the average user who doesn't hang around in Emacs-related
>> forums, chats, etc. then this is very true.
>>
>> >> The name is distinct, and I like it for what it is.
>> >
>> > Please reconsider, I think this name is very unfortunate, because it
>> > gives users no clue whatsoever about the package's purpose.
>>
>> Susam, what do you say?  Do you have any ideas?  A few names I can think
>> of might be:
>>
>> - no-modifier-mode
>> - prefixless-mode
>> - implicit-ctrl-mode
>> - comma->control-mode
>>
>> but I'm not really convinced by any of these (haven't really used the
>> package yet either).  Perhaps this might inspire someone else to come up
>> with a better suggestion?
>
> Although the default translation rules in Devil translates comma to
> ctrl, m to meta, etc., Devil is very configurable and one is free to
> configure Devil in other ways that may or may not involve the comma
> key or the modifier keys.

Right, that was why I said I wasn't convinced by the suggestions with
"comma" in the name.  By the way, you should add a custom setter to the
user option that configures the key to update the minor-mode map to
rebind the key.

> For example, I am aware that there are users of Devil who use the
> semicolon as the Devil activation key and translate semicolon to
> control. There are also users who only translate some activation key
> to control key but regular alt modifier key on their keyboard for the
> meta modifier.
>
>> If you really insist, then I think we really have to come up with a
>> better description, because "Minor mode for Devil-like command entering"
>> is really confusing.
>>
>> > Thanks.
>
> While I understand the desire for a more descriptive name, I believe
> that "Devil" is a suitable choice due to its humorous reference to
> both God mode and Evil mode. Some people like the name. Some do not. I
> like this name.

If you insist, I guess we'll go with that (unless anyone wants to veto
it), but I think it is sad to contribute to the further spread of
confusing and opaque names for packages that has been increasing on GNU
and NonGNU ELPA recently.

> If it is essential for the package's name to reflect its purpose, I
> propose "Devil" to stand for "Devil's Extremely Versatile Interception
> Layer".

I think you know that that is not what is being talked about here.
Retroactive acronyms are usually just a joke, and don't help address the
issue that newcomers face when they are given packages names like
"Corfu", "Captain", "Luwak" or "Eglot".  They are not indicative of
their functionality and at best have vague links to other terminology
that you can make sense of if someone explains it to you (sort of like
the devil to evil/god mode in your case), but most non-enthusiasts
wouldn't see.

While I get the intended pun, and I think "devil-mode" is a clever idea
knowing the context, I would still like to urge you to reconsider -- not
for your own sake but for that of the users.

> I agree that the current description of the package needs improvement.
> I have now updated it to "Minor mode for intercepting and translating
> key sequences."

That probably as good as it gets for a brief description.

> Regards,
> Susam



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  8:09     ` Susam Pal
  2023-05-11  8:45       ` Philip Kaludercic
@ 2023-05-11  8:56       ` Eli Zaretskii
  1 sibling, 0 replies; 36+ messages in thread
From: Eli Zaretskii @ 2023-05-11  8:56 UTC (permalink / raw)
  To: Susam Pal; +Cc: philipk, relekarpayas, rms, emacs-devel

> From: Susam Pal <susam.pal@gmail.com>
> Date: Thu, 11 May 2023 09:09:34 +0100
> Cc: Eli Zaretskii <eliz@gnu.org>, Payas Relekar <relekarpayas@gmail.com>,
>  rms@gnu.org, emacs-devel@gnu.org
> 
> > - no-modifier-mode
> > - prefixless-mode
> > - implicit-ctrl-mode
> > - comma->control-mode
> >
> > but I'm not really convinced by any of these (haven't really used the
> > package yet either).  Perhaps this might inspire someone else to come up
> > with a better suggestion?
> 
> Although the default translation rules in Devil translates comma to
> ctrl, m to meta, etc., Devil is very configurable and one is free to
> configure Devil in other ways that may or may not involve the comma
> key or the modifier keys.

Then how about key-transl or something similar?



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  8:45       ` Philip Kaludercic
@ 2023-05-11  8:58         ` Eli Zaretskii
  2023-05-11  9:08           ` Susam Pal
  0 siblings, 1 reply; 36+ messages in thread
From: Eli Zaretskii @ 2023-05-11  8:58 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: susam.pal, relekarpayas, rms, emacs-devel

> From: Philip Kaludercic <philipk@posteo.net>
> Cc: Eli Zaretskii <eliz@gnu.org>,  Payas Relekar <relekarpayas@gmail.com>,
>   rms@gnu.org,  emacs-devel@gnu.org
> Date: Thu, 11 May 2023 08:45:40 +0000
> 
> > I have now updated it to "Minor mode for intercepting and translating
> > key sequences."
> 
> That probably as good as it gets for a brief description.

Except that I'm not sure "intercepting" is correct here.  Is it?



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  8:58         ` Eli Zaretskii
@ 2023-05-11  9:08           ` Susam Pal
  2023-05-11  9:12             ` Philip Kaludercic
  2023-05-11 10:36             ` Eli Zaretskii
  0 siblings, 2 replies; 36+ messages in thread
From: Susam Pal @ 2023-05-11  9:08 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Philip Kaludercic, relekarpayas, rms, emacs-devel

Eli Zaretskii <eliz@gnu.org> wrote:
>
> > From: Philip Kaludercic <philipk@posteo.net>
> > Cc: Eli Zaretskii <eliz@gnu.org>,  Payas Relekar <relekarpayas@gmail.com>,
> >   rms@gnu.org,  emacs-devel@gnu.org
> > Date: Thu, 11 May 2023 08:45:40 +0000
> >
> > > I have now updated it to "Minor mode for intercepting and translating
> > > key sequences."
> >
> > That probably as good as it gets for a brief description.
>
> Except that I'm not sure "intercepting" is correct here.  Is it?

Is the following description better?

"Minor mode for reading and translating key sequences."



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  9:08           ` Susam Pal
@ 2023-05-11  9:12             ` Philip Kaludercic
  2023-05-11  9:19               ` Susam Pal
  2023-05-11 10:36             ` Eli Zaretskii
  1 sibling, 1 reply; 36+ messages in thread
From: Philip Kaludercic @ 2023-05-11  9:12 UTC (permalink / raw)
  To: Susam Pal; +Cc: Eli Zaretskii, relekarpayas, rms, emacs-devel

Susam Pal <susam.pal@gmail.com> writes:

> Eli Zaretskii <eliz@gnu.org> wrote:
>>
>> > From: Philip Kaludercic <philipk@posteo.net>
>> > Cc: Eli Zaretskii <eliz@gnu.org>,  Payas Relekar <relekarpayas@gmail.com>,
>> >   rms@gnu.org,  emacs-devel@gnu.org
>> > Date: Thu, 11 May 2023 08:45:40 +0000
>> >
>> > > I have now updated it to "Minor mode for intercepting and translating
>> > > key sequences."
>> >
>> > That probably as good as it gets for a brief description.
>>
>> Except that I'm not sure "intercepting" is correct here.  Is it?
>
> Is the following description better?
>
> "Minor mode for reading and translating key sequences."
                  ^
                  is this redundant?  hard to translate without reading.

That sounds very generic, is the package capable of doing that for any
kind of key translation.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  9:12             ` Philip Kaludercic
@ 2023-05-11  9:19               ` Susam Pal
  2023-05-11  9:34                 ` Ruijie Yu via Emacs development discussions.
  0 siblings, 1 reply; 36+ messages in thread
From: Susam Pal @ 2023-05-11  9:19 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: emacs-devel

Philip Kaludercic <philipk@posteo.net> wrote:
>
> Susam Pal <susam.pal@gmail.com> writes:
>
> > Eli Zaretskii <eliz@gnu.org> wrote:
> >>
> >> > From: Philip Kaludercic <philipk@posteo.net>
> >> > Cc: Eli Zaretskii <eliz@gnu.org>,  Payas Relekar <relekarpayas@gmail.com>,
> >> >   rms@gnu.org,  emacs-devel@gnu.org
> >> > Date: Thu, 11 May 2023 08:45:40 +0000
> >> >
> >> > > I have now updated it to "Minor mode for intercepting and translating
> >> > > key sequences."
> >> >
> >> > That probably as good as it gets for a brief description.
> >>
> >> Except that I'm not sure "intercepting" is correct here.  Is it?
> >
> > Is the following description better?
> >
> > "Minor mode for reading and translating key sequences."
>                   ^
>                   is this redundant?  hard to translate without reading.
>
> That sounds very generic, is the package capable of doing that for any
> kind of key translation.

Thanks for the feedback. In that case,

"Minor mode for translating key sequences."



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  9:19               ` Susam Pal
@ 2023-05-11  9:34                 ` Ruijie Yu via Emacs development discussions.
  2023-05-11 10:09                   ` Susam Pal
  0 siblings, 1 reply; 36+ messages in thread
From: Ruijie Yu via Emacs development discussions. @ 2023-05-11  9:34 UTC (permalink / raw)
  To: Susam Pal; +Cc: Philip Kaludercic, emacs-devel


Susam Pal <susam.pal@gmail.com> writes:

>> > "Minor mode for reading and translating key sequences."
>>                   ^
>>                   is this redundant?  hard to translate without reading.
>>
>> That sounds very generic, is the package capable of doing that for any
>> kind of key translation.
>
> Thanks for the feedback. In that case,
>
> "Minor mode for translating key sequences."

Can your package translate more than just modifier keys like control or
meta?  Like translate key sequence "j k" into something else?

If the answer is no, then maybe you should clarify that in the
description.

-- 
Best,


RY



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  9:34                 ` Ruijie Yu via Emacs development discussions.
@ 2023-05-11 10:09                   ` Susam Pal
  2023-05-11 10:31                     ` Susam Pal
  0 siblings, 1 reply; 36+ messages in thread
From: Susam Pal @ 2023-05-11 10:09 UTC (permalink / raw)
  To: Ruijie Yu; +Cc: Philip Kaludercic, emacs-devel

Ruijie Yu <ruijie@netyu.xyz> wrote:
>
>
> Susam Pal <susam.pal@gmail.com> writes:
>
> >> > "Minor mode for reading and translating key sequences."
> >>                   ^
> >>                   is this redundant?  hard to translate without reading.
> >>
> >> That sounds very generic, is the package capable of doing that for any
> >> kind of key translation.
> >
> > Thanks for the feedback. In that case,
> >
> > "Minor mode for translating key sequences."
>
> Can your package translate more than just modifier keys like control or
> meta?  Like translate key sequence "j k" into something else?
>
> If the answer is no, then maybe you should clarify that in the
> description.

Yes, this is possible. Although the defaults cater to how I and some
other users use this package, i.e., converting comma-prefixed key
sequences with modifier-based key sequences, the key sequence
translation logic does not make any assumption about modifier keys.

For example, one could configure the following key translations:

(setq devil-key "j")
(require 'devil)
(global-devil-mode)
(setq devil-logging t)
(setq devil-translations '(("%k k" . "RET")
                           ("%k l" . "<f10>")
                           ("%k m" . "C-M-")))

Assuming vanilla Emacs key bindings have not been altered, now typing
"j j" results in a newline. Typing "j l" opens the menu bar.
Similarly, typing "j m s" results in regexp i-search.

Regards,
Susam



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11 10:09                   ` Susam Pal
@ 2023-05-11 10:31                     ` Susam Pal
  0 siblings, 0 replies; 36+ messages in thread
From: Susam Pal @ 2023-05-11 10:31 UTC (permalink / raw)
  To: Ruijie Yu; +Cc: Philip Kaludercic, emacs-devel

On Thu, 11 May 2023 at 11:09, Susam Pal <susam.pal@gmail.com> wrote:
>
> Ruijie Yu <ruijie@netyu.xyz> wrote:
> >
> >
> > Susam Pal <susam.pal@gmail.com> writes:
> >
> > >> > "Minor mode for reading and translating key sequences."
> > >>                   ^
> > >>                   is this redundant?  hard to translate without reading.
> > >>
> > >> That sounds very generic, is the package capable of doing that for any
> > >> kind of key translation.
> > >
> > > Thanks for the feedback. In that case,
> > >
> > > "Minor mode for translating key sequences."
> >
> > Can your package translate more than just modifier keys like control or
> > meta?  Like translate key sequence "j k" into something else?
> >
> > If the answer is no, then maybe you should clarify that in the
> > description.
>
> Yes, this is possible. Although the defaults cater to how I and some
> other users use this package, i.e., converting comma-prefixed key
> sequences with modifier-based key sequences, the key sequence
> translation logic does not make any assumption about modifier keys.
>
> For example, one could configure the following key translations:
>
> (setq devil-key "j")
> (require 'devil)
> (global-devil-mode)
> (setq devil-logging t)
> (setq devil-translations '(("%k k" . "RET")
>                            ("%k l" . "<f10>")
>                            ("%k m" . "C-M-")))
>
> Assuming vanilla Emacs key bindings have not been altered, now typing
> "j j" results in a newline. Typing "j l" opens the menu bar.
> Similarly, typing "j m s" results in regexp i-search.

Correction.

(setq devil-key "j")
(require 'devil)
(global-devil-mode)
(setq devil-translations '(("%k k" . "RET")
                           ("%k l" . "<f10>")
                           ("%k m" . "C-M-")))

Now "j k" inserts newline, "j l" opens menu bar, and "j m s" performs
regexp i-search.

On Thu, 11 May 2023 at 11:09, Susam Pal <susam.pal@gmail.com> wrote:
>
> Ruijie Yu <ruijie@netyu.xyz> wrote:
> >
> >
> > Susam Pal <susam.pal@gmail.com> writes:
> >
> > >> > "Minor mode for reading and translating key sequences."
> > >>                   ^
> > >>                   is this redundant?  hard to translate without reading.
> > >>
> > >> That sounds very generic, is the package capable of doing that for any
> > >> kind of key translation.
> > >
> > > Thanks for the feedback. In that case,
> > >
> > > "Minor mode for translating key sequences."
> >
> > Can your package translate more than just modifier keys like control or
> > meta?  Like translate key sequence "j k" into something else?
> >
> > If the answer is no, then maybe you should clarify that in the
> > description.
>
> Yes, this is possible. Although the defaults cater to how I and some
> other users use this package, i.e., converting comma-prefixed key
> sequences with modifier-based key sequences, the key sequence
> translation logic does not make any assumption about modifier keys.
>
> For example, one could configure the following key translations:
>
> (setq devil-key "j")
> (require 'devil)
> (global-devil-mode)
> (setq devil-logging t)
> (setq devil-translations '(("%k k" . "RET")
>                            ("%k l" . "<f10>")
>                            ("%k m" . "C-M-")))
>
> Assuming vanilla Emacs key bindings have not been altered, now typing
> "j j" results in a newline. Typing "j l" opens the menu bar.
> Similarly, typing "j m s" results in regexp i-search.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  9:08           ` Susam Pal
  2023-05-11  9:12             ` Philip Kaludercic
@ 2023-05-11 10:36             ` Eli Zaretskii
  1 sibling, 0 replies; 36+ messages in thread
From: Eli Zaretskii @ 2023-05-11 10:36 UTC (permalink / raw)
  To: Susam Pal; +Cc: philipk, relekarpayas, rms, emacs-devel

> From: Susam Pal <susam.pal@gmail.com>
> Date: Thu, 11 May 2023 10:08:50 +0100
> Cc: Philip Kaludercic <philipk@posteo.net>, relekarpayas@gmail.com, rms@gnu.org, 
> 	emacs-devel@gnu.org
> 
> Eli Zaretskii <eliz@gnu.org> wrote:
> >
> > Except that I'm not sure "intercepting" is correct here.  Is it?
> 
> Is the following description better?
> 
> "Minor mode for reading and translating key sequences."

I'd drop the "reading" part as well.  It should be clear that in order
to translate a sequence, you need to read it.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  7:07     ` Eli Zaretskii
@ 2023-05-12 15:02       ` Brian Cully via Emacs development discussions.
  0 siblings, 0 replies; 36+ messages in thread
From: Brian Cully via Emacs development discussions. @ 2023-05-12 15:02 UTC (permalink / raw)
  To: Eli Zaretskii
  Cc: Philip Kaludercic, relekarpayas, rms, susam.pal, emacs-devel


Eli Zaretskii <eliz@gnu.org> writes:

> How about comma-modifiers ?

Or maybe ‘com-mode’.

I'll see myself out.

-bjc



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-11  6:33 ` Eli Zaretskii
  2023-05-11  6:52   ` Philip Kaludercic
@ 2023-05-12 16:19   ` Jim Porter
  2023-05-13  7:10     ` Philip Kaludercic
  2023-05-13 22:30     ` Richard Stallman
  1 sibling, 2 replies; 36+ messages in thread
From: Jim Porter @ 2023-05-12 16:19 UTC (permalink / raw)
  To: Eli Zaretskii, Payas Relekar; +Cc: rms, philipk, susam.pal, emacs-devel

On 5/10/2023 11:33 PM, Eli Zaretskii wrote:
> Please reconsider, I think this name is very unfortunate, because it
> gives users no clue whatsoever about the package's purpose.

How about something like "devil-keys"? That should make it clear that 
the package has something to do with keys. It doesn't tell exactly what 
it *does* with those keys, but I think a more-detailed description 
belongs in the package description or the manual.

Within the package itself, I think it would be fine to refer to it as 
"Devil" (without the "-keys"), since once you're looking at the package 
in detail, the "keys" hint isn't needed anymore.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-12 16:19   ` Jim Porter
@ 2023-05-13  7:10     ` Philip Kaludercic
  2023-05-13  9:05       ` Susam Pal
  2023-05-13 22:30     ` Richard Stallman
  1 sibling, 1 reply; 36+ messages in thread
From: Philip Kaludercic @ 2023-05-13  7:10 UTC (permalink / raw)
  To: Jim Porter; +Cc: Eli Zaretskii, Payas Relekar, rms, susam.pal, emacs-devel

Jim Porter <jporterbugs@gmail.com> writes:

> On 5/10/2023 11:33 PM, Eli Zaretskii wrote:
>> Please reconsider, I think this name is very unfortunate, because it
>> gives users no clue whatsoever about the package's purpose.
>
> How about something like "devil-keys"? That should make it clear that
> the package has something to do with keys. It doesn't tell exactly
> what it *does* with those keys, but I think a more-detailed
> description belongs in the package description or the manual.
>
> Within the package itself, I think it would be fine to refer to it as
> "Devil" (without the "-keys"), since once you're looking at the
> package in detail, the "keys" hint isn't needed anymore.

I think this is a nice idea, and a good compromise.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-13  7:10     ` Philip Kaludercic
@ 2023-05-13  9:05       ` Susam Pal
  2023-05-15 22:12         ` Richard Stallman
  2023-05-17 13:30         ` João Távora
  0 siblings, 2 replies; 36+ messages in thread
From: Susam Pal @ 2023-05-13  9:05 UTC (permalink / raw)
  To: emacs-devel; +Cc: Philip Kaludercic

Philip Kaludercic <philipk@posteo.net> wrote:
>
> Jim Porter <jporterbugs@gmail.com> writes:
>
> > On 5/10/2023 11:33 PM, Eli Zaretskii wrote:
> >> Please reconsider, I think this name is very unfortunate, because it
> >> gives users no clue whatsoever about the package's purpose.
> >
> > How about something like "devil-keys"? That should make it clear that
> > the package has something to do with keys. It doesn't tell exactly
> > what it *does* with those keys, but I think a more-detailed
> > description belongs in the package description or the manual.
> >
> > Within the package itself, I think it would be fine to refer to it as
> > "Devil" (without the "-keys"), since once you're looking at the
> > package in detail, the "keys" hint isn't needed anymore.
>
> I think this is a nice idea, and a good compromise.

I worry that choosing "devil-keys" as the package identifier is going
to make the identifier inconsistent with how Devil is packaged in
MELPA. The instructions to install Devil are going to become more
complicated than they need to be with differing instructions for MELPA
and NonGNU ELPA.

I am not convinced that a meaningful name is necessary for this
package. Consider the popular package meow. It is a fairly recent
package that was created in 2020 and added in December 2022. It exists
with the name "meow" in NonGNU ELPA. People who do not know about it
of course do not know about it. But people who do know about it do not
get confused about what it does. I doubt anyone is going to stumble
upon these packages merely due to a meaningful name. At minimum, one
is going to run M-x package-list-packages RET and search the buffer
for strings like "modal", "key", etc. But more typically, people
encounter these packages via recommendations from other community
members. People learn about packages like this in some context where
the context makes it clear what these packages do.

In general, I do not think packages with quirky names or names
unrelated to the purpose of the package is a problem. On the other
hand, I feel, the more the merrier! At the same time, I do acknowledge
that opinions on this matter differ.

Devil is a package created as a result of a whimsical idea and I think
the whimsical name is befitting. In my humble opinion, an additional
suffix like "-keys" does not really add much. One still has to read
the package description to understand what it does. However adding
this suffix does take away something. It takes away simplicity,
elegance, and consistency. It introduces inconsistency between the
package identifier and the package name. It introduces inconsistency
between NonGNU ELPA and MELPA.

I believe that using "devil" as both the package identifier and name,
combined with the updated package description mentioning its purpose
as a key sequence translation package does provide sufficient clarity
for anyone browsing the package list.

I would like to thank everyone who has generously invested their time
and contributed to this discussion. Despite differing opinions, I
wanted to take a moment to express my thoughts on the matter.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-12 16:19   ` Jim Porter
  2023-05-13  7:10     ` Philip Kaludercic
@ 2023-05-13 22:30     ` Richard Stallman
  1 sibling, 0 replies; 36+ messages in thread
From: Richard Stallman @ 2023-05-13 22:30 UTC (permalink / raw)
  To: Jim Porter; +Cc: eliz, relekarpayas, philipk, susam.pal, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > How about something like "devil-keys"? That should make it clear that 
  > the package has something to do with keys. It doesn't tell exactly what 
  > it *does* with those keys, but I think a more-detailed description 
  > belongs in the package description or the manual.

I like this way of serving both goals at once: a clue about what the job is,
and a name to distinguish this package from others for thatjob.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-13  9:05       ` Susam Pal
@ 2023-05-15 22:12         ` Richard Stallman
  2023-05-17 13:30         ` João Távora
  1 sibling, 0 replies; 36+ messages in thread
From: Richard Stallman @ 2023-05-15 22:12 UTC (permalink / raw)
  To: Susam Pal; +Cc: emacs-devel, philipk

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > I worry that choosing "devil-keys" as the package identifier is going
  > to make the identifier inconsistent with how Devil is packaged in
  > MELPA.

Compatibility with MELPA is not one of our goals.  It is not a reason
to choose a suboptimal way of doing things.

  > Consider the popular package meow. It is a fairly recent
  > package that was created in 2020 and added in December 2022. It exists
  > with the name "meow" in NonGNU ELPA. People who do not know about it
  > of course do not know about it. But people who do know about it do not
  > get confused about what it does.

That's what generally happens with a package whose name gives no
guide: people who regularly use the package know what it does, and
others have no idea.

The reason to choose a name that tells something about the package is
to get a better outcome than that.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-13  9:05       ` Susam Pal
  2023-05-15 22:12         ` Richard Stallman
@ 2023-05-17 13:30         ` João Távora
  2023-05-17 14:06           ` Philip Kaludercic
  1 sibling, 1 reply; 36+ messages in thread
From: João Távora @ 2023-05-17 13:30 UTC (permalink / raw)
  To: Susam Pal; +Cc: emacs-devel, Philip Kaludercic

[-- Attachment #1: Type: text/plain, Size: 3506 bytes --]

On Sat, May 13, 2023, 10:06 Susam Pal <susam.pal@gmail.com> wrote:

> Philip Kaludercic <philipk@posteo.net> wrote:
> >
> > Jim Porter <jporterbugs@gmail.com> writes:
> >
> > > On 5/10/2023 11:33 PM, Eli Zaretskii wrote:
> > >> Please reconsider, I think this name is very unfortunate, because it
> > >> gives users no clue whatsoever about the package's purpose.
> > >
> > > How about something like "devil-keys"? That should make it clear that
> > > the package has something to do with keys. It doesn't tell exactly
> > > what it *does* with those keys, but I think a more-detailed
> > > description belongs in the package description or the manual.
> > >
> > > Within the package itself, I think it would be fine to refer to it as
> > > "Devil" (without the "-keys"), since once you're looking at the
> > > package in detail, the "keys" hint isn't needed anymore.
> >
> > I think this is a nice idea, and a good compromise.
>
> I worry that choosing "devil-keys" as the package identifier is going
> to make the identifier inconsistent with how Devil is packaged in
> MELPA. The instructions to install Devil are going to become more
> complicated than they need to be with differing instructions for MELPA
> and NonGNU ELPA.
>
> I am not convinced that a meaningful name is necessary for this
> package. Consider the popular package meow. It is a fairly recent
> package that was created in 2020 and added in December 2022. It exists
> with the name "meow" in NonGNU ELPA. People who do not know about it
> of course do not know about it. But people who do know about it do not
> get confused about what it does. I doubt anyone is going to stumble
> upon these packages merely due to a meaningful name. At minimum, one
> is going to run M-x package-list-packages RET and search the buffer
> for strings like "modal", "key", etc. But more typically, people
> encounter these packages via recommendations from other community
> members. People learn about packages like this in some context where
> the context makes it clear what these packages do.
>
> In general, I do not think packages with quirky names or names
> unrelated to the purpose of the package is a problem. On the other
> hand, I feel, the more the merrier! At the same time, I do acknowledge
> that opinions on this matter differ.
>
> Devil is a package created as a result of a whimsical idea and I think
> the whimsical name is befitting. In my humble opinion, an additional
> suffix like "-keys" does not really add much. One still has to read
> the package description to understand what it does. However adding
> this suffix does take away something. It takes away simplicity,
> elegance, and consistency. It introduces inconsistency between the
> package identifier and the package name. It introduces inconsistency
> between NonGNU ELPA and MELPA.
>
> I believe that using "devil" as both the package identifier and name,
> combined with the updated package description mentioning its purpose
> as a key sequence translation package does provide sufficient clarity
> for anyone browsing the package list.
>
> I would like to thank everyone who has generously invested their time
> and contributed to this discussion. Despite differing opinions, I
> wanted to take a moment to express my thoughts on the matter.
>

FWIW i agree with you on all points.

It's important for packages to be allowed to keep the names the developers
baptized them with.

João

>

[-- Attachment #2: Type: text/html, Size: 4567 bytes --]

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-17 13:30         ` João Távora
@ 2023-05-17 14:06           ` Philip Kaludercic
  2023-05-17 15:41             ` João Távora
  0 siblings, 1 reply; 36+ messages in thread
From: Philip Kaludercic @ 2023-05-17 14:06 UTC (permalink / raw)
  To: João Távora; +Cc: Susam Pal, emacs-devel

João Távora <joaotavora@gmail.com> writes:

> FWIW i agree with you on all points.
>
> It's important for packages to be allowed to keep the names the developers
> baptized them with.

Important in what sense?  There have frequently been authors that have
changed the names of their packages when this was suggested to them, so
it doesn't like it was important for them.  People are making a bigger
deal out of quirky names than it should be.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-17 14:06           ` Philip Kaludercic
@ 2023-05-17 15:41             ` João Távora
  2023-05-17 15:46               ` Eli Zaretskii
  0 siblings, 1 reply; 36+ messages in thread
From: João Távora @ 2023-05-17 15:41 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: Susam Pal, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 848 bytes --]

On Wed, May 17, 2023 at 3:06 PM Philip Kaludercic <philipk@posteo.net>
wrote:
>
> João Távora <joaotavora@gmail.com> writes:
>
> > FWIW i agree with you on all points.
> >
> > It's important for packages to be allowed to keep the names the
developers
> > baptized them with.
>
> Important in what sense?

In just the sense Susam described.  My message simply intended to support
Susam's view.

> There have frequently been authors that have
> changed the names of their packages when this was suggested to them, so
> it doesn't like it was important for them.

I don't see the relevance. Susam doesn't want to and IMO it's perfectly
legitimate.

> People are making a bigger
> deal out of quirky names than it should be.

Precisely my point, so let's stop insisting that authors change the names
of their creations.

[-- Attachment #2: Type: text/html, Size: 1200 bytes --]

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [NonGNU ELPA] New package: devil
  2023-05-17 15:41             ` João Távora
@ 2023-05-17 15:46               ` Eli Zaretskii
  0 siblings, 0 replies; 36+ messages in thread
From: Eli Zaretskii @ 2023-05-17 15:46 UTC (permalink / raw)
  To: João Távora; +Cc: philipk, susam.pal, emacs-devel

> From: João Távora <joaotavora@gmail.com>
> Date: Wed, 17 May 2023 16:41:58 +0100
> Cc: Susam Pal <susam.pal@gmail.com>, emacs-devel <emacs-devel@gnu.org>
> 
> let's stop insisting that authors change the names
> of their creations.

We are not insisting.  We are respectfully asking them to consider the
possibility, and explain why it will be useful.



^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2023-05-17 15:46 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-09  1:57 [NonGNU ELPA] New package: devil Susam Pal
2023-05-09  8:42 ` Philip Kaludercic
2023-05-09  8:52   ` Eli Zaretskii
2023-05-09  8:58     ` Philip Kaludercic
2023-05-09 18:19       ` chad
2023-05-09 22:07         ` Susam Pal
2023-05-09 20:56   ` Susam Pal
2023-05-10  6:09     ` Philip Kaludercic
2023-05-10 21:00       ` Susam Pal
2023-05-10 21:56       ` Richard Stallman
  -- strict thread matches above, loose matches on Subject: below --
2023-05-11  5:23 Payas Relekar
2023-05-11  6:26 ` Po Lu
2023-05-11  6:33 ` Eli Zaretskii
2023-05-11  6:52   ` Philip Kaludercic
2023-05-11  7:07     ` Eli Zaretskii
2023-05-12 15:02       ` Brian Cully via Emacs development discussions.
2023-05-11  8:09     ` Susam Pal
2023-05-11  8:45       ` Philip Kaludercic
2023-05-11  8:58         ` Eli Zaretskii
2023-05-11  9:08           ` Susam Pal
2023-05-11  9:12             ` Philip Kaludercic
2023-05-11  9:19               ` Susam Pal
2023-05-11  9:34                 ` Ruijie Yu via Emacs development discussions.
2023-05-11 10:09                   ` Susam Pal
2023-05-11 10:31                     ` Susam Pal
2023-05-11 10:36             ` Eli Zaretskii
2023-05-11  8:56       ` Eli Zaretskii
2023-05-12 16:19   ` Jim Porter
2023-05-13  7:10     ` Philip Kaludercic
2023-05-13  9:05       ` Susam Pal
2023-05-15 22:12         ` Richard Stallman
2023-05-17 13:30         ` João Távora
2023-05-17 14:06           ` Philip Kaludercic
2023-05-17 15:41             ` João Távora
2023-05-17 15:46               ` Eli Zaretskii
2023-05-13 22:30     ` Richard Stallman

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).