3

Top 10 reasons why you should be using Eshell

 1 year ago
source link: https://emacsconf.org/2022/talks/eshell/
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.

Top 10 reasons why you should be using Eshell

Howard Abrams (he/him)

In this talk, Howard Abrams shows how eshell combines the best of Emacs Lisp and shells. Afterwards, he will handle questions via BigBlueButton.

The following image shows where the talk is in the schedule for Sun 2022-12-04. Solid lines show talks with Q&A via BigBlueButton. Dashed lines show talks with Q&A via IRC or Etherpad.

Schedule for Sunday Sunday 9:00- 9:05 Sunday opening remarks sun-open 9:06- 9:26 Results of the 2022 Emacs Survey survey 9:35- 9:45 This Year in Org orgyear 9:57-10:22 Build a Zettelkasten with the Hyperbole Rolodex rolodex 10:40-10:50 Linking headings with org-super-links (poor-man's Zettelkasten) orgsuperlinks 11:10-11:20 orgvm: a simple HTTP server for org orgvm 1:00- 1:30 Powerful productivity with Hyperbole and Org Mode hyperorg 1:50- 2:15 Org workflows for developers workflows 2:35- 2:55 GRAIL---A Generalized Representation and Aggregation of Information Layers grail 3:25- 3:45 Putting Org Mode on the Indieweb indieweb 4:05- 4:15 Emacs development updates devel 4:25- 4:35 Fanfare for the Common Emacs User fanfare 4:50- 5:00 Sunday closing remarks sun-close 10:00-10:25 rde Emacs introduction rde 10:50-11:05 justl: Driving recipes within Emacs justl 11:15-11:35 What I'd like to see in Emacs rms 1:01- 1:16 Getting detached from Emacs detached 1:40- 1:55 Top 10 reasons why you should be using Eshell eshell 2:20- 2:40 Emacs was async before async was cool async 3:15- 3:35 The Wheels on D-Bus dbus 4:00- 4:10 Pre-localizing Emacs localizing 4:30- 4:35 Short hyperlinks to Python docs python 9 AM 10 AM 11 AM 12 PM 1 PM 2 PM 3 PM 4 PM 5 PM

Format: 15-min talk followed by live Q&A (https://emacsconf.org/current/eshell/room)
Etherpad: https://pad.emacsconf.org/2022-eshell
Discuss on IRC: #emacsconf-dev
Status: Q&A open for participation

Times in different timezones:
Your local time: ~ 12/4/22, 6:40 PM to ~ 12/4/22, 6:55 PM
Sunday, Dec 4 2022, ~1:40 PM - 1:55 PM EST (US/Eastern)

Description

While Eshell is this quick and dirty way to run external commands, its dirtiness plays into the Lisp’s malleable big ball of mud metaphor, and I have a number of quick hacks that will make you want to play in this puddle.

This will be a lightning talk that I will pre-record to show off some features in eshell I found while diving into the source code … stuff you can’t do in another terminals. Did you know that `$$` is a special variable that contains the output from the last command?

Transcript

[00:00:00.000] I have 10 minutes to talk you into giving Eshell a second chance. Have the right perspective and expectation, and I think you’ll really enjoy it. Just remember eshell is a shell, not a terminal emulator. I use both Eshell and vterm. I’m going to talk and type fast, as I have 10 reasons for you to try Eshell again.

[00:00:29.000]

  1. It’s an Emacs REPL.

I mean, check this out. Let’s start up Eshell here. Let’s just type a Lisp expression. It works. As a shell, the parens are kinda optional.

[00:00:48.600]

  1. It’s also a shell.

While eshell may look like a shell, like Bash you should view it as a REPL with parenthesis-less s-expressions. This makes sense, because a shell command with options, like this ls command, looks like an s-expression.

[00:01:10.120]

  1. You can mix these two modes.

Shells can call subshells which return their output like a function call, like this Bash command. In this Eshell example, I use the output of a text file as command line arguments to ripgrep. Notice how I use braces to state that it is a call to an eshell expression. We can mix Lisp-expressions and Shell-expressions. Allow me a contrived example. Notice I use good ol' setq to create a variable. Yes, those are global Emacs variables available everywhere. In Eshell, the wildcard actually creates a list. This variable assignment doesn’t work as you might expect, as setq in Eshell is still setq, and it assigns variables in pairs. To make a list in Eshell, we use listify: Without parens, Eshell is in “shell mode”, which means that words are strings, and variables need to be prefixed with dollar signs. A command can have both Eshell and Lisp expressions. As you can see here, I have a call to ripgrep, but part of it is an s-expression. Remember the differences: With parens, eshell treats it as Lisp, like the last line in my example. With braces, eshell follows these shell-like rules: First, if it looks like a number, it's a number. Otherwise, eshell converts it to a string (quotes, like a shell, groups words). What about this mix between functions and executables for the first word? Functions that begin with eshell are called first. Next in priority are executables on your $PATH, then matching Lisp functions. You can actually switch this order with the `eshell-prefer-lisp-functions' variable.

[00:03:27.560]

  1. Emacs is actually better than shell.

If the following works, why would you call expr or bc or dc, or any of those other calculators? You can just call a Lisp expression. Why call less or more when you could call view-file? Here, I’ve aliased less to view-file. Load it up, and it shows up in an Emacs mode. Just like with less, if you hit q, you go back to your Eshell terminal. I do have an improvement, though. The problem with view-file is it takes a single file as an argument. In a shell, we might want to view more than one. So let’s make a solution to that. This function will call the first function with the first argument, and the second function with each of the rest. This allows me to make a version of less that calls view-file on the first [argument] given, but open in another window for each additional file.

[00:04:36.080]

  1. Better regular expressions.

Can’t remember regular expressions when calling grep or some other search function? Use the rx macro. Here I call ripgrep again, but this time, I’m using a Lisp expression calling the rx macro to look for UUIDs in the files in my current directory. But I have another improvement for this. While the rx macro is freaking cool for Emacs Lisp, it doesn’t always translate to regular expressions accepted by most commands. The (I have no idea how to pronounce this) pcre2el project can convert from a Lisp regular expression to Perl-compatible regular expressions (PCRE) acceptable by most search commands. I’ve created a new macro here, prx, that translates the output of the rx macro. This allows me to type something much more readable, and probably easier to remember. Certainly easier than this freaking regular expression. I’ve got an even better improvement. The rx macro with regular expression snippets can be assigned to key words that I can then take advantage of. Now our command would be much simpler to type.

[00:06:13.480]

  1. Loops are better with predicates.

Let’s say you want to remove the execute bit from files that have it. In a shell like bash, you need both a for loop and an if, as you can see in this example. With eshell, use a predicate to combine into a simple loop. The paren x after a file glob filters for only files marked as executable. Now here is another improvement. Since we often type loops to execute on one command, what about creating a function that can do this all in one go? This do function splits the arguments on that double colon, where the left side is a single statement to run, and the right side is a list of files. I have to append and flatten it in order for it to work. It loops through each file, creating an eshell command with the file appended. With this, I can remove the execute bit on all CSV files that have it. I see that my example wasn’t too good, as most commands like chmod accept multiple files, but you get the idea. In my final, larger form on my website, I don’t assume the command expression accepts a file as a final argument, as I can also replace underscores with the filename.

[00:07:39.640]

  1. Output of last command.

Most shells have a special variable like $? for the exit code of the last command. While reading through the source code, I noticed that the $$ refers to the output of the last command. This seems pretty cool. However, Eshell returns true or nil when running external commands, so accessing the output from a call to ls doesn’t work as expected. But this is Emacs. We can fix that. After running any command, eshell sets these four variables. I can hook a function call after every Eshell command. Using buffer-substring, I store the output into a global variable, and extend Eshell’s special variables list. In my Emacs configuration, I turned this variable into a ring, so while $$ works, so does array sub-scripting on that variable. This allows me to run a command and use the output from that command more than once. The code for this is a bit longer, so you’ll need to see my Emacs configuration for details.

[00:09:08.520]

  1. Redirection back to Emacs.

Output of any command can go to kill-ring (or the clipboard). Think of the implications. You don’t have to go into text selection mode. Just grab the output. In fact, with our $$ improvement, we can always copy the output from the last command to the clipboard. Better yet, let’s write the output to our engineering notebook. Here’s my idea. First, create a capture template that takes a string, or if called interactively, the region, and that does an immediate-finish after inserting that string to the default notes file. Next, create a wrapper function to call org-capture-string to run that template. Finally, we add our new function to eshell-virtual-targets. Let’s see this in action. I have a CSV file of user information. I can use grep and cut to extract some of that and write it out to this month’s engineering notebook.

[00:10:26.880]

  1. Using Emacs buffers.

Why leave the results of eshell commands in the eshell buffer? Send the output into a buffer where you can use it. Here’s a call to ripgrep that searches for lines with email addresses using a complicated regular expression that I added to my prx macro. When I switch to this almost-grep buffer, I can turn on grep-mode. Now I can jump around as if I just called grep directly. Perhaps I’m proficient with my prx macro to filter out entries, but not good with shell commands that I can use in pipes to extract just one… the address column, for instance? Let’s just extract it, send it to a buffer called email-list, and now I can use Emacs commands that I know and love to edit the data directly. We currently have an over-sight that the Eshell’s built-in cat command doesn’t pipe buffer contents as standard in. So I created a bcat, a buffer cat, function to do this. So this command works to grab my email addresses I just extracted and send them to another program. If you’re interested, I have a more elaborate and yet simpler workflow surrounding sending data back and forth from Eshell to Emacs buffers.

[00:12:28.400]

  1. Did I mention that you can cd to remote systems?

This command uses SSH to jump to my host, goblin, start a root session, and jump to the etc directory. Remember that Tramp can be finicky if you start blinging your remote hosts with oh-my-zshell, and funky prompts and things like that, so your mileage may vary.

[00:12:59.360] In summary: Use eshell if you want a quick way to run commands and Emacs functions as a REPL, or to run an OS program but process the output with Emacs. Keep in mind that Eshell has two types of subshells, and you can mix and match during a command call. The rx macro is really cool. Eshell loops are better with filters and predicates … if you can remember them. Take advantage of Emacs buffers to really enhance your shell experience. You’ve now seen that just like Emacs, I’ve crafted Eshell to be my own shell creation, tailored to my workflow. So, steal my spells, cast your own magic, but feel free to share your incantations back to me. I’ve gone over my time allotment, so we’ll have to continue this discussion on the intertubes. Why yes, I have joined the birdless diaspora, so toot me over there. Thanks.

Captioner: howard Questions or comments? Please e-mail [email protected]


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK