This commit is contained in:
Abraham Raji 2020-01-15 21:55:42 +05:30
parent 3302b9a14d
commit 42b80cd9a3
1 changed files with 155 additions and 0 deletions

View File

@ -192,3 +192,158 @@ Scrolling through the output and searching for results that can be copied to the
*Note:* We cant add it to the list until after we start our first
eshell session, so we just add it to the =eshell-pred-load-hook=
which is sufficient.
** Special Prompt
Following [[http://blog.liangzan.net/blog/2012/12/12/customizing-your-emacs-eshell-prompt/][these instructions]], we build a better prompt with the Git
branch in it (Of course, it matches my Bash prompt). First, we need
a function that returns a string with the Git branch in it,
e.g. ":master"
#+BEGIN_SRC emacs-lisp
(defun curr-dir-git-branch-string (pwd)
"Returns current git branch as a string, or the empty string if
PWD is not in a git repo (or the git command is not found)."
(interactive)
(when (and (not (file-remote-p pwd))
(eshell-search-path "git")
(locate-dominating-file pwd ".git"))
(let* ((git-url (shell-command-to-string "git config --get remote.origin.url"))
(git-repo (file-name-base (s-trim git-url)))
(git-output (shell-command-to-string (concat "git rev-parse --abbrev-ref HEAD")))
(git-branch (s-trim git-output))
(git-icon "\xe0a0")
(git-icon2 (propertize "\xf020" 'face `(:family "octicons"))))
(concat git-repo " " git-icon2 " " git-branch))))
#+END_SRC
The function takes the current directory passed in via =pwd= and
replaces the =$HOME= part with a tilde. I'm sure this function
already exists in the eshell source, but I didn't find it...
#+BEGIN_SRC emacs-lisp
(defun pwd-replace-home (pwd)
"Replace home in PWD with tilde (~) character."
(interactive)
(let* ((home (expand-file-name (getenv "HOME")))
(home-len (length home)))
(if (and
(>= (length pwd) home-len)
(equal home (substring pwd 0 home-len)))
(concat "~" (substring pwd home-len))
pwd)))
#+END_SRC
Make the directory name be shorter...by replacing all directory
names with just its first names. However, we leave the last two to
be the full names. Why yes, I did steal this.
#+BEGIN_SRC emacs-lisp
(defun pwd-shorten-dirs (pwd)
"Shorten all directory names in PWD except the last two."
(let ((p-lst (split-string pwd "/")))
(if (> (length p-lst) 2)
(concat
(mapconcat (lambda (elm) (if (zerop (length elm)) ""
(substring elm 0 1)))
(butlast p-lst 2)
"/")
"/"
(mapconcat (lambda (elm) elm)
(last p-lst 2)
"/"))
pwd))) ;; Otherwise, we just return the PWD
#+END_SRC
Break up the directory into a "parent" and a "base":
#+BEGIN_SRC emacs-lisp
(defun split-directory-prompt (directory)
(if (string-match-p ".*/.*" directory)
(list (file-name-directory directory) (file-name-base directory))
(list "" directory)))
#+END_SRC
Using virtual environments for certain languages is helpful to know,
especially since I change them based on the directory.
#+BEGIN_SRC emacs-lisp
(defun ruby-prompt ()
"Returns a string (may be empty) based on the current Ruby Virtual Environment."
(let* ((executable "~/.rvm/bin/rvm-prompt")
(command (concat executable "v g")))
(when (file-exists-p executable)
(let* ((results (shell-command-to-string executable))
(cleaned (string-trim results))
(gem (propertize "\xe92b" 'face `(:family "alltheicons"))))
(when (and cleaned (not (equal cleaned "")))
(s-replace "ruby-" gem cleaned))))))
(defun python-prompt ()
"Returns a string (may be empty) based on the current Python
Virtual Environment. Assuming the M-x command: `pyenv-mode-set'
has been called."
(when (fboundp #'pyenv-mode-version)
(let ((venv (pyenv-mode-version)))
(when venv
(concat
(propertize "\xe928" 'face `(:family "alltheicons"))
(pyenv-mode-version))))))
#+END_SRC
Now tie it all together with a prompt function can color each of the
prompts components.
#+BEGIN_SRC emacs-lisp
(defun eshell/eshell-local-prompt-function ()
"A prompt for eshell that works locally (in that is assumes
that it could run certain commands) in order to make a prettier,
more-helpful local prompt."
(interactive)
(let* ((pwd (eshell/pwd))
(directory (split-directory-prompt
(pwd-shorten-dirs
(pwd-replace-home pwd))))
(parent (car directory))
(name (cadr directory))
(branch (curr-dir-git-branch-string pwd))
(ruby (when (not (file-remote-p pwd)) (ruby-prompt)))
(python (when (not (file-remote-p pwd)) (python-prompt)))
(dark-env (eq 'dark (frame-parameter nil 'background-mode)))
(for-bars `(:weight bold))
(for-parent (if dark-env `(:foreground "dark orange") `(:foreground "blue")))
(for-dir (if dark-env `(:foreground "orange" :weight bold)
`(:foreground "blue" :weight bold)))
(for-git `(:foreground "green"))
(for-ruby `(:foreground "red"))
(for-python `(:foreground "#5555FF")))
(concat
(propertize "⟣─ " 'face for-bars)
(propertize parent 'face for-parent)
(propertize name 'face for-dir)
(when branch
(concat (propertize " ── " 'face for-bars)
(propertize branch 'face for-git)))
(when ruby
(concat (propertize " ── " 'face for-bars)
(propertize ruby 'face for-ruby)))
(when python
(concat (propertize " ── " 'face for-bars)
(propertize python 'face for-python)))
(propertize "\n" 'face for-bars)
(propertize (if (= (user-uid) 0) " #" " $") 'face `(:weight ultra-bold))
;; (propertize " └→" 'face (if (= (user-uid) 0) `(:weight ultra-bold :foreground "red") `(:weight ultra-bold)))
(propertize " " 'face `(:weight bold)))))
(setq-default eshell-prompt-function #'eshell/eshell-local-prompt-function)
#+END_SRC
Turn off the default prompt, otherwise, it won't use ours:
#+BEGIN_SRC emacs-lisp
(setq eshell-highlight-prompt nil)
#+END_SRC
Here is the result:
[[http://imgur.com/nkpwII0.png]]