2

Let's say I have a file called .alias in my $HOME directory with the following content:

alias "my-first-alias"="ls -lha"
alias "my-second-alias="echo 'Hello World'"

I know that if put the line source "$HOME/.alias" in both my .bashrc and .zshrc files I'll be able to create aliases on these shells at the same time in a single file, just so I don't have to manually copy one alias that I have just created in .bashrc to .zshrc...

So far everything is fine... The problem starts with eshell, its alias syntax is different, the last two aliases in eshell syntax would be the following:

alias my-first-alias 'ls -lha'
alias my-second-alias 'echo "Hello World"'

Since its syntax is different I can't just source my .alias file for eshell, I wouldn't like to manually translate my aliases for the eshell syntax all the times that I create a new alias. Is there any standard way of solving problems like this on emacs? Or should I be thinking about how to create a script that will translate my bash aliases to eshell aliases for sourcing it?

raylight
  • 217
  • 8

1 Answers1

2

If you go over to EshellAlias on EmacsWiki, there are many solutions to this problem. The one by Edgar Vincent that's currently at the very bottom of the page is the most concise and elegant solution so far.

  (defun eshell-load-bash-aliases ()
    "Read Bash aliases and add them to the list of eshell aliases."
    ;; Bash needs to be run - temporarily - interactively
    ;; in order to get the list of aliases.
      (with-temp-buffer
        (call-process "bash" nil '(t nil) nil "-ci" "alias")
        (goto-char (point-min))
        (while (re-search-forward "alias \\(.+\\)='\\(.+\\)'$" nil t)
          (eshell/alias (match-string 1) (match-string 2)))))

  ;; We only want Bash aliases to be loaded when Eshell loads its own aliases,
  ;; rather than every time `eshell-mode' is enabled.
  (add-hook 'eshell-alias-load-hook 'eshell-load-bash-aliases)

It reads the output of bash -ci alias and loops through them to run eshell/alias on each alias it finds. It should implicitly load your $HOME/.alias file.

The function eshell/alias in the eshell-laod-bash-aliases above writes the list of aliases to the file eshell-aliases-file after each addition of one alias.
That may take long for long alias lists. The following version writes the list only after processing all aliases from bash.

(require 'cl-lib)

(defun eshell-load-bash-aliases ()
  "Read Bash aliases and add them to the list of eshell aliases."
  ;; Bash needs to be run - temporarily - interactively
  ;; in order to get the list of aliases.
  (with-temp-buffer
    (call-process "bash" nil '(t nil) nil "-ci" "alias")
    (goto-char (point-min))
    (cl-letf (((symbol-function 'eshell-write-aliases-list) #'ignore))
      (while (re-search-forward "alias \\(.+\\)='\\(.+\\)'$" nil t)
        (eshell/alias (match-string 1) (match-string 2))))
    (eshell-write-aliases-list)))

;; We only want Bash aliases to be loaded when Eshell loads its own aliases,
;; rather than every time `eshell-mode' is enabled.
(add-hook 'eshell-alias-load-hook 'eshell-load-bash-aliases)
Tobias
  • 32,569
  • 1
  • 34
  • 75
g-gundam
  • 1,096
  • 1
  • 3
  • 13
  • 1
    Thanks! Even though it worked fine it seems that emacs loads this function on the run all the times that I open `eshell` for the first time on emacs... Since I have a lot of aliases this solution is slow for my case (it takes around 40 seconds to start)... I'm not sure if there's a workaround with a elisp solution. But I've realized the bash solution on the page from your link works immediately... Probably writing a bash script that watches changes on my `.alias` file and rewrites a second `.alias_eshell` file works better for me. – raylight Nov 02 '22 at 05:57
  • Just out of curiosity, how many aliases do you have? 40 seconds is a long time just to load aliases. – g-gundam Nov 02 '22 at 07:06
  • 1
    Well, it's an old file with aliases and I don't really know all of them by heart. But there are 131 aliases. I've also tested with an empty `.alias` file and in this case this solution works immediately. Apparently, 131 is a huge number for elisp, I'm not sure if it's only that though... – raylight Nov 02 '22 at 07:18
  • 1
    @raylight Please, try again with the modified version at the bottom of this answer. – Tobias Nov 03 '22 at 05:12
  • @Tobias Thank you for that speed optimization. – g-gundam Nov 03 '22 at 14:48
  • @Tobias Thanks, with the second sample of code it works immediately for me now. – raylight Nov 06 '22 at 18:26