Emacs, Shell, Abbrev, and ELISP Power to Bear!

Perm URL with updates: http://ergoemacs.org/misc/emacs_abbrev_shell_elisp.html

Using Abbrev for Shell Commands

You can define abbrev for frequently used shell commands. For example, i type “3rs” and it expands to

rsync -z -r -v -t --chmod=Dugo+x --chmod=ugo+r --delete --exclude='*~' --exclude='.bash_history' --exclude='logs/'  --rsh='ssh -l u89150' ~/web/ u89150@s72750.example.com:~/

Is emacs abbrev better than bash alias?

Emacs abbrev is better than bash alias, because you see the full command.

what about using shell 【Ctrl+r】 back search feature?

That's great, but for frequently used command, alias or abbrev is better, because you get EXACTLY the command you want.

With back search, you might have modified a command, and you have to eye-ball to be sure it's the command you want. Bash alias or emacs abbrev are muscle memory.

for how to set abbrev, see: Using Emacs Abbrev Mode for Abbreviation

Advantage of Using Shell Inside Emacs

using shell inside emacs is much superior than using a terminal. You have all lines logged by default, can be saved if you want, anytime. You can edit or copy/paste easily any past lines. And you have full power of emacs to edit any line, or jump into any file path (ffap)

for how to use shell inside emacs, see Emacs Shell Tutorial (Bash, cmd.exe, PowerShell)

Elisp Power Come to Bear

now, for the more advanced and esoteric emacs users.

What's even better, is elisp.

I have many shell command abbrevs. For example:

;; shell commands
("3ditto" "ditto -ck --sequesterRsrc --keepParent src dest")
("3im" "convert -quality 85% ")
("3ims" "convert -size  -quality 85% ")
("3im256" "convert +dither -colors 256 ")
("3imf" "find . -name \"*png\" | xargs -l -i basename \"{}\" \".png\" | xargs -l -i  convert -quality 85% \"{}.png\" \"{}.jpg\"")

("3f0" "find . -type f -empty")
("3f00" "find . -type f -size 0 -exec rm {} ';'")
("3chmod" "find . -type f -exec chmod 644 {} ';'")
("3chmod2" "find . -type d -exec chmod 755 {} ';'")

("3unison" "unison -servercmd /usr/bin/unison c:/Users/xah/web ssh://xah@example.com//Users/xah/web")
("3sftp" "sftp xah@xahlee.org")
("3ssh" "ssh xah@xahlee.org")
("3rsync" "rsync -z -r -v -t --exclude=\"*~\" --exclude=\".DS_Store\" --exclude=\".bash_history\" --exclude=\"**/xx_xahlee_info/*\"  --exclude=\"*/_curves_robert_yates/*.png\" --exclude=\"logs/*\"  --exclude=\"xlogs/*\" --delete --rsh=\"ssh -l xah\" ~/web/ xah@example.com:~/")

("3rsync2" "rsync -r -v -t --delete --rsh=\"ssh -l xah\" ~/web/ xah@example.com:~/web/")
("3rsync3" "rsync -r -v -t --delete --exclude=\"**/My *\" --rsh=\"ssh -l xah\" ~/Documents/ xah@example.com:~/Documents/")

the problem is, some of them are not frequently used, and i forgot what is the abbrev. For example, i have many command that convert image in various ways. They starts with “3im”. But i forgot the one i wanted. So, i have to open my abbrev file to see. 〔☛ Using Emacs's Bookmark Feature

would it be great, if all your abbrevs has a ido-like interface? so that you can see them as you type? 〔☛ Emacs: iswitch vs ido mode〕 〔☛ Emacs: Name Completion Features & Packages〕 〔☛ Emacs: List/Switch Buffers

So, now i wrote a command, like this:

(defcustom xah-shell-abbrev-alist nil "alist of xah's shell abbrevs")
(setq xah-shell-abbrev-alist
          '(
            ("rsync1" . "rsync -z -r -v -t --chmod=Dugo+x --chmod=ugo+r --delete --exclude='*~' --exclude='.bash_history' --exclude='logs/'  --rsh='ssh -l u80781' ~/web/ u80781@s30097.example.com:~/")

            ("ssh" . "ssh -l u80781 xahlee.org ")
            ("img1" . "convert -quality 85% ")
            ("imgScale" . "convert -scale 50% -quality 85% ")
            ("img256" . "convert +dither -colors 256 ")
            ("imgBatch" . "find . -name \"*png\" | xargs -l -i basename \"{}\" \".png\" | xargs -l -i  convert -quality 85% \"{}.png\" \"{}.jpg\"")
            ("img-bmp2png" . "find . -name \"*bmp\" | xargs -l -i basename \"{}\" \".bmp\" | xargs -l -i  convert \"{}.bmp\" \"{}.png\"")

            ("grep" . "grep -r -F 'xxx' --include='*html' ~/web")

            ("rm_empty" . "find . -type f -empty")
            ("chmod_file" . "find . -type f -exec chmod 644 {} ';'")
            ("rm~" . "find . -name \"*~\" -exec rm {} ';'")
            ("findEmptyDir" . "find . -depth -empty -type d")
            ("rmEmptyDir" . "find . -depth -empty -type d -exec rmdir {} ';'")
            ("chmod2" . "find . -type d -exec chmod 755 {} ';'")
            ("lynx" . "lynx -dump -assume_local_charset=utf-8 -display_charset=utf-8 -width=100")
            ("vp" . "feh --randomize --recursive --auto-zoom --action \"gvfs-trash '%f'\" --geometry 1600x1000 ~/Pictures/cinse_pixra3/ &")
            )

          )

(defun xah-shell-commands (cmdAbbrev)
  "insert shell command from a selection prompt."
  (interactive
   (list
      (ido-completing-read "shell abbrevs:" (mapcar (lambda (x) (car x)) xah-shell-abbrev-alist) "PREDICATE" "REQUIRE-MATCH") ) )
  (progn
    (insert (cdr (assoc cmdAbbrev xah-shell-abbrev-alist)))
    ))

i give a easy key for this command. When i need a shell command, i press a key, ido comes up showing me all the abbrevs. Then, i type 2 or more keys and press Enter ↵ and my command is inserted. Nice!

be warned, that this will take some used to. Like keybinding, you have to kick habit, and that may not be easy.

Popular posts from this blog

Browser User Agent Strings 2012

11 Years of Writing About Emacs

does md5 creates more randomness?