6

BASH, ZSH, FISH. How about Eshell?

 1 year ago
source link: https://famme.sk/blog/how-about-eshell.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Prologue

Nowadays, a GNU/Linux user can work without a terminal emulator. The vast majority of the settings, if a suitable distribution is chosen, can be done via the GUI.
But anyone who has become familiar with the command line will be obessed of its efficiency, straightforwardness, and speed.

From BASH to eshell

Like probably most, I started with a shell (i.e., a program that is a working interface in a command-line environment) called bash. And I used it for many years. Then, influenced by YT videos, I tried zsh and fish. These had some excellent features that were addictive, especially the addition of switches to familiar commands.
Later I started using GNU Emacs extensively. That is, I used it to replace my file manager, word processor, RSS reader, and programming language documentation viewer. But not only that. It has replaced my audio and radio players, of course the programming IDE, etc.
And it also replaced my bash/zsh/fish shell.

A couple of motivating features

Eshell is written in eLisp. It tries to mimic the behavior of bash and commands from GNU Coreutils. It is available in Emacs on all supported OSes, and (according to others, I've never tried it) is better than Cygwin Bash.

But that's probably too little to be anything special, or...?

It should be remembered that:

Eshell is not (paradoxically) a terminal emulator. Everything it does - from displaying things on the screen, to loading the contents of a directory - it does via Emacs, and Emacs communicates with the OS directly. So it's not "something" on top of another shell. It's not bash or zsh or fish, although it is inspired by them (or is it the other way around?). In short - it needs to be seen as something different and distinct. It doesn't hold a candle to full-screen TUIs like Mutt or htop. Those have to be run in a separate ansi-term, but that's what we'll talk about. Eshell allows direct execution of functions or programs written in eLisp. It also works internally with parameters as lists. And as we know eLisp is very powerful when working with lists. And its strength is also TRAMP, which is a remote access tool (ftp, ssh,...) and its integration. Another strong point is its existence in a text buffer, to which similar rules and editing methods are applied as to any text buffer. And this is what attracted me the most. Oh, and it's running in Emacs, and Emacs is a master at working with multiple buffers, windows. So we don't need screen or tmux or tabs of emulator teminal.

In the next chapters we'll talk more about its nice features, tweak it a bit and make it a drop-down (a.k.a. Quake) terminal.

Basic features and other pleasantries

Multipass (multishell)

So as mentioned, even without additional programs it is possible to have multiple shells side by side. If we use the man command, it will open in the next window, while the focus stays on the original one. Then we can (e.g. using M-PgDn, M-PgUp) flip through the help and type in the command line at the same time. Or - jump to the second window (the designation in Emacs is a bit confusing - window is a de-facto split of the current Emacs window into several, and frame is a separate window [more of the history here]) and from there (even without a mouse) copy the text to the clipboard (in Emacs it's called a kill-ring). Whether it's a window or a frame, all these entities are interconnected.

Pic. 1: 3 shells in one Emacs frame
Fig. 1: 3 shells in one Emacs frame

Eshell is buffer

And now the amazing thing - since eshell is de-facto a regular text buffer, it is possible to run the cursor in all directions. And mark text, copy or delete it, or even re-run commands.

Fig. 2: Cursor manipulation - moving around the buffer and copying text
Fig. 2: Cursor manipulation - moving around the buffer and copying text

So no pagers like more or less are needed. And this is very addictive in my opinion. Plus the ability to search, highlight using regular expressions, just anything one could wish for and as far as one's imagination goes.

Redirect to another buffer

To redirect there are the following (I don't know what it's called):

 > overwrite
 >> adding
 >>> adding to a cursor position in another buffer

So the target can be a file, or a buffer:
 echo "hello world" > #<buffer hello>>
Good, isn't it? Some long listing to look at e.g. in a temporary <*scratch*> buffer.

Eshell has additionally these pseudo-devices:
 echo hello > /dev/clip → puts in the X11 clipboard
 echo hello > /dev/kill → puts into the internal Emacs clipboard (kill-ring)

(kill-ring and normal clipboard can both manage the same content).

ELisp rocks!

Calling ELisp functions allows you to do any action, which Emacs can do, from the command line. So, for example:

 find-file-other-window <file>

Opens the file in a new window.

But not only that. This is how you can call any commands, even those called with M-x, modify Emacs variables, define functions - all from the aforementioned shell.

Cooperation with Dired

As I once wrote in a post, Dired is a built-in tool for batch visual file manipulation. So if we need to do a bulk rename in a hurry, some handy macro, a more complicated copy, the

dired .
command is immediately at hand.

Other built-in features

… which I have got used to and use on a regular basis (I am only mentioning the name of the function, as the keyboard shortcut assignment is, like everything in Emacs, configurable).

| eshell-next(previous)-prompt    | move in the buffer to the next (previous) entry in the command line                                        |
|                                 | (defacto no need to move the cursor to the running command through all statements of the executed command) |
|                                 |                                                                                                            |
| pcomplete-expand                | autocomplete a command or parameter                                                                        |
|                                 | (but we'll show a more massive extension of this functionality)                                            |
|                                 |                                                                                                            |
| eshell-show-output              | jumps to the beginning of the output of the last command,                                                  |
|                                 | which saves us scrolling through a multi-page output                                                       |
|                                 |                                                                                                            |
| eshell-next(previous)-matching- | adds the next (previous) matching input                                                                    |
| input-from-input                | (e.g., after entering cd and calling the function, it is possible to scroll through the past cd entries)   |
|                                 |                                                                                                            |
| eshell-next(previous)-input     | classic history scrolling as we know it from bash (arrows ↑ ↓)                                             |

Visual (ncurses) programs

As mentioned, eshell doesn't do well with full-screen TUI programs such as Alpine, Mutt or htop (it does with the top command, however, because it runs an imitation of it written in eLisp). But there is an option for this case to drop a term (or ansi-term) instance that can handle these things.
By setting the appropriate list:

(setq eshell-visual-commands
   (quote
    ("alpine -i" "screen" "top" "less" "more" "ncdu" "alpine" "htop" "most")))
Fig. 3: TUI mail client
Fig. 3: TUI mail client "Alpine" running in ansi-term
Here we are not impoverished in cursor movement in all directions either - anti-term or term can work in two modes (term-char-mode and term-line-mode), which can of course also be switched between with a shortcut (C-c C-k and C-c C-j, respectively).

Other extensions

Autojump

…is an extension to facilitate switching between directories. Typing j with no arguments displays a list of favorite directories; j <regexp> can be used to move to a directory. The list of directories is formed by the frequency with which they are used. To do this, the package eshell-autojump is required.

Helm-eshell-history

In addition, there is also a history of cd commands, after typing cd = it is possible to select (using a number) from the list. This is not bad, but if we already have the helm extension framework installed, we can use the helm-eshell-history command, which allows us to (fuzzy) search the history and of course insert past commands at the cursor position in eshell.

Fig. 4: Improved command history handling
Fig. 4: Improved command history
A related feature is helm-eshell-prompts, which allows us to move the cursor to a past command - it defacto scrolls through the buffer for past commands, similar to eshell-next(previous)-prompt, but visually.

Autocompletion

Did we say Emacs is the master of working with text? Well probably a few times and it's still true. And autocomplete is inherent to working with text.

Autocomplete is possible in several ways, which can be combined with each other.

1. Completing file names and commands
Just the classic bash-like way, after pressing TAB. This is basic out-of-box functionality that will impress no one, except perhaps a person who used DOS until yesterday.

2. Adding of extra and command parameters
Thus identical behavior as in zsh or fish shell.
You need to have the fish add-ons installed (easiest by installing fish itself), which are usually found in ~/.local/share/fish and ~/.local/etc/fish.
Furthermore, an Emacs package called helm-fish-completion is required.

And while typing it in, when the eponymous command is run (or a keyboard shortcut is set (e.g. again TAB)), this beauty appears:

Fig. 5: Completion of the infinite parameters of the Tar command
Fig. 5: Completion of the infinite parameters of the Tar command
Fig. 6: Completing the parameters of the Apt command
Fig. 6: Completing the parameters of the Apt command

3. Completing with Abbrev
Abbrev is a basic Emacs functionality that is always pre-installed. It allows you to list between occurrences of a string (by default) in the current buffer by typing a few characters (even one is sufficient) and calling the dabbrev-expand command.

For example, in the screenshot below, I typed rt and then pressed M-/ a few times until the desired addition was selected.

Fig. 7: Filename completion using Abbrev
Fig. 7: Filename completion using `Abbrev'

4. Using auto-complete
…is similar to the previous, but using a pop-up menu. This pops up automatically after 3 characters are entered (unless otherwise specified) and by default it completes from the current buffer, but it can also complete from other buffers or the dictionary. Primarily this is an extension intended for programming, but in Emacs everything can be combined together (and even tinkered with ☺). I'll just add that this extension needs to be installed too.

Fig. 8: Adding a filename using the popup menu
Fig. 8: Adding a filename using the popup menu

App-launcher

Many people, myself included, prefer to launch applications (the old "programs") by typing (part of) their name rather than clicking in the menu structure or on icons. There are many launchers, e.g. dmenu, App Select or gExec. And this nifty thing is also implemented in an extension called app-launcher. When you run it, a list of installed programs appears (it is a listing of .desktop files (both global and local in ~/.local/share/applications/). Typing part of the name dynamically narrows the list.
Fig. 9: Launcher for launching programs
Fig. 9: Launcher for launching programs

Upload to 0x0 and other…

I often use the https://0x0.st/ service to temporarily store a large file that wouldn't go through email. So far, I've been using a script in which the upload was done with curl -F'file= https://0x0.st. However, there is also an extension 0x0.el that simplifies this and directly "throws" the resulting link into the kill-ring. There are similar extensions for temporary emails, URL shorteners, upload and download on YouTube or Invidious.

And now the negatives

A responsible review includes criticism. Even if it is Emacs, which arouses extreme emotions both ways.

Eshell's main shortcomings:

Everything is a buffer and everything goes through (virtual) buffers. This affects the speed. For example, a command in the var/log directory: time cat * | wc -l takes 13 ms in bash, but 500 ms in eshell. For normal shell work these differences are not noticeable, but for some super burdensome manipulation, e.g. with sed, it could be annoying. In eshell it is possible to run the command in the background (as always with & at the end). But once it is running in the foreground, it is not possible (e.g. using the familiar C-z) to move it to the background. I'm paraphrasing the scene from The Hobbit Part 2 where the dwarves (with Gandalf and Bilbo) are being chased by Beorn. At the end, Gandalf responds to unspoken questions with (I don't know exactly, but something like this), "He's not cursed, he's just like that!". Compared to other Emacs tools, the built-in documentation is weaker, although there are good tutorials on the web. While it's great to experience the benefits and environment of the shell even in e.g. Windows, where the use of Emacs is also widespread, if someone who doesn't otherwise use Emacs, wants to try Eshell, he'll struggle with the typically Emacs-like controls - which will make the learning curve even steeper.

Eshell as a pop-up terminal

In the past, I have very often used a terminal emulator called Tilda. Similar to e.g. Guake or Yakuake, which are all terminals that roll out from the top when you press a hotkey, similar to the terminal in game Quake (which I can't confirm, because I never played that game, but e.g. Hexen II did, and it was like that there too).

But how to do it with eshell so that it's always at hand?

The solution is possible with the tdrop program (https://github.com/noctuid/tdrop). It's a great program that adds this popup parade to any program, using programs like xprop (to find out the properties of a window), xdotool (to resize and reposition the window), and xwininfo (to change the window name, among other things).

I downloaded the compiled binary from GitHub and defined the keyboard shortcuts in the window manager file (in my case, the window manager is IceWM, and so it is a ~/.icewm/keys file - but I'm sure there is an analogous solution for every window manager, not to mention desktop environments):

    key "Ctrl+Menu"	       ~/bin/tdrop/tdrop -ma -h 95% -w 98% -y 30 -s  dropdown emacs -f eshell  -title Eshell
  


Where:

| parameter       | action                                                                           |
|-----------------+----------------------------------------------------------------------------------|
| -ma             | automatic manager detection and resolution                                       |
| -h 95%          | setting the height of the popup window (can be set absolutely)                   |
| -w 98%          | detto - but the width                                                            |
| -y 30           | offset (shift) of the window relative to the upper left corner                   |
|                 | (I didn't want the popup to overlap the toolbar)                                 |
| dropdown        | internal command                                                                 |
| emacs -f eshell | specific program with parameters (in our case emacs with function call `eshell'  |
| -title Eshell   | the name of the newly created popup window                                       |
  

Epilogue

I believe I have described all the essential features of eshell, and I believe in a good perspective. If you use Emacs and have not tried eshell yet, don't hesitate and probably after the initial grumblings you will get used to it and stay with it.
It may also be a good tool for those who have to occasionally enter the sad world of MS Windows, and at the same time want to keep the memory of GNU/Linux alive.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK