From 064c989ffefa7516c80485cd041208e2a8a5032d Mon Sep 17 00:00:00 2001 From: Sacha Chua Date: Sun, 4 Dec 2022 13:41:24 -0500 Subject: Automated commit --- ...should-be-using-eshell--howard-abrams--main.vtt | 739 +++++++++++++++++++++ 1 file changed, 739 insertions(+) create mode 100644 2022/captions/emacsconf-2022-eshell--top-10-reasons-why-you-should-be-using-eshell--howard-abrams--main.vtt (limited to '2022/captions/emacsconf-2022-eshell--top-10-reasons-why-you-should-be-using-eshell--howard-abrams--main.vtt') diff --git a/2022/captions/emacsconf-2022-eshell--top-10-reasons-why-you-should-be-using-eshell--howard-abrams--main.vtt b/2022/captions/emacsconf-2022-eshell--top-10-reasons-why-you-should-be-using-eshell--howard-abrams--main.vtt new file mode 100644 index 00000000..80b3afb8 --- /dev/null +++ b/2022/captions/emacsconf-2022-eshell--top-10-reasons-why-you-should-be-using-eshell--howard-abrams--main.vtt @@ -0,0 +1,739 @@ +WEBVTT captioned by howard + +NOTE Introduction + +00:00:00.000 --> 00:00:04.999 +I have 10 minutes to talk you into + +00:00:05.000 --> 00:00:07.879 +giving Eshell a second chance. + +00:00:07.880 --> 00:00:10.119 +Have the right perspective and expectation, + +00:00:10.120 --> 00:00:12.919 +and I think you’ll really enjoy it. + +00:00:12.920 --> 00:00:15.679 +Just remember eshell is a shell, + +00:00:15.680 --> 00:00:17.839 +not a terminal emulator. + +00:00:17.840 --> 00:00:20.279 +I use both Eshell and vterm. + +00:00:20.280 --> 00:00:23.479 +I’m going to talk and type fast, + +00:00:23.480 --> 00:00:28.999 +as I have 10 reasons for you to try Eshell again. + +NOTE 1. It’s an Emacs REPL + +00:00:29.000 --> 00:00:32.599 +1. It’s an Emacs REPL. + +00:00:32.600 --> 00:00:33.999 +I mean, check this out. + +00:00:34.000 --> 00:00:36.999 +Let’s start up Eshell here. + +00:00:37.000 --> 00:00:41.399 +Let’s just type a Lisp expression. + +00:00:41.400 --> 00:00:43.919 +It works. + +00:00:43.920 --> 00:00:48.599 +As a shell, the parens are kinda optional. + +NOTE 2. It’s also a shell + +00:00:48.600 --> 00:00:52.519 +2. It’s also a shell. + +00:00:52.520 --> 00:00:56.479 +While eshell may look like a shell, like Bash + +00:00:56.480 --> 00:00:58.559 +you should view it as a REPL + +00:00:58.560 --> 00:01:02.399 +with parenthesis-less s-expressions. + +00:01:02.400 --> 00:01:05.559 +This makes sense, because a shell command with options, + +00:01:05.560 --> 00:01:07.999 +like this ls command, + +00:01:08.000 --> 00:01:10.119 +looks like an s-expression. + +NOTE 3. You can mix these two modes + +00:01:10.120 --> 00:01:12.879 +3. You can mix these two modes. + +00:01:12.880 --> 00:01:14.959 +Shells can call subshells + +00:01:14.960 --> 00:01:17.919 +which return their output like a function call, + +00:01:17.920 --> 00:01:20.799 +like this Bash command. + +00:01:20.800 --> 00:01:22.759 +In this Eshell example, + +00:01:22.760 --> 00:01:24.639 +I use the output of a text file + +00:01:24.640 --> 00:01:27.959 +as command line arguments to ripgrep. + +00:01:27.960 --> 00:01:29.639 +Notice how I use braces + +00:01:29.640 --> 00:01:34.759 +to state that it is a call to an eshell expression. + +00:01:34.760 --> 00:01:40.039 +We can mix Lisp-expressions and Shell-expressions. + +00:01:40.040 --> 00:01:45.599 +Allow me a contrived example. + +00:01:45.600 --> 00:01:50.079 +Notice I use good ol' setq to create a variable. + +00:01:50.080 --> 00:01:54.919 +Yes, those are global Emacs variables available everywhere. + +00:01:54.920 --> 00:01:59.599 +In Eshell, the wildcard actually creates a list. + +00:01:59.600 --> 00:02:04.479 +This variable assignment doesn’t work as you might expect, + +00:02:04.480 --> 00:02:07.559 +as setq in Eshell is still setq, + +00:02:07.560 --> 00:02:10.319 +and it assigns variables in pairs. + +00:02:10.320 --> 00:02:17.119 +To make a list in Eshell, we use listify: + +00:02:17.120 --> 00:02:21.239 +Without parens, Eshell is in “shell mode”, + +00:02:21.240 --> 00:02:23.799 +which means that words are strings, + +00:02:23.800 --> 00:02:26.879 +and variables need to be prefixed with dollar signs. + +00:02:26.880 --> 00:02:32.399 +A command can have both Eshell and Lisp expressions. + +00:02:32.400 --> 00:02:34.559 +As you can see here, + +00:02:34.560 --> 00:02:37.119 +I have a call to ripgrep, + +00:02:37.120 --> 00:02:40.319 +but part of it is an s-expression. + +00:02:40.320 --> 00:02:42.239 +Remember the differences: + +00:02:42.240 --> 00:02:46.159 +With parens, eshell treats it as Lisp, + +00:02:46.160 --> 00:02:49.199 +like the last line in my example. + +00:02:49.200 --> 00:02:53.919 +With braces, eshell follows these shell-like rules: + +00:02:53.920 --> 00:02:57.159 +First, if it looks like a number, it's a number. + +00:02:57.160 --> 00:02:59.439 +Otherwise, eshell converts it to a string + +00:02:59.440 --> 00:03:03.679 +(quotes, like a shell, groups words). + +00:03:03.680 --> 00:03:07.519 +What about this mix between functions and executables + +00:03:07.520 --> 00:03:10.839 +for the first word? + +00:03:10.840 --> 00:03:15.439 +Functions that begin with eshell are called first. + +00:03:15.440 --> 00:03:19.079 +Next in priority are executables on your $PATH, + +00:03:19.080 --> 00:03:22.159 +then matching Lisp functions. + +00:03:22.160 --> 00:03:23.940 +You can actually switch this order + +00:03:23.941 --> 00:03:27.559 +with the `eshell-prefer-lisp-functions' variable. + +NOTE 4. Emacs is better than shell + +00:03:27.560 --> 00:03:31.759 +4. Emacs is actually better than shell. + +00:03:31.760 --> 00:03:35.199 +If the following works, why would you call + +00:03:35.200 --> 00:03:40.039 +expr or bc or dc, or any of those other calculators? + +00:03:40.040 --> 00:03:43.639 +You can just call a Lisp expression. + +00:03:43.640 --> 00:03:47.999 +Why call less or more when you could call view-file? + +00:03:48.000 --> 00:03:52.839 +Here, I’ve aliased less to view-file. + +00:03:52.840 --> 00:03:57.559 +Load it up, and it shows up in an Emacs mode. + +00:03:57.560 --> 00:04:01.519 +Just like with less, if you hit q, + +00:04:01.520 --> 00:04:05.759 +you go back to your Eshell terminal. + +00:04:05.760 --> 00:04:08.439 +I do have an improvement, though. + +00:04:08.440 --> 00:04:10.479 +The problem with view-file is + +00:04:10.480 --> 00:04:13.399 +it takes a single file as an argument. + +00:04:13.400 --> 00:04:15.719 +In a shell, we might want to view more than one. + +00:04:15.720 --> 00:04:18.719 +So let’s make a solution to that. + +00:04:18.720 --> 00:04:20.999 +This function will call the first function + +00:04:21.000 --> 00:04:22.159 +with the first argument, + +00:04:22.160 --> 00:04:26.679 +and the second function with each of the rest. + +00:04:26.680 --> 00:04:29.559 +This allows me to make a version of less + +00:04:29.560 --> 00:04:33.159 +that calls view-file on the first [argument] given, + +00:04:33.160 --> 00:04:36.079 +but open in another window for each additional file. + +NOTE 5. Better regular expressions + +00:04:36.080 --> 00:04:41.239 +5. Better regular expressions. + +00:04:41.240 --> 00:04:44.799 +Can’t remember regular expressions when calling + +00:04:44.800 --> 00:04:48.639 +grep or some other search function? Use the rx macro. + +00:04:48.640 --> 00:04:55.919 +Here I call ripgrep again, but this time, + +00:04:55.920 --> 00:05:00.679 +I’m using a Lisp expression calling the rx macro + +00:05:00.680 --> 00:05:04.719 +to look for UUIDs in the files in my current directory. + +00:05:04.720 --> 00:05:08.159 +But I have another improvement for this. + +00:05:08.160 --> 00:05:13.479 +While the rx macro is freaking cool for Emacs Lisp, + +00:05:13.480 --> 00:05:15.919 +it doesn’t always translate to regular expressions + +00:05:15.920 --> 00:05:20.079 +accepted by most commands. + +00:05:20.080 --> 00:05:25.199 +The (I have no idea how to pronounce this) pcre2el project + +00:05:25.200 --> 00:05:28.519 +can convert from a Lisp regular expression + +00:05:28.520 --> 00:05:31.359 +to Perl-compatible regular expressions (PCRE) + +00:05:31.360 --> 00:05:33.519 +acceptable by most search commands. + +00:05:33.520 --> 00:05:37.879 +I’ve created a new macro here, prx, + +00:05:37.880 --> 00:05:41.319 +that translates the output of the rx macro. + +00:05:41.320 --> 00:05:46.519 +This allows me to type something much more readable, + +00:05:46.520 --> 00:05:48.519 +and probably easier to remember. + +00:05:48.520 --> 00:05:54.679 +Certainly easier than this freaking regular expression. + +00:05:54.680 --> 00:05:59.439 +I’ve got an even better improvement. + +00:05:59.440 --> 00:06:03.559 +The rx macro with regular expression snippets + +00:06:03.560 --> 00:06:05.759 +can be assigned to key words + +00:06:05.760 --> 00:06:08.679 +that I can then take advantage of. + +00:06:08.680 --> 00:06:13.479 +Now our command would be much simpler to type. + +NOTE 6. Loops are better with predicates + +00:06:13.480 --> 00:06:16.159 +6. Loops are better with predicates. + +00:06:16.160 --> 00:06:18.759 +Let’s say you want to remove the execute bit + +00:06:18.760 --> 00:06:20.479 +from files that have it. + +00:06:20.480 --> 00:06:24.399 +In a shell like bash, you need both a for loop and an if, + +00:06:24.400 --> 00:06:26.599 +as you can see in this example. + +00:06:26.600 --> 00:06:31.559 +With eshell, use a predicate to combine into a simple loop. + +00:06:31.560 --> 00:06:34.359 +The paren x after a file glob + +00:06:34.360 --> 00:06:36.879 +filters for only files marked as executable. + +00:06:36.880 --> 00:06:43.559 +Now here is another improvement. + +00:06:43.560 --> 00:06:47.959 +Since we often type loops to execute on one command, + +00:06:47.960 --> 00:06:49.519 +what about creating a function + +00:06:49.520 --> 00:06:50.999 +that can do this all in one go? + +00:06:51.000 --> 00:06:57.599 +This do function splits the arguments on that double colon, + +00:06:57.600 --> 00:07:00.079 +where the left side is a single statement to run, + +00:07:00.080 --> 00:07:02.599 +and the right side is a list of files. + +00:07:02.600 --> 00:07:05.839 +I have to append and flatten it + +00:07:05.840 --> 00:07:07.639 +in order for it to work. + +00:07:07.640 --> 00:07:09.399 +It loops through each file, + +00:07:09.400 --> 00:07:12.079 +creating an eshell command with the file appended. + +00:07:12.080 --> 00:07:15.759 +With this, I can remove the execute bit + +00:07:15.760 --> 00:07:20.759 +on all CSV files that have it. + +00:07:20.760 --> 00:07:24.319 +I see that my example wasn’t too good, as most commands + +00:07:24.320 --> 00:07:29.039 +like chmod accept multiple files, but you get the idea. + +00:07:29.040 --> 00:07:33.159 +In my final, larger form on my website, + +00:07:33.160 --> 00:07:35.279 +I don’t assume the command expression accepts + +00:07:35.280 --> 00:07:36.719 +a file as a final argument, + +00:07:36.720 --> 00:07:39.639 +as I can also replace underscores with the filename. + +NOTE 7. Output of last command + +00:07:39.640 --> 00:07:45.399 +7. Output of last command. + +00:07:45.400 --> 00:07:48.799 +Most shells have a special variable + +00:07:48.800 --> 00:07:52.839 +like $? for the exit code of the last command. + +00:07:52.840 --> 00:07:55.919 +While reading through the source code, + +00:07:55.920 --> 00:07:58.799 +I noticed that the $$ refers to + +00:07:58.800 --> 00:08:00.599 +the output of the last command. + +00:08:00.600 --> 00:08:05.799 +This seems pretty cool. + +00:08:05.800 --> 00:08:10.759 +However, Eshell returns true or nil + +00:08:10.760 --> 00:08:12.719 +when running external commands, + +00:08:12.720 --> 00:08:15.879 +so accessing the output from a call to ls + +00:08:15.880 --> 00:08:19.479 +doesn’t work as expected. + +00:08:19.480 --> 00:08:21.119 +But this is Emacs. + +00:08:21.120 --> 00:08:23.159 +We can fix that. + +00:08:23.160 --> 00:08:28.119 +After running any command, eshell sets these four variables. + +00:08:28.120 --> 00:08:33.519 +I can hook a function call after every Eshell command. + +00:08:33.520 --> 00:08:36.759 +Using buffer-substring, + +00:08:36.760 --> 00:08:39.279 +I store the output into a global variable, + +00:08:39.280 --> 00:08:43.599 +and extend Eshell’s special variables list. + +00:08:43.600 --> 00:08:46.519 +In my Emacs configuration, + +00:08:46.520 --> 00:08:48.479 +I turned this variable into a ring, + +00:08:48.480 --> 00:08:51.439 +so while $$ works, + +00:08:51.440 --> 00:08:54.399 +so does array sub-scripting on that variable. + +00:08:54.400 --> 00:08:58.399 +This allows me to run a command + +00:08:58.400 --> 00:09:02.279 +and use the output from that command more than once. + +00:09:02.280 --> 00:09:05.279 +The code for this is a bit longer, + +00:09:05.280 --> 00:09:08.519 +so you’ll need to see my Emacs configuration for details. + +NOTE 8. Redirection back to Emacs + +00:09:08.520 --> 00:09:13.439 +8. Redirection back to Emacs. + +00:09:13.440 --> 00:09:14.879 +Output of any command + +00:09:14.880 --> 00:09:18.519 +can go to kill-ring (or the clipboard). + +00:09:18.520 --> 00:09:21.079 +Think of the implications. + +00:09:21.080 --> 00:09:23.839 +You don’t have to go into text selection mode. + +00:09:23.840 --> 00:09:26.239 +Just grab the output. + +00:09:26.240 --> 00:09:30.279 +In fact, with our $$ improvement, + +00:09:30.280 --> 00:09:33.239 +we can always copy the output from the last command + +00:09:33.240 --> 00:09:34.079 +to the clipboard. + +00:09:34.080 --> 00:09:37.999 +Better yet, let’s write the output + +00:09:38.000 --> 00:09:39.399 +to our engineering notebook. + +00:09:39.400 --> 00:09:41.679 +Here’s my idea. + +00:09:41.680 --> 00:09:46.079 +First, create a capture template that takes a string, + +00:09:46.080 --> 00:09:48.199 +or if called interactively, the region, + +00:09:48.200 --> 00:09:51.879 +and that does an immediate-finish after inserting + +00:09:51.880 --> 00:09:53.879 +that string to the default notes file. + +00:09:53.880 --> 00:09:57.679 +Next, create a wrapper function + +00:09:57.680 --> 00:10:01.559 +to call org-capture-string to run that template. + +00:10:01.560 --> 00:10:07.639 +Finally, we add our new function to eshell-virtual-targets. + +00:10:07.640 --> 00:10:08.759 +Let’s see this in action. + +00:10:08.760 --> 00:10:15.707 +I have a CSV file of user information. + +00:10:15.708 --> 00:10:19.719 +I can use grep and cut to extract some of that + +00:10:19.720 --> 00:10:26.879 +and write it out to this month’s engineering notebook. + +NOTE 9. Using Emacs buffers + +00:10:26.880 --> 00:10:35.279 +9. Using Emacs buffers. + +00:10:35.280 --> 00:10:39.159 +Why leave the results of eshell commands + +00:10:39.160 --> 00:10:40.279 +in the *eshell* buffer? + +00:10:40.280 --> 00:10:44.119 +Send the output into a buffer where you can use it. + +00:10:44.120 --> 00:10:47.999 +Here’s a call to ripgrep + +00:10:48.000 --> 00:10:50.759 +that searches for lines with email addresses + +00:10:50.760 --> 00:10:53.519 +using a complicated regular expression + +00:10:53.520 --> 00:10:56.079 +that I added to my prx macro. + +00:10:56.080 --> 00:11:01.079 +When I switch to this almost-grep buffer, + +00:11:01.080 --> 00:11:03.319 +I can turn on grep-mode. + +00:11:03.320 --> 00:11:09.039 +Now I can jump around as if I just called grep directly. + +00:11:09.040 --> 00:11:14.759 +Perhaps I’m proficient with my prx macro + +00:11:14.760 --> 00:11:16.639 +to filter out entries, + +00:11:16.640 --> 00:11:19.279 +but not good with shell commands + +00:11:19.280 --> 00:11:23.999 +that I can use in pipes to extract just one… + +00:11:24.000 --> 00:11:26.039 +the address column, for instance? + +00:11:26.040 --> 00:11:28.959 +Let’s just extract it, + +00:11:28.960 --> 00:11:33.279 +send it to a buffer called email-list, + +00:11:33.280 --> 00:11:38.479 +and now I can use Emacs commands that I know and love + +00:11:38.480 --> 00:11:39.799 +to edit the data directly. + +00:11:39.800 --> 00:11:55.799 +We currently have an over-sight + +00:11:55.800 --> 00:11:58.839 +that the Eshell’s built-in cat command + +00:11:58.840 --> 00:12:02.719 +doesn’t pipe buffer contents as standard in. + +00:12:02.720 --> 00:12:07.919 +So I created a bcat, a buffer cat, function to do this. + +00:12:07.920 --> 00:12:09.879 +So this command works + +00:12:09.880 --> 00:12:14.599 +to grab my email addresses I just extracted + +00:12:14.600 --> 00:12:16.319 +and send them to another program. + +00:12:16.320 --> 00:12:20.959 +If you’re interested, I have a more elaborate + +00:12:20.960 --> 00:12:25.759 +and yet simpler workflow surrounding sending data + +00:12:25.760 --> 00:12:28.399 +back and forth from Eshell to Emacs buffers. + +NOTE 10. cd to remote systems + +00:12:28.400 --> 00:12:35.679 +10. Did I mention that you can cd to remote systems? + +00:12:35.680 --> 00:12:39.879 +This command uses SSH to jump to my host, goblin, + +00:12:39.880 --> 00:12:44.039 +start a root session, and jump to the etc directory. + +00:12:44.040 --> 00:12:47.719 +Remember that Tramp can be finicky + +00:12:47.720 --> 00:12:52.839 +if you start blinging your remote hosts with oh-my-zshell, + +00:12:52.840 --> 00:12:57.790 +and funky prompts and things like that, + +00:12:57.791 --> 00:12:59.359 +so your mileage may vary. + +NOTE Summary + +00:12:59.360 --> 00:13:03.959 +In summary: Use eshell if you want + +00:13:03.960 --> 00:13:07.319 +a quick way to run commands and Emacs functions as a REPL, + +00:13:07.320 --> 00:13:11.479 +or to run an OS program but process the output with Emacs. + +00:13:11.480 --> 00:13:15.919 +Keep in mind that Eshell has two types of subshells, + +00:13:15.920 --> 00:13:19.599 +and you can mix and match during a command call. + +00:13:19.600 --> 00:13:22.639 +The rx macro is really cool. + +00:13:22.640 --> 00:13:26.599 +Eshell loops are better with filters and predicates … + +00:13:26.600 --> 00:13:28.239 +if you can remember them. + +00:13:28.240 --> 00:13:30.959 +Take advantage of Emacs buffers + +00:13:30.960 --> 00:13:32.879 +to really enhance your shell experience. + +00:13:32.880 --> 00:13:36.039 +You’ve now seen that just like Emacs, + +00:13:36.040 --> 00:13:39.519 +I’ve crafted Eshell to be my own shell creation, + +00:13:39.520 --> 00:13:41.039 +tailored to my workflow. + +00:13:41.040 --> 00:13:44.799 +So, steal my spells, cast your own magic, + +00:13:44.800 --> 00:13:48.759 +but feel free to share your incantations back to me. + +00:13:48.760 --> 00:13:51.359 +I’ve gone over my time allotment, so we’ll have to + +00:13:51.360 --> 00:13:53.679 +continue this discussion on the intertubes. + +00:13:53.680 --> 00:13:57.159 +Why yes, I have joined the birdless diaspora, + +00:13:57.160 --> 00:13:59.199 +so toot me over there. + +00:13:59.200 --> 00:14:01.920 +Thanks. -- cgit v1.2.3