index all rss mastodon twitter github linkedin email
Álvaro Ramírez

Álvaro Ramírez

19 June 2021 Blurring the lines between shell and editor


I recently tweeted that Vivek Haldar's 10-year old post rings true today just the same. He writes about the levels of Emacs proficiency. All 6 levels are insightful in their own right, but for the sake of this post, let's quote an extract from level 4. Shell inside Emacs:

"And then, you learned about it: M-x shell.

It was all just text. Why did you need another application for it? Why should only the shell prompt be editable? Why can’t I move my cursor up a few lines to where the last command spewed out its results? All these problems simply disappear when your shell (or shells) simply becomes another Emacs buffer, upon which all of the text manipulation power of Emacs can be brought to bear."

In other words, we aren't merely removing shell restrictions, but opening up possibilities…

Take Emacs eshell looping, for example. I use it so infrequently, I could never remember eshell's syntax. I would refer back to EmacsWiki's Eshell For Loop or Mastering Emacs's Mastering Eshell comments for a reminder. It finally dawned on me. I don't need to internalize this eshell syntax. I have YASnippet available like any other buffer. I could just type "for" and let YASnippet do the rest for me.


All I need is a tiny YASnippet:

#name : Eshell for loop
#key : for
# --
for f in ${1:*} { ${2:echo} "$f"; $3} $0

Want a gentle and succinct YASnippet intro? Check out Jake's YASnippet introduction video.


If you're a shell-mode user, YASnippet would have you covered in your favorite shell. The expansion snippet can be modified to a Bash equivalent, giving us the same benefit. We type "for" and let YASnippet expand and hop over arguments. Here's a Bash equivalent emphasizing the hopping a little more:


#name : bash for loop
#key : for
# --
for f in ${1:*}; do ${2:echo} $f; done $0

ps. Looks like vterm, term, or ansi-term work too. See Shane Mulligan's post: Use YASnippets in term and vterm in emacs.