The PowerLine project can really clean up the mode line, but I’m also able to create my own “theme” in order to remove many of the minor modes that don’t really help.
(use-package powerline
:ensure t
:init
(setq powerline-default-separator 'curve
powerline-default-separator-dir (quote (left . right))
powerline-height 28
powerline-display-buffer-size nil
powerline-display-hud nil
powerline-display-mule-info nil
powerline-gui-use-vcs-glyph t
powerline-inactive1 '((t (:background "grey11" :foreground "#c5c8c6")))
powerline-inactive2 '((t (:background "grey20" :foreground "#c5c8c6")))))
Let’s make the modification status a bit more useful… and iconic:
(defun powerline-get-icon (name alt-sym help-message)
"Returns a propertized icon if available, otherwise, returns ALT-SYM."
(propertize alt-sym 'help-echo help-message))
(defun powerline-modified ()
(condition-case ex
(let ((state (vc-git-state (buffer-file-name))))
(cond ((buffer-modified-p) (powerline-get-icon "pencil" "✦" "Modified buffer"))
((eq state 'edited) (powerline-get-icon "pencil" "✦" "Modified buffer, unregistered changes"))
((eq state 'unregistered) (powerline-get-icon "question" "❓" "Unregistered file in VCS"))
((eq state 'missing) (powerline-get-icon "exclamation" "⁈" "File exists only in VCS, not on the hard disk"))
((eq state 'ignored) (powerline-get-icon "ban" "♟" "Ignored file in VCS"))
((eq state 'added) (powerline-get-icon "plus" "➕" "File will be registered in VCS in the next commit"))
(t " ")))
(error (powerline-get-icon "exclamation" "⁈" (car ex)))))
In order to check if the current mode matches a particular mode, we need to do something like:
(defun is-mode-p (mode)
"Predicate to return `true' if the current buffer's major mode matches the requested MODE."
(buffer-local-value 'major-mode (current-buffer))
(eq major-mode mode))
Let’s display the current Ruby version and Gemset, but only if the buffer’s mode is set to Ruby:
(defun current-ruby-mode-line ()
"Display the Ruby version and Gemset (using RVM) if `ruby-mode' is enabled. Nil otherwise."
(ignore-errors
(when (is-mode-p 'ruby-mode)
(concat (replace-regexp-in-string "ruby-" "" rvm--current-ruby)
(when rvm--current-gemset
" 💎 ") rvm--current-gemset))))
(defun current-ruby-mode-line ()
"Display the Ruby version and Gemset (using RVM) if `ruby-mode' is enabled. Nil otherwise."
(ignore-errors
(when (is-mode-p 'ruby-mode)
(concat (replace-regexp-in-string "ruby-" "" rvm--current-ruby)
(propertize " \xe92b " ; "\xe92a"
'face `(:family "all-the-icons" :height 1.2)
'display '(raise -0.1))
(when rvm--current-gemset
rvm--current-gemset)))))
Display the current Python virtual environment, using pyenv
:
(defun current-python-mode-line ()
"Display the Python virtual environment and version if `python-mode' is enabled. Nil otherwise."
(ignore-errors
(when (and (is-mode-p 'python-mode) (pyenv-mode-version))
(concat "🐍" (pyenv-mode-version)))))
(defun current-python-mode-line ()
"Display the Python virtual environment and version if `python-mode' is enabled. Nil otherwise."
(ignore-errors
(when (and (is-mode-p 'python-mode) (pyenv-mode-version))
(concat
(propertize "\xe928 "
'face `(:family "all-the-icons")
'display '(raise -0.1))
(pyenv-mode-version)))))
Put everything together, where we will either display the Ruby, Python, or if no particular language, display the eyebrowse:
(defun powerline-lang-version ()
"docstring"
(or (current-python-mode-line)
(current-ruby-mode-line)
(when (derived-mode-p 'prog-mode)
which-func-format)
" "))
Clean up the project location:
(defun powerline-project-vc ()
(ignore-errors
(when (projectile-project-p)
(propertize (projectile-project-name)
'help-echo (format "Base: %s"
(projectile-project-root))))))
While the use-package
project diminishes most minor modes, I still
have one left:
(defun trim-minor-modes (s)
(replace-regexp-in-string "ARev" "↺" s))
Change the bottom right corner of the mode line to not only display the textual details of the evil state, but also to colorize it to make it more obvious.
(defface powerline-evil-insert-face
'((((class color))
(:background "green" :foreground "black" :weight bold))
(t (:weight bold)))
"face to fontify mode-line for Evil's `insert' state"
:group 'powerline)
(defface powerline-evil-normal-face
'((((class color))
(:background "red" :foreground "black" :weight bold))
(t (:weight bold)))
"face to fontify mode-line for Evil's `normal' state"
:group 'powerline)
(defface powerline-evil-visual-face
'((((class color))
(:background "yellow" :foreground "black" :weight bold))
(t (:weight bold)))
"face to fontify mode-line for Evil's `visual' state"
:group 'powerline)
(defface powerline-evil-motion-face
'((((class color))
(:background "blue" :foreground "black" :weight bold))
(t (:weight bold)))
"face to fontify mode-line for Evil's `motion' state"
:group 'powerline)
;; (defface powerline-evil-emacs-face
;; '((((class color))
;; (:background "blue violet" :foreground "black" :weight bold))
;; (t (:weight bold)))
;; "face to fontify mode-line for Evil's `emacs' state"
;; :group 'powerline)
(defun powerline-evil-face (active)
(let ((face (intern (concat "powerline-evil-" (symbol-name evil-state) "-face"))))
(cond ((equal (symbol-name evil-state) "emacs") 'mode-line)
((and active (facep face))
face)
(active 'mode-line)
(t 'powerline-inactive1))))
(defun powerline-evil-state ()
"Displays *my* version of displaying the evil state."
(case evil-state
('normal " Ⓝ")
('insert " Ⓘ")
('visual " Ⓥ")
('motion " Ⓜ")
(t " Ⓔ")))
(defpowerline powerline-evil
(powerline-evil-state))
Let’s put everything together into our mode-line:
(setq-default mode-line-format
'("%e"
(:eval
(let* ((active (powerline-selected-window-active))
(mode-line-buffer-id (if active 'mode-line-buffer-id 'mode-line-buffer-id-inactive))
(mode-line (if active 'mode-line 'mode-line-inactive))
(face1 (if active 'powerline-active1 'powerline-inactive1))
(face2 (if active 'powerline-active2 'powerline-inactive2))
(eface (powerline-evil-face active))
(separator-left (intern (format "powerline-%s-%s"
(powerline-current-separator)
(car powerline-default-separator-dir))))
(separator-right (intern (format "powerline-%s-%s"
(powerline-current-separator)
(cdr powerline-default-separator-dir))))
(lhs (list
;; Section 1: File status and whatnot
(powerline-raw (powerline-modified) face1 'l)
;; (powerline-buffer-size mode-line 'l)
(powerline-raw mode-line-client face1 'l)
(powerline-raw " " face1 'l)
;; Section 2: ( Buffer Name ) ... bright
(funcall separator-right face1 mode-line)
(powerline-buffer-id mode-line-buffer-id 'l)
(powerline-raw " " mode-line)
(funcall separator-left mode-line face1)
;; Section 3: Git ... dark
(powerline-narrow face1 'l)
(powerline-raw " " face1)
(powerline-raw (powerline-project-vc) face1 'l)
(powerline-vc face1 'l)))
(rhs (list (powerline-raw global-mode-string face1 'r)
;; Section 1: Language-specific ... optional
(powerline-raw (powerline-lang-version) face1 'r)
;; Section 2: Function Name or Row Number
(funcall separator-right mode-line eface)
(powerline-raw (powerline-evil-state) eface 'r)
(powerline-raw "%4l:%3c" eface 'r)))
(center (list (powerline-raw " " face1)
(funcall separator-left face1 face2)
(when (and (boundp 'erc-track-minor-mode) erc-track-minor-mode)
(powerline-raw erc-modified-channels-object face2 'l))
(powerline-major-mode face2 'l)
(powerline-process face2)
(powerline-raw " :" face2)
(powerline-minor-modes face2 'l)
(powerline-raw " " face2)
(funcall separator-right face2 face1))))
(concat (powerline-render lhs)
(powerline-fill-center face1 (/ (powerline-width center) 2.0))
(powerline-render center)
(powerline-fill face1 (powerline-width rhs))
(powerline-render rhs))))))
Make sure that we can simply require
this library.
(provide 'init-mode-line)
Before you can build this on a new system, make sure that you put
the cursor over any of these properties, and hit: C-c C-c