branch: elpa/casual
commit 7522e3bc7657b9cdef4e2d2e7d5e12e3839afea6
Merge: 76b3017d13 69c7635bb0
Author: Charles Choi <[email protected]>
Commit: GitHub <[email protected]>
Merge pull request #273 from kickingvegas/166-build-casual-elisp
Add Casual Elisp
---
README.org | 2 +-
docs/casual.info | Bin 116970 -> 120784 bytes
docs/casual.org | 38 +++---
docs/casual.texi | 166 ++++++++++++++++++++-----
docs/compile.org | 42 ++++---
docs/editkit.org | 3 +
docs/elisp.org | 55 ++++++++
docs/images/casual-elisp-edebug-screenshot.png | Bin 0 -> 158941 bytes
docs/images/casual-elisp-screenshot.png | Bin 0 -> 158044 bytes
docs/sponsorship.org | 5 +
lisp/Makefile | 5 +
lisp/Makefile-elisp.make | 30 +++++
lisp/casual-compile.el | 26 +++-
lisp/casual-elisp-settings.el | 68 ++++++++++
lisp/casual-elisp-utils.el | 72 +++++++++++
lisp/casual-elisp.el | 110 ++++++++++++++++
tests/Makefile | 5 +
tests/casual-elisp-test-utils.el | 43 +++++++
tests/test-casual-elisp-settings.el | 50 ++++++++
tests/test-casual-elisp-utils.el | 52 ++++++++
tests/test-casual-elisp.el | 95 ++++++++++++++
21 files changed, 804 insertions(+), 63 deletions(-)
diff --git a/README.org b/README.org
index 97b60e6ecc..ac6494ec34 100644
--- a/README.org
+++ b/README.org
@@ -12,7 +12,7 @@ Casual has no aims to be a mutually exclusive user interface.
All existing user
To learn more about the motivations and design considerations for Casual as
well as seeing it at work, please watch the presentation
[[https://emacsconf.org/2024/talks/casual/][“Re-imagining the Emacs User
Experience with Casual Suite”]] from EmacsConf 2024.
-Please refer to the Casual User Guide (TBD) for detailed information about it.
This user guide is available both in Emacs Info and HTML formats.
+Please refer to the [[https://kickingvegas.github.io/casual][Casual User
Guide]] for detailed information about it. This user guide is available both in
Emacs Info and HTML formats.
* Asks
diff --git a/docs/casual.info b/docs/casual.info
index c0436c58ec..9ce83e8dce 100644
Binary files a/docs/casual.info and b/docs/casual.info differ
diff --git a/docs/casual.org b/docs/casual.org
index 559bc245ed..aadb56805a 100644
--- a/docs/casual.org
+++ b/docs/casual.org
@@ -16,10 +16,9 @@
#+TEXINFO_DIR_NAME: Casual
#+TEXINFO_DIR_DESC: Transient user interfaces for different Emacs modes.
#+TEXINFO_PRINTED_TITLE: Casual User Guide
+#+TEXINFO_FOOTER: https://buymeacoffee.com/kickingvegas
-Pre-release Version: {{{version}}}
-
-NOTE: THIS USER GUIDE IS A WORK IN PROGRESS.
+Version: {{{version}}}
Casual is a project to re-imagine the primary user interface for Emacs using
keyboard-driven menus.
@@ -31,6 +30,8 @@ Casual has no aims to be a mutually exclusive user interface.
All existing user
To learn more about the motivations and design considerations for Casual and
to see it at work, please watch the presentation
[[https://emacsconf.org/2024/talks/casual/][“Re-imagining the Emacs User
Experience with Casual Suite”]] from EmacsConf 2024.
+#+INCLUDE: "./sponsorship.org"
+
* Copying
:PROPERTIES:
:COPYING: t
@@ -38,7 +39,6 @@ To learn more about the motivations and design considerations
for Casual and to
Copyright © 2024-2025 Charles Y. Choi
-
* Introduction
#+CINDEX: Introduction
** Motivations
@@ -134,9 +134,10 @@ Configuration of a particular Casual user interface is
performed per mode. Go to
- [[#bookmarks-install][Bookmarks]]
- [[#calc-install][Calc]]
- [[#calendar-install][Calendar]]
-- [[#compile-install][Compile]]
+- [[#compile-install][Compile (Grep)]]
- [[#dired-install][Dired]]
- [[#editkit-install][EditKit]]
+- [[#elisp-install][Elisp]]
- [[#eshell-install][Eshell]]
- [[#help-install][Help]]
- [[#ibuffer-install][IBuffer]]
@@ -148,7 +149,12 @@ Configuration of a particular Casual user interface is
performed per mode. Go to
- [[#re-builder-install][Re-Builder]]
- [[#timezone-install][Timezone]]
-** Upgrading to Casual 2.x
+** A Note on Package Dependencies
+Casual requires a recent installation of Transient 0.9.0+ from either
[[https://elpa.gnu.org/packages/transient.html][ELPA]] or
[[https://melpa.org/#/transient][MELPA]]. If your version of Emacs is ≤ 30 but
also includes Transient as a built-in package, you will need to set the
customizable variable ~package-install-upgrade-built-in~ to ~t~ to enable
updating it via ~package.el~. Set this variable and proceed with installing
Casual. Alternately invoking ~package-install~ with a prefix [...]
+
+If you already have the latest version of Magit installed (via
[[https://elpa.nongnu.org/nongnu/magit.html][non-GNU ELPA]] or
[[https://melpa.org/#/magit][MELPA]]), you can bypass the above instruction as
Magit already includes the Transient package as a dependency.
+
+** Upgrading to Casual 1.x to 2.x
If you have been using an earlier version 1.x of Casual, thank you. Please use
the following guidance:
*** If you do not use ~use-package~ to configure Casual
@@ -170,12 +176,6 @@ For version 2.x going forward, I (Charles Choi) have
decided to not offer any do
That said, if you have used ~:ensure t~ to install a superseded package, you
/must/ remove that configuration. After doing so, please follow the above
instructions for installing ~casual~.
-** A Note on Package Dependencies
-Casual requires a recent installation of Transient 0.9.0+ from either
[[https://elpa.gnu.org/packages/transient.html][ELPA]] or
[[https://melpa.org/#/transient][MELPA]]. If your version of Emacs is ≤ 30 but
also includes Transient as a built-in package, you will need to set the
customizable variable ~package-install-upgrade-built-in~ to ~t~ to enable
updating it via ~package.el~. Set this variable and proceed with installing
Casual. Alternately invoking ~package-install~ with a prefix [...]
-
-If you already have the latest version of Magit installed (via
[[https://elpa.nongnu.org/nongnu/magit.html][non-GNU ELPA]] or
[[https://melpa.org/#/magit][MELPA]]), you can bypass the above instruction as
Magit already includes the Transient package as a dependency.
-
-
* UX Conventions
#+CINDEX: UX Conventions
@@ -201,7 +201,7 @@ If ~casual-lib-use-unicode~ is set to ~t~, it is also
recommended that the varia
#+TEXINFO: @majorheading Common Key Bindings
-Listed below are keybindings which are common among Casual menus.
+Listed below are keybindings which are common among Casual menus.
- {{{kbd(J)}}} Jump to Bookmark…
@@ -213,7 +213,7 @@ Listed below are keybindings which are common among Casual
menus.
- {{{kbd(j)}}} Goto… (mode specific)
- Many modes provide a list of items. The binding {{{kbd(j)}}} is used to map
to the command to move the point to an item that the user explicitly specifies.
+ Many modes provide a list of items. If a command exists that allows the user
to jump to a specified item, the binding {{{kbd(j)}}} is mapped to it.
- {{{kbd(n)}}} Next, {{{kbd(p)}}} Previous
@@ -223,6 +223,15 @@ Listed below are keybindings which are common among
Casual menus.
For modes that organize items into sections, navigation to a next or
previous section is bound to {{{kbd([)}}} and {{{kbd(])}}} respectively.
+
+#+TEXINFO: @majorheading Label Conventions
+
+Casual annotates menu labels with the following conventions:
+
+- ‘…’ :: If the label ends with an ellipsis, then the command will prompt the
user for input.
+- ‘›’ :: If the label ends with a right-pointing arrow, then the item will
raise a sub-menu.
+- ‘ⁿ’ :: If the label ends with the superscript ‘ⁿ’, then the command supports
a prefix {{{kbd(C-u)}}}.
+
* Casual Modes
#+CINDEX: Casual Modes
@@ -239,6 +248,7 @@ The following modes are supported by Casual:
#+INCLUDE: "./compile.org" :minlevel 2
#+INCLUDE: "./dired.org" :minlevel 2
#+INCLUDE: "./editkit.org" :minlevel 2
+#+INCLUDE: "./elisp.org" :minlevel 2
#+INCLUDE: "./eshell.org" :minlevel 2
#+INCLUDE: "./help.org" :minlevel 2
#+INCLUDE: "./ibuffer.org" :minlevel 2
diff --git a/docs/casual.texi b/docs/casual.texi
index ecdd6cfb2c..f3f12cb48b 100644
--- a/docs/casual.texi
+++ b/docs/casual.texi
@@ -33,9 +33,7 @@ Copyright © 2024-2025 Charles Y@. Choi
@node Top
@top Casual User Guide
-Pre-release Version: 2.8.0
-
-NOTE: THIS USER GUIDE IS A WORK IN PROGRESS@.
+Version: 2.8.0
Casual is a project to re-imagine the primary user interface for Emacs using
keyboard-driven menus.
@@ -47,6 +45,12 @@ Casual has no aims to be a mutually exclusive user
interface. All existing user
To learn more about the motivations and design considerations for Casual and
to see it at work, please watch the presentation
@uref{https://emacsconf.org/2024/talks/casual/, “Re-imagining the Emacs User
Experience with Casual Suite”} from EmacsConf 2024.
+If you enjoy using Casual, consider making a modest financial contribution to
help support its development and maintenance.
+
+@image{images/default-yellow,,,,png}
+
+@uref{https://www.buymeacoffee.com/kickingvegas}
+
@end ifnottex
@menu
@@ -73,10 +77,10 @@ Introduction
Install
-* Upgrading to Casual 2.x: Upgrading to Casual 2x.
* A Note on Package Dependencies::
+* Upgrading to Casual 1.x to 2.x: Upgrading to Casual 1x to 2x.
-Upgrading to Casual 2.x
+Upgrading to Casual 1.x to 2.x
* If you do not use @code{use-package} to configure Casual::
* If you have used @code{use-package} to configure Casual::
@@ -90,6 +94,7 @@ Casual Modes
* Compile::
* Dired::
* EditKit::
+* Elisp::
* Eshell::
* Help::
* IBuffer::
@@ -172,6 +177,11 @@ EditKit Usage
* Macro::
* EditKit Settings::
+Elisp
+
+* Elisp Install::
+* Elisp Usage::
+
Eshell
* Eshell Install::
@@ -395,12 +405,14 @@ Configuration of a particular Casual user interface is
performed per mode. Go to
@item
@ref{Calendar Install, , Calendar}
@item
-@ref{Compile Install, , Compile}
+@ref{Compile Install, , Compile (Grep)}
@item
@ref{Dired Install, , Dired}
@item
@ref{EditKit Install, , EditKit}
@item
+@ref{Elisp Install, , Elisp}
+@item
@ref{Eshell Install, , Eshell}
@item
@ref{Help Install, , Help}
@@ -423,12 +435,19 @@ Configuration of a particular Casual user interface is
performed per mode. Go to
@end itemize
@menu
-* Upgrading to Casual 2.x: Upgrading to Casual 2x.
* A Note on Package Dependencies::
+* Upgrading to Casual 1.x to 2.x: Upgrading to Casual 1x to 2x.
@end menu
-@node Upgrading to Casual 2x
-@section Upgrading to Casual 2.x
+@node A Note on Package Dependencies
+@section A Note on Package Dependencies
+
+Casual requires a recent installation of Transient 0.9.0+ from either
@uref{https://elpa.gnu.org/packages/transient.html, ELPA} or
@uref{https://melpa.org/#/transient, MELPA}. If your version of Emacs is ≤ 30
but also includes Transient as a built-in package, you will need to set the
customizable variable @code{package-install-upgrade-built-in} to @code{t} to
enable updating it via @code{package.el}. Set this variable and proceed with
installing Casual. Alternately invoking @code{packa [...]
+
+If you already have the latest version of Magit installed (via
@uref{https://elpa.nongnu.org/nongnu/magit.html, non-GNU ELPA} or
@uref{https://melpa.org/#/magit, MELPA}), you can bypass the above instruction
as Magit already includes the Transient package as a dependency.
+
+@node Upgrading to Casual 1x to 2x
+@section Upgrading to Casual 1.x to 2.x
If you have been using an earlier version 1.x of Casual, thank you. Please use
the following guidance:
@@ -460,13 +479,6 @@ For version 2.x going forward, I (Charles Choi) have
decided to not offer any do
That said, if you have used @code{:ensure t} to install a superseded package,
you @emph{must} remove that configuration. After doing so, please follow the
above instructions for installing @code{casual}.
-@node A Note on Package Dependencies
-@section A Note on Package Dependencies
-
-Casual requires a recent installation of Transient 0.9.0+ from either
@uref{https://elpa.gnu.org/packages/transient.html, ELPA} or
@uref{https://melpa.org/#/transient, MELPA}. If your version of Emacs is ≤ 30
but also includes Transient as a built-in package, you will need to set the
customizable variable @code{package-install-upgrade-built-in} to @code{t} to
enable updating it via @code{package.el}. Set this variable and proceed with
installing Casual. Alternately invoking @code{packa [...]
-
-If you already have the latest version of Magit installed (via
@uref{https://elpa.nongnu.org/nongnu/magit.html, non-GNU ELPA} or
@uref{https://melpa.org/#/magit, MELPA}), you can bypass the above instruction
as Magit already includes the Transient package as a dependency.
-
@node UX Conventions
@chapter UX Conventions
@@ -494,7 +506,7 @@ If @code{casual-lib-use-unicode} is set to @code{t}, it is
also recommended that
@majorheading Common Key Bindings
-Listed below are keybindings which are common among Casual menus.
+Listed below are keybindings which are common among Casual menus.
@itemize
@item
@@ -510,7 +522,7 @@ Many modes have settings specific to them. The binding
@kbd{,} is used in many m
@item
@kbd{j} Goto… (mode specific)
-Many modes provide a list of items. The binding @kbd{j} is used to map to the
command to move the point to an item that the user explicitly specifies.
+Many modes provide a list of items. If a command exists that allows the user
to jump to a specified item, the binding @kbd{j} is mapped to it.
@item
@kbd{n} Next, @kbd{p} Previous
@@ -523,6 +535,20 @@ For modes that provide a list of items, navigation to a
next or previous item is
For modes that organize items into sections, navigation to a next or previous
section is bound to @kbd{[} and @kbd{]} respectively.
@end itemize
+
+@majorheading Label Conventions
+
+Casual annotates menu labels with the following conventions:
+
+@table @asis
+@item ‘…’
+If the label ends with an ellipsis, then the command will prompt the user for
input.
+@item ‘›’
+If the label ends with a right-pointing arrow, then the item will raise a
sub-menu.
+@item ‘ⁿ’
+If the label ends with the superscript ‘ⁿ’, then the command supports a prefix
@kbd{C-u}.
+@end table
+
@node Casual Modes
@chapter Casual Modes
@@ -542,6 +568,7 @@ The following modes are supported by Casual:
* Compile::
* Dired::
* EditKit::
+* Elisp::
* Eshell::
* Help::
* IBuffer::
@@ -1014,11 +1041,13 @@ By enabling “@kbd{u} Use Unicode Symbols” from the
Settings menu, Casual Cal
@section Compile
@cindex Compile
+@cindex compilation-mode
+@cindex grep-mode
@vindex casual-compile-tmenu
-Casual Compile is a user interface for the output of the @code{compile}
command (@ref{Compilation,,,emacs,}). This output buffer uses the major mode
@code{compilation-mode}, whose commands are surfaced by Casual Compile.
+Casual Compile is a user interface for the output of the @code{compile}
command (@ref{Compilation,,,emacs,}). The output buffer's major mode is
@code{compilation-mode} whose commands are surfaced by Casual Compile.
-The output of Emacs-wrapped Grep commands such as @code{rgrep}, @code{grep},
and @code{lgrep} uses @code{grep-mode} which is derived from
@code{compilation-mode}. As such the main menu @code{casual-compile-tmenu} can
be used for both @code{compile} and Grep commands.
+In similar fashion, output of Emacs-wrapped Grep commands (@ref{Grep
Searching,,,emacs,}) is also supported by Casual Compile. This is because the
output of Grep commands use the major mode @code{grep-mode} which is derived
from @code{compilation-mode}.
The screenshot below shows the menu for compilation results.
@@ -1038,39 +1067,34 @@ The screenshot below shows the menu for Grep results.
Note the menu label change
@cindex Compile Install
-In your initialization file, bind the Transient @code{casual-compile-tmenu} to
your key binding of preference.
+In your initialization file, bind the Transient @code{casual-compile-tmenu} to
your key binding of preference. It should be bound in two maps:
@code{compilation-mode-map} and @code{grep-mode-map}.
@lisp
(keymap-set compilation-mode-map "C-o" #'casual-compile-tmenu)
+(keymap-set grep-mode-map "C-o" #'casual-compile-tmenu)
@end lisp
-@code{casual-compile-tmenu} deviates from the default bindings of
@code{compilation-mode-map} as shown in the table below to support using a
single key on an @samp{en.US} keyboard.
+@code{casual-compile-tmenu} deviates from the default bindings of
@code{compilation-mode-map} as shown in the table below to support using a
single key on an @samp{en.US} keyboard.
-@multitable {aaaaaaaaaaaaaaa} {aaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaa}
{aaaaaaaaaaaaaaaaaaa}
+@multitable {aaaaaaaaaaaaaaa} {aaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaa}
@headitem Default Binding
@tab Casual Binding
@tab Command
-@tab Notes
@item M-p
@tab k
@tab compilation-previous-error
-@tab vi-style navigation
@item M-n
@tab j
@tab compilation-next-error
-@tab vi-style navigation
@item M-@{
@tab [
@tab compilation-previous-file
-@tab
@item M-@}
@tab ]
@tab compilation-next-file
-@tab
@item C-o
@tab o
@tab compilation-display-error
-@tab
@end multitable
The following keybindings are recommended to support consistent behavior
between @code{compilation-mode-map} and @code{casual-compile-tmenu}.
@@ -1083,6 +1107,16 @@ The following keybindings are recommended to support
consistent behavior between
(keymap-set compilation-mode-map "]" #'compilation-next-file)
@end lisp
+Similar treatment for @code{grep-mode-map} can be done.
+
+@lisp
+(keymap-set grep-mode-map "k" #'compilation-previous-error)
+(keymap-set grep-mode-map "j" #'compilation-next-error)
+(keymap-set grep-mode-map "o" #'compilation-display-error)
+(keymap-set grep-mode-map "[" #'compilation-previous-file)
+(keymap-set grep-mode-map "]" #'compilation-next-file)
+@end lisp
+
@node Compile Usage
@subsection Compile Usage
@@ -1098,15 +1132,14 @@ The following sections are offered in the menu:
@item Follow
Navigate the point while opening the location of the error in the source file
in another window.
@item Error
-Error operations.
+Error commands for navigation and viewing.
@item File
If there are errors in multiple files, navigate to the file.
@item Compile
Get compile for different Elisp types. Note that the “@kbd{k} Kill” item is
displayed when there is a running job.
@end table
-
-If the output window is from a Grep command, @code{casual-compile-tmenu} will
adjust its label accordingly as shown below.
+If the output window is from a Grep command, @code{casual-compile-tmenu} will
adjust its labels accordingly as shown below.
@image{images/casual-compile-grep-screenshot,,,,png}
@@ -1645,6 +1678,75 @@ Those commands will instead apply to the current buffer.
The variables listed ab
@image{images/casual-editkit-settings-screenshot,,,,png}
+@node Elisp
+@section Elisp
+
+@cindex Elisp
+@vindex casual-elisp-tmenu
+
+Casual Elisp is a user interface for @code{emacs-lisp-mode}. It provides a
menu for commands useful for Elisp development.
+
+@image{images/casual-elisp-screenshot,,,,png}
+
+@menu
+* Elisp Install::
+* Elisp Usage::
+@end menu
+
+@node Elisp Install
+@subsection Elisp Install
+
+@cindex Elisp Install
+
+In your initialization file, bind the Transient @code{casual-elisp-tmenu} to
your key binding of preference. Suggested bindings include @kbd{M-m} and
@kbd{C-c m}. This menu is intended to be auxiliary to @ref{EditKit, , Casual
EditKit}.
+
+@lisp
+(keymap-set emacs-lisp-mode-map "M-m" #'casual-elisp-tmenu)
+@end lisp
+
+@node Elisp Usage
+@subsection Elisp Usage
+
+@cindex Elisp Usage
+
+@image{images/casual-elisp-screenshot,,,,png}
+
+Invoke the Casual Elisp main menu @code{casual-elisp-tmenu} via the binding
@kbd{M-m} (or your binding of preference) in an Elisp window. Typically this is
whenever an @samp{.el} file is opened.
+
+The following sections are offered in the menu:
+
+@table @asis
+@item Evaluate
+Commands to evaluate or execute an Elisp expression (@ref{Eval,,,elisp,}).
+
+@item Xref
+Cross-referencing commands (@ref{Xref,,,emacs,}).
+
+@item Checkdoc
+Checks docstrings in the file.
+
+@item Byte-Compile
+Commands for byte-compilation (@ref{Byte Compilation,,,elisp,}).
+
+@item Find
+Find commands.
+
+@item Navigate
+Commands for Sexp (balanced expression) navigation.
+@end table
+
+
+@majorheading Edebug Support
+@cindex Edebug
+
+Using the prefix @kbd{C-u} when @code{casual-elisp-tmenu} is raised will
change the “@kbd{d} Defunⁿ” menu item to “@kbd{d} Edebugⁿ” to support
instrumenting a function for Edebug (@ref{Edebug,,,elisp,}).
+
+@image{images/casual-elisp-edebug-screenshot,,,,png}
+
+@majorheading Elisp Unicode Symbol Support
+
+By enabling “@kbd{u} Use Unicode Symbols” from the Settings menu, Casual Elisp
will use Unicode symbols as appropriate in its menus.
+
@node Eshell
@section Eshell
diff --git a/docs/compile.org b/docs/compile.org
index b6e0514f30..167cc2a505 100644
--- a/docs/compile.org
+++ b/docs/compile.org
@@ -1,10 +1,12 @@
* Compile
#+CINDEX: Compile
+#+CINDEX: compilation-mode
+#+CINDEX: grep-mode
#+VINDEX: casual-compile-tmenu
-Casual Compile is a user interface for the output of the ~compile~ command
([[info:emacs#Compilation]]). This output buffer uses the major mode
~compilation-mode~, whose commands are surfaced by Casual Compile.
+Casual Compile is a user interface for the output of the ~compile~ command
([[info:emacs#Compilation]]). The output buffer's major mode is
~compilation-mode~ whose commands are surfaced by Casual Compile.
-The output of Emacs-wrapped Grep commands such as ~rgrep~, ~grep~, and ~lgrep~
uses ~grep-mode~ which is derived from ~compilation-mode~. As such the main
menu ~casual-compile-tmenu~ can be used for both ~compile~ and Grep commands.
+In similar fashion, output of Emacs-wrapped Grep commands ([[info:emacs#Grep
Searching]]) is also supported by Casual Compile. This is because the output of
Grep commands use the major mode ~grep-mode~ which is derived from
~compilation-mode~.
The screenshot below shows the menu for compilation results.
@@ -13,7 +15,6 @@ The screenshot below shows the menu for compilation results.
The screenshot below shows the menu for Grep results. Note the menu label
changes based on the output mode (in this case ~grep-mode~).
[[file:images/casual-compile-grep-screenshot.png]]
-
** Compile Install
:PROPERTIES:
:CUSTOM_ID: compile-install
@@ -21,21 +22,22 @@ The screenshot below shows the menu for Grep results. Note
the menu label change
#+CINDEX: Compile Install
-In your initialization file, bind the Transient ~casual-compile-tmenu~ to your
key binding of preference.
+In your initialization file, bind the Transient ~casual-compile-tmenu~ to your
key binding of preference. It should be bound in two maps:
~compilation-mode-map~ and ~grep-mode-map~.
#+begin_src elisp :lexical no
(keymap-set compilation-mode-map "C-o" #'casual-compile-tmenu)
+ (keymap-set grep-mode-map "C-o" #'casual-compile-tmenu)
#+end_src
-~casual-compile-tmenu~ deviates from the default bindings of
~compilation-mode-map~ as shown in the table below to support using a single
key on an =en.US= keyboard.
+~casual-compile-tmenu~ deviates from the default bindings of
~compilation-mode-map~ as shown in the table below to support using a single
key on an =en.US= keyboard.
-| Default Binding | Casual Binding | Command | Notes
|
-|-----------------+----------------+----------------------------+---------------------|
-| M-p | k | compilation-previous-error | vi-style
navigation |
-| M-n | j | compilation-next-error | vi-style
navigation |
-| M-{ | [ | compilation-previous-file |
|
-| M-} | ] | compilation-next-file |
|
-| C-o | o | compilation-display-error |
|
+| Default Binding | Casual Binding | Command |
+|-----------------+----------------+----------------------------|
+| M-p | k | compilation-previous-error |
+| M-n | j | compilation-next-error |
+| M-{ | [ | compilation-previous-file |
+| M-} | ] | compilation-next-file |
+| C-o | o | compilation-display-error |
The following keybindings are recommended to support consistent behavior
between ~compilation-mode-map~ and ~casual-compile-tmenu~.
@@ -47,6 +49,17 @@ The following keybindings are recommended to support
consistent behavior between
(keymap-set compilation-mode-map "]" #'compilation-next-file)
#+end_src
+Similar treatment for ~grep-mode-map~ can be done.
+
+#+BEGIN_SRC elisp :lexical no
+ (keymap-set grep-mode-map "k" #'compilation-previous-error)
+ (keymap-set grep-mode-map "j" #'compilation-next-error)
+ (keymap-set grep-mode-map "o" #'compilation-display-error)
+ (keymap-set grep-mode-map "[" #'compilation-previous-file)
+ (keymap-set grep-mode-map "]" #'compilation-next-file)
+#+END_SRC
+
+
** Compile Usage
#+CINDEX: Compile Usage
@@ -57,12 +70,11 @@ After running ~compile~, invoke ~casual-compile-tmenu~ in
the buffer named =✳
The following sections are offered in the menu:
- Follow :: Navigate the point while opening the location of the error in the
source file in another window.
-- Error :: Error operations.
+- Error :: Error commands for navigation and viewing.
- File :: If there are errors in multiple files, navigate to the file.
- Compile :: Get compile for different Elisp types. Note that the
“{{{kbd(k)}}} Kill” item is displayed when there is a running job.
-
-If the output window is from a Grep command, ~casual-compile-tmenu~ will
adjust its label accordingly as shown below.
+If the output window is from a Grep command, ~casual-compile-tmenu~ will
adjust its labels accordingly as shown below.
[[file:images/casual-compile-grep-screenshot.png]]
diff --git a/docs/editkit.org b/docs/editkit.org
index 16111cad79..2021c86a51 100644
--- a/docs/editkit.org
+++ b/docs/editkit.org
@@ -1,4 +1,7 @@
* EditKit
+:PROPERTIES:
+:CUSTOM_ID: editkit
+:END:
#+CINDEX: EditKit
#+VINDEX: casual-editkit-main-tmenu
diff --git a/docs/elisp.org b/docs/elisp.org
new file mode 100644
index 0000000000..0c8beed86a
--- /dev/null
+++ b/docs/elisp.org
@@ -0,0 +1,55 @@
+* Elisp
+#+CINDEX: Elisp
+#+VINDEX: casual-elisp-tmenu
+
+Casual Elisp is a user interface for ~emacs-lisp-mode~. It provides a menu for
commands useful for Elisp development.
+
+[[file:images/casual-elisp-screenshot.png]]
+
+** Elisp Install
+:PROPERTIES:
+:CUSTOM_ID: elisp-install
+:END:
+
+#+CINDEX: Elisp Install
+
+In your initialization file, bind the Transient ~casual-elisp-tmenu~ to your
key binding of preference. Suggested bindings include {{{kbd(M-m)}}} and
{{{kbd(C-c m)}}}. This menu is intended to be auxiliary to [[#editkit][Casual
EditKit]].
+
+#+begin_src elisp :lexical no
+ (keymap-set emacs-lisp-mode-map "M-m" #'casual-elisp-tmenu)
+#+end_src
+
+
+** Elisp Usage
+#+CINDEX: Elisp Usage
+
+[[file:images/casual-elisp-screenshot.png]]
+
+Invoke the Casual Elisp main menu ~casual-elisp-tmenu~ via the binding
{{{kbd(M-m)}}} (or your binding of preference) in an Elisp window. Typically
this is whenever an =.el= file is opened.
+
+The following sections are offered in the menu:
+
+- Evaluate :: Commands to evaluate or execute an Elisp expression
([[info:elisp#Eval]]).
+
+- Xref :: Cross-referencing commands ([[info:emacs#Xref]]).
+
+- Checkdoc :: Checks docstrings in the file.
+
+- Byte-Compile :: Commands for byte-compilation ([[info:elisp#Byte
Compilation]]).
+
+- Find :: Find commands.
+
+- Navigate :: Commands for Sexp (balanced expression) navigation.
+
+
+#+TEXINFO: @majorheading Edebug Support
+#+CINDEX: Edebug
+
+Using the prefix {{{kbd(C-u)}}} when ~casual-elisp-tmenu~ is raised will
change the “{{{kbd(d)}}} Defunⁿ” menu item to “{{{kbd(d)}}} Edebugⁿ” to support
instrumenting a function for Edebug ([[info:elisp#Edebug]]).
+
+[[file:images/casual-elisp-edebug-screenshot.png]]
+
+#+TEXINFO: @majorheading Elisp Unicode Symbol Support
+
+By enabling “{{{kbd(u)}}} Use Unicode Symbols” from the Settings menu, Casual
Elisp will use Unicode symbols as appropriate in its menus.
+
diff --git a/docs/images/casual-elisp-edebug-screenshot.png
b/docs/images/casual-elisp-edebug-screenshot.png
new file mode 100644
index 0000000000..9187e567ad
Binary files /dev/null and b/docs/images/casual-elisp-edebug-screenshot.png
differ
diff --git a/docs/images/casual-elisp-screenshot.png
b/docs/images/casual-elisp-screenshot.png
new file mode 100644
index 0000000000..cf2c92c7e5
Binary files /dev/null and b/docs/images/casual-elisp-screenshot.png differ
diff --git a/docs/sponsorship.org b/docs/sponsorship.org
new file mode 100644
index 0000000000..06c06b9e83
--- /dev/null
+++ b/docs/sponsorship.org
@@ -0,0 +1,5 @@
+If you enjoy using Casual, consider making a modest financial contribution to
help support its development and maintenance.
+
+[[file:images/default-yellow.png]]
+
+[[https://www.buymeacoffee.com/kickingvegas]]
diff --git a/lisp/Makefile b/lisp/Makefile
index 750b1597ad..bcce5008c9 100644
--- a/lisp/Makefile
+++ b/lisp/Makefile
@@ -26,6 +26,7 @@ calendar-tests \
compile-tests \
dired-tests \
editkit-tests \
+elisp-tests \
eshell-tests \
help-tests \
ibuffer-tests \
@@ -68,6 +69,10 @@ dired-tests:
editkit-tests:
$(MAKE) -C $(SRC_DIR) -f Makefile-editkit.make tests
+.PHONY: elisp-tests
+elisp-tests:
+ $(MAKE) -C $(SRC_DIR) -f Makefile-elisp.make tests
+
.PHONY: eshell-tests
eshell-tests:
$(MAKE) -C $(SRC_DIR) -f Makefile-eshell.make tests
diff --git a/lisp/Makefile-elisp.make b/lisp/Makefile-elisp.make
new file mode 100644
index 0000000000..f9d2fb8466
--- /dev/null
+++ b/lisp/Makefile-elisp.make
@@ -0,0 +1,30 @@
+##
+# Copyright (C) 2025 Charles Y. Choi
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+include Makefile--defines.make
+
+PACKAGE_NAME=casual-elisp
+ELISP_INCLUDES=casual-elisp-utils.el \
+casual-elisp-settings.el
+ELISP_PACKAGES=
+ELISP_TEST_INCLUDES=casual-elisp-test-utils.el
+PACKAGE_PATHS= \
+-L $(EMACS_ELPA_DIR)/compat-current \
+-L $(EMACS_ELPA_DIR)/seq-current \
+-L $(EMACS_ELPA_DIR)/transient-current \
+-L $(CASUAL_LIB_LISP_DIR)
+
+include Makefile--rules.make
diff --git a/lisp/casual-compile.el b/lisp/casual-compile.el
index 071dc0641f..9486eebe40 100644
--- a/lisp/casual-compile.el
+++ b/lisp/casual-compile.el
@@ -20,15 +20,30 @@
;;; Commentary:
+
+;; Casual Compile is a user interface for the output of the `compile' command.
+;; The output buffer's major mode is `compilation-mode' whose commands are
+;; surfaced by Casual Compile.
+
+;; In similar fashion, output of Emacs-wrapped Grep commands is also supported
+;; by Casual Compile. This is because the output of Grep commands use the major
+;; mode `grep-mode' which is derived from `compilation-mode'.
+
;; This library provides a Transient-based user interface for
;; `compilation-mode'.
;; INSTALL
;; In your initialization file, bind the Transient `casual-compile-tmenu' to
-;; your key binding of preference.
+;; your key binding of preference. It should be bound in two maps:
+;; `compilation-mode-map' and `grep-mode-map'.
;; (keymap-set compilation-mode-map "C-o" #'casual-compile-tmenu)
+;; (keymap-set grep-mode-map "C-o" #'casual-compile-tmenu)
+
+;; `casual-compile-tmenu' deviates from the default bindings of
+;; `compilation-mode-map' as shown in the table below to support using a single
+;; key on an en.US keyboard.
;; The following keybindings are recommended to support consistent behavior
;; between `compilation-mode-map' and `casual-compile-tmenu'.
@@ -39,10 +54,19 @@
;; (keymap-set compilation-mode-map "[" #'compilation-previous-file)
;; (keymap-set compilation-mode-map "]" #'compilation-next-file)
+;; Similar treatment for `grep-mode-map' can be done.
+
+;; (keymap-set grep-mode-map "k" #'compilation-previous-error)
+;; (keymap-set grep-mode-map "j" #'compilation-next-error)
+;; (keymap-set grep-mode-map "o" #'compilation-display-error)
+;; (keymap-set grep-mode-map "[" #'compilation-previous-file)
+;; (keymap-set grep-mode-map "]" #'compilation-next-file)
+
;;; Code:
(require 'casual-compile-settings)
(require 'casual-compile-utils)
+;;;###autoload (autoload 'casual-compile-tmenu "casual-compile" nil t)
(transient-define-prefix casual-compile-tmenu ()
"Casual main menu for `compilation-mode'."
:refresh-suffixes t
diff --git a/lisp/casual-elisp-settings.el b/lisp/casual-elisp-settings.el
new file mode 100644
index 0000000000..3053d1516e
--- /dev/null
+++ b/lisp/casual-elisp-settings.el
@@ -0,0 +1,68 @@
+;;; casual-elisp-settings.el --- Casual Elisp Settings -*- lexical-binding: t;
-*-
+
+;; Copyright (C) 2025 Charles Y. Choi
+
+;; Author: Charles Choi <[email protected]>
+;; Keywords: tools
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+
+;;; Code:
+(require 'elisp-mode)
+(require 'casual-lib)
+
+(transient-define-prefix casual-elisp-settings-tmenu ()
+ "Casual Elisp settings menu."
+ ["Customize"
+ (casual-lib-customize-unicode)
+ (casual-lib-customize-hide-navigation)]
+
+ [:class transient-row
+ (casual-lib-quit-one)
+ ("a" "About" casual-elisp-about :transient nil)
+ (casual-lib-quit-all)])
+
+(defun casual-elisp-about-elisp ()
+ "Casual Elisp is a Transient menu for `emacs-lisp-mode'.
+
+Learn more about using Casual Elisp at our discussion group on GitHub.
+Any questions or comments about it should be made there.
+URL `https://github.com/kickingvegas/casual/discussions'
+
+If you find a bug or have an enhancement request, please file an issue.
+Our best effort will be made to answer it.
+URL `https://github.com/kickingvegas/casual/issues'
+
+If you enjoy using Casual Elisp, consider making a modest financial
+contribution to help support its development and maintenance.
+URL `https://www.buymeacoffee.com/kickingvegas'
+
+Casual Elisp was conceived and crafted by Charles Choi in San Francisco,
+California.
+
+Thank you for using Casual Elisp.
+
+Always choose love."
+ (ignore))
+
+(defun casual-elisp-about ()
+ "About information for Casual Elisp."
+ (interactive)
+ (describe-function #'casual-elisp-about-elisp))
+
+(provide 'casual-elisp-settings)
+;;; casual-elisp-settings.el ends here
diff --git a/lisp/casual-elisp-utils.el b/lisp/casual-elisp-utils.el
new file mode 100644
index 0000000000..cf24478e0e
--- /dev/null
+++ b/lisp/casual-elisp-utils.el
@@ -0,0 +1,72 @@
+;;; casual-elisp-utils.el --- Casual Elisp Utils -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2025 Charles Y. Choi
+
+;; Author: Charles Choi <[email protected]>
+;; Keywords: tools
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+
+;;; Code:
+(require 'xref)
+(require 'elisp-mode)
+(require 'casual-lib)
+
+(defconst casual-elisp-unicode-db
+ '((:backward-char . '("←" "Char"))
+ (:backward-sexp . '("(←)" "Sexp"))
+ (:forward-char . '("→" "Char"))
+ (:forward-sexp . '("(→)" "Sexp"))
+
+ (:previous-line . '("↑" "Line"))
+ (:backward-up-list . '("(↰" "Sexp"))
+
+ (:next-line . '("↓" "Line"))
+ (:down-list . '("⤵(" "Sexp")))
+
+ "Unicode symbol DB to use for Elisp Transient menus.")
+
+(defun casual-elisp-unicode-get (key)
+ "Lookup Unicode symbol for KEY in DB.
+
+- KEY symbol used to lookup Unicode symbol in DB.
+
+If the value of customizable variable `casual-lib-use-unicode'
+is non-nil, then the Unicode symbol is returned, otherwise a
+plain ASCII-range string."
+ (casual-lib-unicode-db-get key casual-elisp-unicode-db))
+
+(defun casual-elisp--next-sexp-raw ()
+ "Raw implementation to move point to the beginning of the next sexp.
+
+This function has no error checking."
+ (forward-sexp 2)
+ (backward-sexp))
+
+(defun casual-elisp-next-sexp ()
+ "Move point to beginning of the next balanced expression (sexp)."
+ (interactive)
+ (condition-case nil
+ (casual-elisp--next-sexp-raw)
+ (error (condition-case nil
+ (forward-sexp)
+ (error
+ (message
+ "Unable to move point to next balanced expression (sexp)."))))))
+
+(provide 'casual-elisp-utils)
+;;; casual-elisp-utils.el ends here
diff --git a/lisp/casual-elisp.el b/lisp/casual-elisp.el
new file mode 100644
index 0000000000..cdee46fdde
--- /dev/null
+++ b/lisp/casual-elisp.el
@@ -0,0 +1,110 @@
+;;; casual-elisp.el --- Transient UI for Elisp Mode -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2025 Charles Choi
+
+;; Author: Charles Choi <[email protected]>
+;; Keywords: tools
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library provides a Transient-based user interface for
`emacs-lisp-mode'.
+
+;; INSTALL
+
+;; In your initialization file, bind the Transient `casual-elisp-tmenu' to
+;; your key binding of preference.
+
+;; (keymap-set emacs-lisp-mode-map "M-m" #'casual-elisp-tmenu)
+
+;;; Code:
+
+(require 'xref)
+(require 'find-func)
+(require 'casual-elisp-settings)
+(require 'casual-elisp-utils)
+
+;;;###autoload (autoload 'casual-elisp-tmenu "casual-elisp" nil t)
+(transient-define-prefix casual-elisp-tmenu ()
+ ["Casual Elisp"
+ :description (lambda () (format "Casual Elisp: %s" (buffer-name)))
+ ["Evaluate"
+ ("x" "Last Sexp" eval-last-sexp)
+ ("L" "Buffer or Region" elisp-eval-region-or-buffer
+ :description (lambda () (if (use-region-p) "Region" "Buffer")))
+ ("d" "Defun" eval-defun
+ :description (lambda () (if prefix-arg "Edebugⁿ" "Defunⁿ")))]
+
+ ["Xref"
+ ("." "Definition" xref-find-definitions)
+ ("r" "References" xref-find-references)
+ ("R" "Replace" xref-find-references-and-replace)]
+
+ ["Checkdoc"
+ ("c" "Checkdoc" checkdoc)]
+
+ ["Byte-Compile"
+ ("B" "File" elisp-byte-compile-file)
+ ("b" "Buffer" elisp-byte-compile-buffer)
+ ("D" "Directory…" byte-recompile-directory)]
+
+ ["Find"
+ ("l" "Library…" find-library)
+ ("v" "Variable…" find-variable)
+ ("f" "Function…" find-function)]]
+
+ ["Navigate"
+ :pad-keys t
+ ["Backward"
+ :pad-keys t
+ ("<left>" "Char" backward-char
+ :description (lambda () (casual-elisp-unicode-get :backward-char))
+ :transient t)
+ ("C-<left>" "Sexp" backward-sexp
+ :description (lambda () (casual-elisp-unicode-get :backward-sexp))
+ :transient t)] ; "(←"
+ ["Forward"
+ :pad-keys t
+ ("<right>" "Char" forward-char
+ :description (lambda () (casual-elisp-unicode-get :forward-char))
+ :transient t)
+ ("C-<right>" "Sexp" casual-elisp-next-sexp
+ :description (lambda () (casual-elisp-unicode-get :forward-sexp))
+ :transient t)]
+ ["Up"
+ :pad-keys t
+ ("<up>" "Line" previous-line
+ :description (lambda () (casual-elisp-unicode-get :previous-line))
+ :transient t)
+ ("C-<up>" "List" backward-up-list
+ :description (lambda () (casual-elisp-unicode-get :backward-up-list))
+ :transient t)] ; "(↰"
+ ["Down"
+ :pad-keys t
+ ("<down>" "Line" next-line
+ :description (lambda () (casual-elisp-unicode-get :next-line))
+ :transient t)
+ ("C-<down>" "List" down-list
+ :description (lambda () (casual-elisp-unicode-get :down-list))
+ :transient t)]] ; "⤵("
+
+ [:class transient-row
+ (casual-lib-quit-one)
+ (casual-lib-quit-all)
+ ("," "Settings›" casual-elisp-settings-tmenu)
+ ("RET" "Dismiss" transient-quit-all)])
+
+(provide 'casual-elisp)
+;;; casual-elisp.el ends here
diff --git a/tests/Makefile b/tests/Makefile
index ae04ecd1dd..519268fb45 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -25,6 +25,7 @@ calendar-tests \
compile-tests \
dired-tests \
editkit-tests \
+elisp-tests \
eshell-tests \
help-tests \
ibuffer-tests \
@@ -45,6 +46,7 @@ calendar-tests \
compile-tests \
dired-tests \
editkit-tests \
+elisp-tests \
eshell-tests \
help-tests \
ibuffer-tests \
@@ -79,6 +81,9 @@ dired-tests:
editkit-tests:
$(MAKE) -C $(SRC_DIR) $@
+elisp-tests:
+ $(MAKE) -C $(SRC_DIR) $@
+
eshell-tests:
$(MAKE) -C $(SRC_DIR) $@
diff --git a/tests/casual-elisp-test-utils.el b/tests/casual-elisp-test-utils.el
new file mode 100644
index 0000000000..a543e82085
--- /dev/null
+++ b/tests/casual-elisp-test-utils.el
@@ -0,0 +1,43 @@
+;;; casual-elisp-test-utils.el --- Casual Test Utils -*-
lexical-binding: t; -*-
+
+;; Copyright (C) 2024-2025 Charles Y. Choi
+
+;; Author: Charles Choi <[email protected]>
+;; Keywords: tools
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+(require 'ert)
+(require 'casual-lib)
+(require 'kmacro)
+
+(defun casualt-elisp-setup (&optional filename)
+ "Casual menu test setup function."
+ (when filename
+ (let ((temp-filename (concat "/tmp/" filename)))
+ )))
+
+(defun casualt-elisp-breakdown (&optional filename)
+ "Casual menu test breakdown function, if CLEAR is non-nil then clear state."
+ (when filename
+ (let ((temp-filename (concat "/tmp/" filename)))
+ )))
+
+(provide 'casual-elisp-test-utils)
+;;; casual-elisp-test-utils.el ends here
diff --git a/tests/test-casual-elisp-settings.el
b/tests/test-casual-elisp-settings.el
new file mode 100644
index 0000000000..52591ce1c0
--- /dev/null
+++ b/tests/test-casual-elisp-settings.el
@@ -0,0 +1,50 @@
+;;; test-casual-elisp-settings.el --- Casual Elisp Settings Tests -*-
lexical-binding: t; -*-
+
+;; Copyright (C) 2025 Charles Y. Choi
+
+;; Author: Charles Choi <[email protected]>
+;; Keywords: tools
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+(require 'casual-elisp-test-utils)
+(require 'casual-elisp-settings)
+
+(ert-deftest test-casual-elisp-settings-tmenu ()
+ (let ()
+ (cl-letf ((casualt-mock #'casual-lib-customize-casual-lib-hide-navigation)
+ (casualt-mock #'casual-lib-customize-casual-lib-use-unicode)
+ (casualt-mock #'casual-elisp-about))
+
+ (let ((test-vectors
+ '((:binding "u" :command
casual-lib-customize-casual-lib-use-unicode)
+ (:binding "n" :command
casual-lib-customize-casual-lib-hide-navigation)
+ (:binding "a" :command casual-elisp-about))))
+
+ (casualt-suffix-testcase-runner test-vectors
+ #'casual-elisp-settings-tmenu
+ '(lambda () (random 5000)))))))
+
+(ert-deftest test-casual-elisp-about ()
+ (should (stringp (casual-elisp-about))))
+
+(provide 'test-casual-elisp-settings)
+;;; test-casual-elisp-setttings.el ends here
diff --git a/tests/test-casual-elisp-utils.el b/tests/test-casual-elisp-utils.el
new file mode 100644
index 0000000000..32a78a88bf
--- /dev/null
+++ b/tests/test-casual-elisp-utils.el
@@ -0,0 +1,52 @@
+;;; test-casual-elisp-utils.el --- Casual Make Utils Tests -*-
lexical-binding: t; -*-
+
+;; Copyright (C) 2025 Charles Y. Choi
+
+;; Author: Charles Choi <[email protected]>
+;; Keywords: tools
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+(require 'ert)
+(require 'casual-elisp-test-utils)
+(require 'casual-elisp-utils)
+
+(ert-deftest test-casual-elisp-unicode-get ()
+ (let ((casual-lib-use-unicode nil))
+ (should (string-equal (casual-elisp-unicode-get :backward-char) "Char"))
+ (should (string-equal (casual-elisp-unicode-get :backward-sexp) "Sexp"))
+ (should (string-equal (casual-elisp-unicode-get :forward-char) "Char"))
+ (should (string-equal (casual-elisp-unicode-get :forward-sexp) "Sexp"))
+ (should (string-equal (casual-elisp-unicode-get :previous-line) "Line"))
+ (should (string-equal (casual-elisp-unicode-get :next-line) "Line"))
+ (should (string-equal (casual-elisp-unicode-get :backward-up-list) "Sexp"))
+ (should (string-equal (casual-elisp-unicode-get :down-list) "Sexp")))
+
+ (let ((casual-lib-use-unicode t))
+ (should (string-equal (casual-elisp-unicode-get :backward-char) "←"))
+ (should (string-equal (casual-elisp-unicode-get :backward-sexp) "(←)"))
+ (should (string-equal (casual-elisp-unicode-get :forward-char) "→"))
+ (should (string-equal (casual-elisp-unicode-get :forward-sexp) "(→)"))
+ (should (string-equal (casual-elisp-unicode-get :previous-line) "↑"))
+ (should (string-equal (casual-elisp-unicode-get :next-line) "↓"))
+ (should (string-equal (casual-elisp-unicode-get :backward-up-list) "(↰"))
+ (should (string-equal (casual-elisp-unicode-get :down-list) "⤵("))))
+
+(provide 'test-casual-elisp-utils)
+;;; test-casual-elisp-utils.el ends here
diff --git a/tests/test-casual-elisp.el b/tests/test-casual-elisp.el
new file mode 100644
index 0000000000..6545c25661
--- /dev/null
+++ b/tests/test-casual-elisp.el
@@ -0,0 +1,95 @@
+;;; test-casual-elisp.el --- Casual Make Tests -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2025 Charles Y. Choi
+
+;; Author: Charles Choi <[email protected]>
+;; Keywords: tools
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+(require 'casual-elisp-test-utils)
+(require 'casual-lib-test-utils)
+(require 'casual-elisp)
+
+(ert-deftest test-casual-elisp-tmenu ()
+ (let ((tmpfile "scratch-elisp.el"))
+ (casualt-elisp-setup)
+ (cl-letf (
+ (casualt-mock #'eval-last-sexp)
+ (casualt-mock #'elisp-eval-region-or-buffer)
+ (casualt-mock #'eval-defun)
+ (casualt-mock #'xref-find-definitions)
+ (casualt-mock #'xref-find-references)
+ (casualt-mock #'xref-find-references-and-replace)
+ (casualt-mock #'checkdoc)
+ (casualt-mock #'elisp-byte-compile-file)
+ (casualt-mock #'elisp-byte-compile-buffer)
+ (casualt-mock #'byte-recompile-directory)
+ (casualt-mock #'find-library)
+ (casualt-mock #'find-variable)
+ (casualt-mock #'find-function)
+ (casualt-mock #'backward-char)
+ (casualt-mock #'backward-sexp)
+ (casualt-mock #'forward-char)
+ (casualt-mock #'casual-elisp-next-sexp)
+ (casualt-mock #'previous-line)
+ (casualt-mock #'backward-up-list)
+ (casualt-mock #'next-line)
+ (casualt-mock #'down-list)
+ (casualt-mock #'casual-elisp-settings-tmenu)
+ (casualt-mock #'transient-quit-all))
+
+ (let ((test-vectors
+ '((:binding "x" :command eval-last-sexp)
+ (:binding "L" :command elisp-eval-region-or-buffer)
+ (:binding "d" :command eval-defun)
+
+ ;;(:binding "." :command xref-find-definitions)
+ ;;(:binding "r" :command xref-find-references)
+ ;;(:binding "R" :command xref-find-references-and-replace)
+
+ (:binding "c" :command checkdoc)
+
+ (:binding "B" :command elisp-byte-compile-file)
+ (:binding "b" :command elisp-byte-compile-buffer)
+ (:binding "D" :command byte-recompile-directory)
+
+ (:binding "l" :command find-library)
+ (:binding "v" :command find-variable)
+ (:binding "f" :command find-function)
+
+ (:binding "<left>" :command backward-char)
+ (:binding "C-<left>" :command backward-sexp)
+ (:binding "<right>" :command forward-char)
+ (:binding "C-<right>" :command casual-elisp-next-sexp)
+ (:binding "<up>" :command previous-line)
+ (:binding "C-<up>" :command backward-up-list)
+ (:binding "<down>" :command next-line)
+ (:binding "C-<down>" :command down-list)
+ (:binding "RET" :command transient-quit-all))))
+
+ (casualt-suffix-testcase-runner test-vectors
+ #'casual-elisp-tmenu
+ '(lambda () (random 5000)))))
+ (casualt-elisp-breakdown)))
+
+(provide 'test-casual-elisp)
+;;; test-casual-elisp.el ends here