branch: elpa/casual
commit 596bd44432d2f5bd4593d71d1b45591f362d00bc
Merge: 7201122431 ee97098523
Author: Charles Choi <[email protected]>
Commit: GitHub <[email protected]>
Merge pull request #258 from
kickingvegas/merge-development-to-main-20250707_134219
Merge development to main 20250707_134219
---
README.org | 6 +
docs/casual.info | 134 ++++++++++++------
docs/casual.org | 36 ++++-
docs/eshell.org | 49 +++++++
docs/images/casual-eshell-process-screenshot.png | Bin 0 -> 228726 bytes
docs/images/casual-eshell-screenshot.png | Bin 0 -> 152307 bytes
lisp/Makefile | 5 +
lisp/Makefile-eshell.make | 35 +++++
lisp/casual-eshell-settings.el | 74 ++++++++++
lisp/casual-eshell-utils.el | 106 +++++++++++++++
lisp/casual-eshell.el | 151 +++++++++++++++++++++
lisp/casual.el | 2 +-
tests/Makefile | 5 +
...n-test-utils.el => casual-eshell-test-utils.el} | 17 ++-
tests/casual-help-test-utils.el | 2 +-
tests/casual-man-test-utils.el | 2 +-
tests/test-casual-eshell-settings.el | 50 +++++++
tests/test-casual-eshell-utils.el | 54 ++++++++
tests/test-casual-eshell.el | 116 ++++++++++++++++
19 files changed, 791 insertions(+), 53 deletions(-)
diff --git a/README.org b/README.org
index 1a9198c3ae..0abb08e3dd 100644
--- a/README.org
+++ b/README.org
@@ -37,6 +37,7 @@ Editorially, all design decisions for Casual are ultimately
the opinion of Charl
- [[#calendar-elisp-library-casual-calendar][Calendar (Elisp library:
~casual-calendar~)]]
- [[#dired-elisp-library-casual-dired][Dired (Elisp library:
~casual-dired~)]]
- [[#editkit-elisp-library-casual-editkit][EditKit (Elisp library:
~casual-editkit~)]]
+ - [[#eshell-elisp-library-casual-eshell][Eshell (Elisp library:
~casual-eshell~)]]
- [[#help-elisp-library-casual-help][Help (Elisp library: ~casual-help~)]]
- [[#ibuffer-elisp-library-casual-ibuffer][IBuffer (Elisp library:
~casual-ibuffer~)]]
- [[#image-elisp-library-casual-image][Image (Elisp library:
~casual-image~)]]
@@ -92,6 +93,10 @@ A cornucopia of interfaces for the different editing
features (e.g. marking, cop
[[file:docs/editkit.org][file:docs/images/casual-editkit-main-screenshot.png]]
+** [[file:docs/eshell.org][Eshell]] (Elisp library: ~casual-eshell~)
+An interface for ~Eshell~, a shell-like command interpreter implemented in
Emacs Lisp.
+
+ [[file:docs/eshell.org][file:docs/images/casual-eshell-screenshot.png]]
** [[file:docs/help.org][Help]] (Elisp library: ~casual-help~)
@@ -164,6 +169,7 @@ Configuration of a particular Casual user interface is
performed per mode. Go to
- [[file:docs/calendar.org::*Install][Calendar]]
- [[file:docs/dired.org::*Install][Dired]]
- [[file:docs/editkit.org::*Install][EditKit]]
+- [[file:docs/eshell.org::*Install][Eshell]]
- [[file:docs/help.org::*Install][Help]]
- [[file:docs/ibuffer.org::*Install][IBuffer]]
- [[file:docs/image.org::*Install][Image]]
diff --git a/docs/casual.info b/docs/casual.info
index cf889aa1c0..5c36ed3aa6 100644
--- a/docs/casual.info
+++ b/docs/casual.info
@@ -11,7 +11,7 @@ File: casual.info, Node: Top, Next: Motivations, Up: (dir)
Casual User Guide
*****************
-Version: 2.6.0
+Version: 2.7.0
Casual is a project to re-imagine the primary user interface for Emacs
using keyboard-driven menus.
@@ -61,6 +61,7 @@ Casual Modes
* Calendar::
* Dired::
* EditKit::
+* Eshell::
* Help::
* IBuffer::
* Image::
@@ -209,6 +210,7 @@ The following modes are supported by Casual:
* Calendar::
* Dired::
* EditKit::
+* Eshell::
* Help::
* IBuffer::
* Image::
@@ -624,7 +626,7 @@ References
• *note Dired: (emacs)Dired.
-File: casual.info, Node: EditKit, Next: Help, Prev: Dired, Up: Casual Modes
+File: casual.info, Node: EditKit, Next: Eshell, Prev: Dired, Up: Casual
Modes
4.6 EditKit
===========
@@ -685,9 +687,57 @@ References
• *note Registers: (emacs)Registers.
-File: casual.info, Node: Help, Next: IBuffer, Prev: EditKit, Up: Casual
Modes
+File: casual.info, Node: Eshell, Next: Help, Prev: EditKit, Up: Casual
Modes
-4.7 Help
+4.7 Eshell
+==========
+
+Casual Eshell is a user interface for ‘Eshell’, a shell-like command
+interpreter implemented in Emacs Lisp.
+
+Configuration
+=============
+
+In your initialization file, bind the Transient ‘casual-eshell-tmenu’ to
+your key binding of preference.
+
+ (require 'casual-eshell) ; optional
+ (keymap-set eshell-mode-map "C-o" #'casual-eshell-tmenu)
+
+Usage
+=====
+
+Basic Usage
+-----------
+
+Eshell can be invoked via ‘M-x eshell’. In any Eshell window, pressing
+‘C-o’ (or your binding of preference) will raise the menu
+‘casual-eshell-tmenu’.
+
+The following sections are offered in the menu:
+
+Input
+ Commands supporting input to the current prompt.
+Argument
+ Commands supporting arguments in the current prompt.
+Prompt
+ Navigation of previous prompt commands.
+Output
+ Commands related to display of prompt. Commands marked with an ‘n’
+ superscript support an optional prefix (‘C-u’) value.
+Misc
+ Miscellaneous commands.
+
+If a process is running, a section for managing signals to send to it is
+provided.
+
+Process
+ Signal commands to send to the process.
+
+
+File: casual.info, Node: Help, Next: IBuffer, Prev: Eshell, Up: Casual
Modes
+
+4.8 Help
========
Casual Help is a user interface for ‘help-mode’, a major mode for
@@ -755,7 +805,7 @@ Source
File: casual.info, Node: IBuffer, Next: Image, Prev: Help, Up: Casual Modes
-4.8 IBuffer
+4.9 IBuffer
===========
Casual IBuffer provides a user interface to Emacs IBuffer, a mode
@@ -830,8 +880,8 @@ References
File: casual.info, Node: Image, Next: Info, Prev: IBuffer, Up: Casual Modes
-4.9 Image
-=========
+4.10 Image
+==========
Casual Image is a user interface for Image Mode. Its top level library
is ‘casual-image’.
@@ -890,7 +940,7 @@ References
File: casual.info, Node: Info, Next: I-Search, Prev: Image, Up: Casual
Modes
-4.10 Info
+4.11 Info
=========
Casual Info is a user interface for the Emacs Info Reader. Its top
@@ -953,7 +1003,7 @@ References
File: casual.info, Node: I-Search, Next: Make, Prev: Info, Up: Casual Modes
-4.11 I-Search
+4.12 I-Search
=============
Casual I-Search is a user interface for Incremental Search. Its top
@@ -1005,7 +1055,7 @@ References
File: casual.info, Node: Make, Next: Man, Prev: I-Search, Up: Casual Modes
-4.12 Make
+4.13 Make
=========
Casual Make is a user interface to ‘make-mode’, a mode tailored for
@@ -1084,7 +1134,7 @@ References
File: casual.info, Node: Man, Next: RE-Builder, Prev: Make, Up: Casual
Modes
-4.13 Man
+4.14 Man
========
Casual Man is a user interface for ‘Man-mode’, a Man page reader.
@@ -1171,7 +1221,7 @@ manual pages.
File: casual.info, Node: RE-Builder, Next: Timezone, Prev: Man, Up: Casual
Modes
-4.14 RE-Builder
+4.15 RE-Builder
===============
Casual RE-Builder is a user interface for RE-Builder. Its top level
@@ -1263,7 +1313,7 @@ References
File: casual.info, Node: Timezone, Prev: RE-Builder, Up: Casual Modes
-4.15 Timezone
+4.16 Timezone
=============
Casual Timezone is a library of commands to work with different time
@@ -1523,6 +1573,9 @@ File: casual.info, Node: Index, Next: Variable Index,
Prev: Acknowledgments,
* EditKit: EditKit. (line 6)
* EditKit Configuration: EditKit. (line 15)
* EditKit Usage: EditKit. (line 25)
+* Eshell: Eshell. (line 6)
+* Eshell Configuration: Eshell. (line 12)
+* Eshell Usage: Eshell. (line 20)
* Feedback: Feedback & Discussion.
(line 6)
* Help: Help. (line 6)
@@ -1578,33 +1631,34 @@ File: casual.info, Node: Variable Index, Prev: Index,
Up: Top
Tag Table:
Node: Top228
-Node: Motivations1953
-Node: Requirements3446
-Node: Transient Conventions3710
-Node: Casual Modes5438
-Node: Agenda6460
-Node: Bookmarks8017
-Node: Calc10292
-Node: Calendar13433
-Node: Dired14781
-Node: EditKit18006
-Node: Help19727
-Node: IBuffer22436
-Node: Image24498
-Node: Info25739
-Node: I-Search27207
-Node: Make28368
-Node: Man30745
-Node: RE-Builder34132
-Node: Timezone37555
-Node: UX Conventions40947
-Node: Customization43648
-Node: Feedback & Discussion44022
-Node: Sponsorship44440
-Node: About44734
-Node: Acknowledgments45011
-Node: Index45393
-Node: Variable Index50171
+Node: Motivations1964
+Node: Requirements3457
+Node: Transient Conventions3721
+Node: Casual Modes5449
+Node: Agenda6482
+Node: Bookmarks8039
+Node: Calc10314
+Node: Calendar13455
+Node: Dired14803
+Node: EditKit18028
+Node: Eshell19751
+Node: Help20966
+Node: IBuffer23674
+Node: Image25736
+Node: Info26979
+Node: I-Search28447
+Node: Make29608
+Node: Man31985
+Node: RE-Builder35372
+Node: Timezone38795
+Node: UX Conventions42187
+Node: Customization44888
+Node: Feedback & Discussion45262
+Node: Sponsorship45680
+Node: About45974
+Node: Acknowledgments46251
+Node: Index46633
+Node: Variable Index51630
End Tag Table
diff --git a/docs/casual.org b/docs/casual.org
index 70064e93bb..87d1c745e3 100644
--- a/docs/casual.org
+++ b/docs/casual.org
@@ -6,7 +6,7 @@
#+OPTIONS: ':t toc:t author:t email:t compact-itemx:t
#+LANGUAGE: en
-#+MACRO: version 2.6.0
+#+MACRO: version 2.7.0
#+TEXINFO_FILENAME: casual.info
#+TEXINFO_HEADER: @syncodeindex pg cp
@@ -488,6 +488,40 @@ Casual EditKit has support for Register commands by
providing a sub-menu for it
#+TEXINFO: @unnumberedsec References
- [[info:emacs#Registers][Registers]]
+** Eshell
+#+CINDEX: Eshell
+
+Casual Eshell is a user interface for ~Eshell~, a shell-like command
interpreter implemented in Emacs Lisp.
+
+#+TEXINFO: @unnumberedsec Configuration
+#+CINDEX: Eshell Configuration
+
+In your initialization file, bind the Transient ~casual-eshell-tmenu~ to your
key binding of preference.
+
+#+begin_src elisp :lexical no
+ (require 'casual-eshell) ; optional
+ (keymap-set eshell-mode-map "C-o" #'casual-eshell-tmenu)
+#+end_src
+
+#+TEXINFO: @unnumberedsec Usage
+#+CINDEX: Eshell Usage
+
+#+TEXINFO: @unnumberedsubsec Basic Usage
+
+Eshell can be invoked via ~M-x eshell~. In any Eshell window, pressing ~C-o~
(or your binding of preference) will raise the menu ~casual-eshell-tmenu~.
+
+The following sections are offered in the menu:
+
+- Input :: Commands supporting input to the current prompt.
+- Argument :: Commands supporting arguments in the current prompt.
+- Prompt :: Navigation of previous prompt commands.
+- Output :: Commands related to display of prompt. Commands marked with an ~n~
superscript support an optional prefix (~C-u~) value.
+- Misc :: Miscellaneous commands.
+
+If a process is running, a section for managing signals to send to it is
provided.
+
+- Process :: Signal commands to send to the process.
+
** Help
#+CINDEX: Help
diff --git a/docs/eshell.org b/docs/eshell.org
new file mode 100644
index 0000000000..dcefef9055
--- /dev/null
+++ b/docs/eshell.org
@@ -0,0 +1,49 @@
+[[../README.org][❮ Back to Casual]]
+
+* Casual Eshell
+
+Casual Eshell is a user interface for ~Eshell~, a shell-like command
interpreter implemented in Emacs Lisp.
+
+[[file:images/casual-eshell-screenshot.png]]
+
+* Install
+
+In your initialization file, bind the Transient ~casual-eshell-tmenu~ to your
key binding of preference.
+
+#+begin_src elisp :lexical no
+ (require 'casual-eshell) ; optional
+ (keymap-set eshell-mode-map "C-o" #'casual-eshell-tmenu)
+#+end_src
+
+
+* Usage
+
+** Basic Usage
+
+Eshell can be invoked via ~M-x eshell~. In any Eshell window, pressing ~C-o~
(or your binding of preference) will raise the menu ~casual-eshell-tmenu~.
+
+The following sections are offered in the menu:
+
+- Input :: Commands supporting input to the current prompt.
+- Argument :: Commands supporting arguments in the current prompt.
+- Prompt :: Navigation of previous prompt commands.
+- Output :: Commands related to display of prompt. Commands marked with an ~n~
superscript support an optional prefix (~C-u~) value.
+- Misc :: Miscellaneous commands.
+
+If a process is running, a section for managing signals to send to it is
provided.
+
+- Process :: Signal commands to send to the process.
+
+ [[file:images/casual-eshell-process-screenshot.png]]
+
+
+*** Unicode Symbol Support
+By enabling “Use Unicode Symbols” from the Settings menu, Casual Eshell will
use Unicode symbols as appropriate in its menus.
+
+* Sponsorship
+If you enjoy using Casual Eshell, consider making a modest financial
contribution to help support its development and maintenance.
+
+[[https://www.buymeacoffee.com/kickingvegas][file:images/default-yellow.png]]
+
+* See Also
+[[file:agenda.org][Agenda]], [[file:bookmarks.org][Bookmarks]],
[[file:calc.org][Calc]], [[file:calendar.org][Calendar]],
[[file:dired.org][Dired]], [[file:editkit.org][EditKit (numerous editing
commands)]], [[file:eshell.org][Eshell]], [[file:help.org][Help]],
[[file:ibuffer.org][IBuffer]], [[file:image.org][Image]],
[[file:info.org][Info]], [[file:isearch.org][I-Search]],
[[file:make-mode.org][Make]], [[file:man.org][Man]],
[[file:re-builder.org][RE-Builder]], [[file:timezone.org][Timezone]]
diff --git a/docs/images/casual-eshell-process-screenshot.png
b/docs/images/casual-eshell-process-screenshot.png
new file mode 100644
index 0000000000..40dcbb0751
Binary files /dev/null and b/docs/images/casual-eshell-process-screenshot.png
differ
diff --git a/docs/images/casual-eshell-screenshot.png
b/docs/images/casual-eshell-screenshot.png
new file mode 100644
index 0000000000..9899f2e4d3
Binary files /dev/null and b/docs/images/casual-eshell-screenshot.png differ
diff --git a/lisp/Makefile b/lisp/Makefile
index 67aee24056..5bd00d6df4 100644
--- a/lisp/Makefile
+++ b/lisp/Makefile
@@ -25,6 +25,7 @@ calc-tests \
calendar-tests \
dired-tests \
editkit-tests \
+eshell-tests \
help-tests \
ibuffer-tests \
info-tests \
@@ -62,6 +63,10 @@ dired-tests:
editkit-tests:
$(MAKE) -C $(SRC_DIR) -f Makefile-editkit.make tests
+.PHONY: eshell-tests
+eshell-tests:
+ $(MAKE) -C $(SRC_DIR) -f Makefile-eshell.make tests
+
.PHONY: help-tests
help-tests:
$(MAKE) -C $(SRC_DIR) -f Makefile-help.make tests
diff --git a/lisp/Makefile-eshell.make b/lisp/Makefile-eshell.make
new file mode 100644
index 0000000000..349f653096
--- /dev/null
+++ b/lisp/Makefile-eshell.make
@@ -0,0 +1,35 @@
+##
+# 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-eshell
+ELISP_INCLUDES=casual-eshell-utils.el \
+casual-eshell-settings.el
+ELISP_PACKAGES=
+ELISP_TEST_INCLUDES=casual-eshell-test-utils.el
+PACKAGE_PATHS= \
+-L $(EMACS_ELPA_DIR)/compat-current \
+-L $(EMACS_ELPA_DIR)/seq-current \
+-L $(EMACS_ELPA_DIR)/transient-current \
+-L $(EMACS_ELPA_DIR)/magit-current \
+-L $(EMACS_ELPA_DIR)/magit-section-current \
+-L $(EMACS_ELPA_DIR)/dash-current \
+-L $(EMACS_ELPA_DIR)/with-editor-current \
+-L $(EMACS_ELPA_DIR)/llama-current \
+-L $(CASUAL_LIB_LISP_DIR)
+
+include Makefile--rules.make
diff --git a/lisp/casual-eshell-settings.el b/lisp/casual-eshell-settings.el
new file mode 100644
index 0000000000..7654e88fd8
--- /dev/null
+++ b/lisp/casual-eshell-settings.el
@@ -0,0 +1,74 @@
+;;; casual-eshell-settings.el --- Casual Eshell 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 'casual-lib)
+
+(transient-define-prefix casual-eshell-settings-tmenu ()
+ "Casual Eshell settings menu."
+ ["Casual Eshell: Settings"
+ [("G" "Eshell Group" casual-eshell--customize-group)
+ (casual-lib-customize-unicode)
+ (casual-lib-customize-hide-navigation)]]
+
+ [:class transient-row
+ (casual-lib-quit-one)
+ ("a" "About" casual-eshell-about :transient nil)
+ (casual-lib-quit-all)])
+
+(defun casual-eshell--customize-group ()
+ "Customize Eshell group."
+ (interactive)
+ (customize-group "eshell"))
+
+
+(defun casual-eshell-about-eshell ()
+ "Casual Eshell is a Transient menu for Eshell.
+
+Learn more about using Casual Eshell 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 Eshell, consider making a modest financial
+contribution to help support its development and maintenance.
+URL `https://www.buymeacoffee.com/kickingvegas'
+
+Casual Eshell was conceived and crafted by Charles Choi in San Francisco,
+California.
+
+Thank you for using Casual Eshell.
+
+Always choose love."
+ (ignore))
+
+(defun casual-eshell-about ()
+ "About information for Casual Eshell."
+ (interactive)
+ (describe-function #'casual-eshell-about-eshell))
+
+(provide 'casual-eshell-settings)
+;;; casual-eshell-settings.el ends here
diff --git a/lisp/casual-eshell-utils.el b/lisp/casual-eshell-utils.el
new file mode 100644
index 0000000000..2ec9503ab7
--- /dev/null
+++ b/lisp/casual-eshell-utils.el
@@ -0,0 +1,106 @@
+;;; casual-eshell-utils.el --- Casual Eshell 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 'eshell)
+(require 'tramp)
+(require 'casual-lib)
+
+(defconst casual-eshell-unicode-db
+ '((:previous . '("↑" "Previous"))
+ (:next . '("↓" "Next"))
+ (:forward . '("→" "Forward"))
+ (:backward . '("←" "Backward"))
+ (:repeat . '("⥅" "Repeat"))
+ (:clear . '("⌫" "Clear")))
+
+ "Unicode symbol DB to use for Eshell Transient menus.")
+
+(defun casual-eshell-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-eshell-unicode-db))
+
+(defun casual-eshell-info ()
+ "Open Info for Eshell."
+ (interactive) (info "(eshell) Top"))
+
+(defun casual-eshell-info-builtins ()
+ "Open Info for Eshell built-in commands."
+ (interactive) (info "(eshell) List of Built-ins"))
+
+(defun casual-eshell-info-aliases ()
+ "Open Info for Eshell aliases."
+ (interactive) (info "(eshell) Aliases"))
+
+(defun casual-eshell-info-remote-access ()
+ "Open Info for Eshell remote access."
+ (interactive) (info "(eshell) Remote Access"))
+
+(defun casual-eshell-info-control-flow ()
+ "Open Info for Eshell control flow."
+ (interactive) (info "(eshell) Control Flow"))
+
+(defun casual-eshell-info-expansion ()
+ "Open Info for Eshell expansion."
+ (interactive) (info "(eshell) Expansion"))
+
+(defun casual-eshell-info-dollars-expansion ()
+ "Open Info for Eshell $ expansion."
+ (interactive) (info "(eshell) Dollars Expansion"))
+
+(defun casual-eshell-info-redirection ()
+ "Open Info for Eshell redirection."
+ (interactive) (info "(eshell) Redirection"))
+
+(defun casual-eshell-info-pipelines ()
+ "Open Info for Eshell pipelines."
+ (interactive) (info "(eshell) Pipelines"))
+
+(defun casual-eshell-edit-aliases ()
+ "Edit file in `eshell-aliases-file'."
+ (interactive)
+ (find-file eshell-aliases-file))
+
+(defun casual-eshell-tilde-path (path)
+ "Parse PATH for display."
+ (let ((test-ssh-path (string-search "/ssh:" path)))
+ (if (and test-ssh-path (= test-ssh-path 0))
+ (let* ((path-obj (tramp-dissect-file-name path))
+ (host (tramp-file-name-host path-obj))
+ (localname (tramp-file-name-localname path-obj)))
+ (format "(%s) %s" host localname))
+
+ (if (string= path (getenv "HOME"))
+ "~"
+ (replace-regexp-in-string
+ (concat "^" (getenv "HOME")) "~" path)))))
+
+(provide 'casual-eshell-utils)
+;;; casual-eshell-utils.el ends here
diff --git a/lisp/casual-eshell.el b/lisp/casual-eshell.el
new file mode 100644
index 0000000000..16702008af
--- /dev/null
+++ b/lisp/casual-eshell.el
@@ -0,0 +1,151 @@
+;;; casual-eshell.el --- Transient UI for Eshell -*- 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:
+
+;; This library provides a Transient-based user interface for `eshell-mode'.
+
+;; INSTALLATION
+
+;; In your initialization file, bind the Transient `casual-eshell-tmenu' to
your
+;; key binding of preference.
+
+;; (require 'casual-eshell) ; optional if using autoloaded menu
+;; (keymap-set eshell-mode-map "C-o" #'casual-eshell-tmenu)
+
+;;; Code:
+
+(require 'casual-eshell-settings)
+(require 'casual-eshell-utils)
+(require 'casual-editkit)
+(require 'magit-status)
+(require 'esh-mode)
+(require 'esh-arg)
+(require 'em-hist)
+(require 'em-prompt)
+
+;;;###autoload (autoload 'casual-eshell-tmenu "casual-eshell" nil t)
+(transient-define-prefix casual-eshell-tmenu ()
+ "Transient menu for Eshell."
+ :refresh-suffixes t
+ ["Casual Eshell"
+ :description (lambda ()
+ (format
+ "Casual Eshell: %s"
+ (casual-eshell-tilde-path default-directory)))
+ ["Input"
+ :pad-keys t
+ :if-not buffer-narrowed-p
+ ("B" "#<buffer >…" eshell-insert-buffer-name)
+ ("k" "Clear" eshell-kill-input
+ :description (lambda () (casual-eshell-unicode-get :clear)))
+ ;; ("C-p" "Previous" eshell-previous-matching-input-from-input
+ ;; :description (lambda () (casual-eshell-unicode-get :previous))
+ ;; :transient t)
+
+ ;; ("C-n" "Next" eshell-next-matching-input-from-input
+ ;; :description (lambda () (casual-eshell-unicode-get :next)
+ ;; :transient t)
+ ("h" "History" eshell-list-history)]
+
+ ["Argument"
+ :if-not buffer-narrowed-p
+ ("b" "Backward" eshell-backward-argument
+ :description (lambda () (casual-eshell-unicode-get :backward))
+ :transient t)
+ ("f" "Forward" eshell-forward-argument
+ :description (lambda () (casual-eshell-unicode-get :forward))
+ :transient t)
+ ("y" "Repeat" eshell-repeat-argument
+ :description (lambda () (casual-eshell-unicode-get :repeat))
+ :transient t)]
+
+ ["Prompt"
+ :if-not buffer-narrowed-p
+ ("p" "Previous" eshell-previous-prompt
+ :description (lambda () (casual-eshell-unicode-get :previous))
+ :transient t)
+ ("n" "Next" eshell-next-prompt
+ :description (lambda () (casual-eshell-unicode-get :next))
+ :transient t)
+ ("RET" "Clone" eshell-copy-old-input)]
+
+ ["Output"
+ :if-not buffer-narrowed-p
+ ("s" "Show" eshell-show-output)
+ ("." "Show Max" eshell-show-maximum-output)
+ ("m" "Mark" eshell-mark-output
+ :description (lambda () (if prefix-arg "Narrow" "Markⁿ")))
+ ("D" "Delete" eshell-delete-output
+ :description (lambda () (if prefix-arg "Kill" "Deleteⁿ")))]
+
+ ["Output"
+ :if buffer-narrowed-p
+ ("w" "Widen" (lambda ()
+ (interactive)
+ (widen)
+ (eshell-show-maximum-output)))]
+
+ ["Misc"
+ ("d" "Dired" dired-jump-other-window)
+ ("a" "Edit Aliases" casual-eshell-edit-aliases)
+ ("J" "Jump to Bookmark…" bookmark-jump)
+ ("g" "Magit" magit-status :if casual-editkit-version-controlled-p)]]
+
+ ["Process"
+ :if (lambda () (car eshell-process-list))
+ :class transient-row
+ ("Pi" "Interrupt" eshell-interrupt-process)
+ ("Pk" "Kill" eshell-kill-process)
+ ("Pq" "Quit" eshell-quit-process)]
+
+ [:class transient-row
+ (casual-lib-quit-one)
+ ("i" "ⓘ›" casual-eshell-info-tmenu)
+ ("," "Settings›" casual-eshell-settings-tmenu)
+ (casual-lib-quit-all)])
+
+(transient-define-prefix casual-eshell-info-tmenu ()
+ "Menu for Eshell Info."
+
+ ["Casual Eshell ⓘ"
+ ["Info"
+ ("i" "Info" casual-eshell-info)]
+
+ ["Commands"
+ ("b" "Built-in Commands" casual-eshell-info-builtins)
+ ("a" "Aliases" casual-eshell-info-aliases)
+ ("r" "Remote Access" casual-eshell-info-remote-access)
+ ("c" "Control Flow" casual-eshell-info-control-flow)]
+
+ ["Expansion"
+ ("e" "Expansion" casual-eshell-info-expansion)
+ ("d" "$" casual-eshell-info-dollars-expansion)]
+
+ ["I/O"
+ ("R" "Redirection" casual-eshell-info-redirection)
+ ("p" "Pipelines" casual-eshell-info-pipelines)]]
+
+ [:class transient-row
+ (casual-lib-quit-one)
+ (casual-lib-quit-all)])
+
+(provide 'casual-eshell)
+;;; casual-eshell.el ends here
diff --git a/lisp/casual.el b/lisp/casual.el
index cc6711c47b..31e696b0a2 100644
--- a/lisp/casual.el
+++ b/lisp/casual.el
@@ -5,7 +5,7 @@
;; Author: Charles Choi <[email protected]>
;; URL: https://github.com/kickingvegas/casual
;; Keywords: tools, wp
-;; Version: 2.6.0
+;; Version: 2.6.1-rc.2
;; Package-Requires: ((emacs "29.1") (transient "0.9.0"))
;; This program is free software; you can redistribute it and/or modify
diff --git a/tests/Makefile b/tests/Makefile
index 94e3b66a4e..ce30421d6e 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -24,6 +24,7 @@ calc-tests \
calendar-tests \
dired-tests \
editkit-tests \
+eshell-tests \
help-tests \
ibuffer-tests \
info-tests \
@@ -42,6 +43,7 @@ calc-tests \
calendar-tests \
dired-tests \
editkit-tests \
+eshell-tests \
help-tests \
ibuffer-tests \
info-tests \
@@ -72,6 +74,9 @@ dired-tests:
editkit-tests:
$(MAKE) -C $(SRC_DIR) $@
+eshell-tests:
+ $(MAKE) -C $(SRC_DIR) $@
+
help-tests:
$(MAKE) -C $(SRC_DIR) $@
diff --git a/tests/casual-man-test-utils.el b/tests/casual-eshell-test-utils.el
similarity index 71%
copy from tests/casual-man-test-utils.el
copy to tests/casual-eshell-test-utils.el
index 5f5ce5192a..7bc96fc7a6 100644
--- a/tests/casual-man-test-utils.el
+++ b/tests/casual-eshell-test-utils.el
@@ -1,6 +1,6 @@
-;;; casual-man-test-utils.el --- Casual Test Utils -*- lexical-binding:
t; -*-
+;;; casual-eshell-test-utils.el --- Casual Test Utils -*-
lexical-binding: t; -*-
-;; Copyright (C) 2024-2025 Charles Y. Choi
+;; Copyright (C) 2025 Charles Y. Choi
;; Author: Charles Choi <[email protected]>
;; Keywords: tools
@@ -27,14 +27,13 @@
(require 'casual-lib)
(require 'kmacro)
-(defun casualt-man-setup ()
- "Casual man setup."
- (setopt Man-prefer-synchronous-call t)
- (man "tar"))
+(defun casualt-eshell-setup ()
+ "Casual Eshell setup."
+ )
-(defun casualt-man-breakdown ()
+(defun casualt-eshell-breakdown ()
"Casual man breakdown."
)
-(provide 'casual-man-test-utils)
-;;; casual-man-test-utils.el ends here
+(provide 'casual-eshell-test-utils)
+;;; casual-eshell-test-utils.el ends here
diff --git a/tests/casual-help-test-utils.el b/tests/casual-help-test-utils.el
index 40e5d36d8e..6d2a482598 100644
--- a/tests/casual-help-test-utils.el
+++ b/tests/casual-help-test-utils.el
@@ -1,6 +1,6 @@
;;; casual-help-test-utils.el --- Casual Test Utils -*- lexical-binding:
t; -*-
-;; Copyright (C) 2024-2025 Charles Y. Choi
+;; Copyright (C) 2025 Charles Y. Choi
;; Author: Charles Choi <[email protected]>
;; Keywords: tools
diff --git a/tests/casual-man-test-utils.el b/tests/casual-man-test-utils.el
index 5f5ce5192a..2ec1ad75cb 100644
--- a/tests/casual-man-test-utils.el
+++ b/tests/casual-man-test-utils.el
@@ -1,6 +1,6 @@
;;; casual-man-test-utils.el --- Casual Test Utils -*- lexical-binding:
t; -*-
-;; Copyright (C) 2024-2025 Charles Y. Choi
+;; Copyright (C) 2025 Charles Y. Choi
;; Author: Charles Choi <[email protected]>
;; Keywords: tools
diff --git a/tests/test-casual-eshell-settings.el
b/tests/test-casual-eshell-settings.el
new file mode 100644
index 0000000000..267873ee41
--- /dev/null
+++ b/tests/test-casual-eshell-settings.el
@@ -0,0 +1,50 @@
+;;; test-casual-eshell-settings.el --- Casual Make 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-eshell-test-utils)
+(require 'casual-eshell-settings)
+
+(ert-deftest test-casual-eshell-settings-tmenu ()
+ (let ()
+ (cl-letf ((casualt-mock #'casual-eshell--customize-group)
+ (casualt-mock #'casual-eshell-about))
+
+ (let ((test-vectors
+ '((:binding "G" :command casual-eshell--customize-group)
+ (:binding "u" :command
casual-lib-customize-casual-lib-use-unicode)
+ (:binding "n" :command
casual-lib-customize-casual-lib-hide-navigation)
+ (:binding "a" :command casual-eshell-about))))
+
+ (casualt-suffix-testcase-runner test-vectors
+ #'casual-eshell-settings-tmenu
+ '(lambda () (random 5000)))))))
+
+(ert-deftest test-casual-eshell-about ()
+ (should (stringp (casual-eshell-about))))
+
+(provide 'test-casual-eshell-settings)
+;;; test-casual-eshell-setttings.el ends here
diff --git a/tests/test-casual-eshell-utils.el
b/tests/test-casual-eshell-utils.el
new file mode 100644
index 0000000000..f54d492bdb
--- /dev/null
+++ b/tests/test-casual-eshell-utils.el
@@ -0,0 +1,54 @@
+;;; test-casual-eshell-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-eshell-test-utils)
+(require 'casual-eshell-utils)
+
+(ert-deftest test-casual-eshell-unicode-get ()
+ (let ((casual-lib-use-unicode nil))
+ (should (string-equal (casual-eshell-unicode-get :previous) "Previous"))
+ (should (string-equal (casual-eshell-unicode-get :next) "Next"))
+ (should (string-equal (casual-eshell-unicode-get :forward) "Forward"))
+ (should (string-equal (casual-eshell-unicode-get :backward) "Backward"))
+ (should (string-equal (casual-eshell-unicode-get :repeat) "Repeat"))
+ (should (string-equal (casual-eshell-unicode-get :clear) "Clear"))
+ )
+
+ (let ((casual-lib-use-unicode t))
+ (should (string-equal (casual-eshell-unicode-get :previous) "↑"))
+ (should (string-equal (casual-eshell-unicode-get :next) "↓"))
+ (should (string-equal (casual-eshell-unicode-get :forward) "→"))
+ (should (string-equal (casual-eshell-unicode-get :backward) "←"))
+ (should (string-equal (casual-eshell-unicode-get :repeat) "⥅"))
+ (should (string-equal (casual-eshell-unicode-get :clear) "⌫"))
+ ))
+
+
+
+
+
+(provide 'test-casual-eshell-utils)
+;;; test-casual-eshell-utils.el ends here
diff --git a/tests/test-casual-eshell.el b/tests/test-casual-eshell.el
new file mode 100644
index 0000000000..2b1cf146d9
--- /dev/null
+++ b/tests/test-casual-eshell.el
@@ -0,0 +1,116 @@
+;;; test-casual-eshell.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-eshell)
+(require 'casual-lib-test-utils)
+(require 'casual-eshell-test-utils)
+
+(ert-deftest test-casual-eshell-tmenu ()
+ (let ()
+ (casualt-eshell-setup)
+
+ (cl-letf ((casualt-mock #'eshell-insert-buffer-name)
+ (casualt-mock #'eshell-kill-input)
+ (casualt-mock #'eshell-list-history)
+ (casualt-mock #'eshell-backward-argument)
+ (casualt-mock #'eshell-forward-argument)
+ (casualt-mock #'eshell-repeat-argument)
+ (casualt-mock #'eshell-previous-prompt)
+ (casualt-mock #'eshell-next-prompt)
+ (casualt-mock #'eshell-copy-old-input)
+ (casualt-mock #'eshell-show-output)
+ (casualt-mock #'eshell-show-maximum-output)
+ (casualt-mock #'eshell-mark-output)
+ (casualt-mock #'eshell-delete-output)
+ ;;(casualt-mock #'dired)
+ (casualt-mock #'casual-eshell-edit-aliases)
+
+ (casualt-mock #'casual-eshell-info-tmenu)
+ (casualt-mock #'casual-eshell-settings-tmenu)
+ ;;(casualt-mock #'bookmark-jump)
+ ;;(casualt-mock #'magit-status)
+ )
+
+ (let ((test-vectors
+ '((:binding "B" :command eshell-insert-buffer-name)
+ (:binding "k" :command eshell-kill-input)
+ (:binding "h" :command eshell-list-history)
+ (:binding "b" :command eshell-backward-argument)
+ (:binding "f" :command eshell-forward-argument)
+ (:binding "y" :command eshell-repeat-argument)
+ (:binding "p" :command eshell-previous-prompt)
+ (:binding "n" :command eshell-next-prompt)
+ (:binding "RET" :command eshell-copy-old-input)
+ (:binding "s" :command eshell-show-output)
+ (:binding "." :command eshell-show-maximum-output)
+ (:binding "m" :command eshell-mark-output)
+ (:binding "D" :command eshell-delete-output)
+ ;; (:binding "d" :command dired)
+ (:binding "a" :command casual-eshell-edit-aliases)
+ (:binding "i" :command casual-eshell-info-tmenu)
+ (:binding "," :command casual-eshell-settings-tmenu))
+ ))
+
+ (casualt-suffix-testcase-runner test-vectors
+ #'casual-eshell-tmenu
+ '(lambda () (random 5000)))))
+ (casualt-eshell-breakdown)))
+
+
+(ert-deftest test-casual-eshell-info-tmenu ()
+ (let ()
+ (casualt-eshell-setup)
+ (cl-letf ((casualt-mock #'casual-eshell-info)
+ (casualt-mock #'casual-eshell-info-builtins)
+ (casualt-mock #'casual-eshell-info-aliases)
+ (casualt-mock #'casual-eshell-info-remote-access)
+ (casualt-mock #'casual-eshell-info-control-flow)
+ (casualt-mock #'casual-eshell-info-expansion)
+ (casualt-mock #'casual-eshell-info-dollars-expansion)
+ (casualt-mock #'casual-eshell-info-redirection)
+ (casualt-mock #'casual-eshell-info-pipelines))
+
+ (let ((test-vectors
+ '(
+ (:binding "i" :command casual-eshell-info)
+ (:binding "b" :command casual-eshell-info-builtins)
+ (:binding "a" :command casual-eshell-info-aliases)
+ (:binding "r" :command casual-eshell-info-remote-access)
+ (:binding "c" :command casual-eshell-info-control-flow)
+ (:binding "e" :command casual-eshell-info-expansion)
+ (:binding "d" :command casual-eshell-info-dollars-expansion)
+ (:binding "R" :command casual-eshell-info-redirection)
+ (:binding "p" :command casual-eshell-info-pipelines)
+ )))
+
+ (casualt-suffix-testcase-runner test-vectors
+ #'casual-eshell-info-tmenu
+ '(lambda () (random 5000)))))
+ (casualt-eshell-breakdown)))
+
+(provide 'test-casual-eshell)
+;;; test-casual-eshell.el ends here