(Emacs/elisp|config)+new package that generates a mode-line

Using left, centre and right segments generates a mode line with
padded strings that actually achieves this.
This commit is contained in:
2024-06-30 01:15:07 +01:00
parent 9d327e4f70
commit 12b62f7cea
2 changed files with 135 additions and 81 deletions

View File

@@ -293,93 +293,58 @@ the borders for Emacs.
(fringe-mode 0))
#+end_src
** Mode line
The mode line is a little bar at the bottom of the buffer, just above
the minibuffer (where you do completions). It can store quite
The mode line is the little bar at the bottom of the buffer, just
above the minibuffer (where you do completions). It can store quite
literally anything, but generally stuff like the buffer name, file
type, column and line info, etc is put there.
The default mode-line is just... disgusting. It displays information
in an unintelligible format that you just have to learn and seems to
smash together a bunch of information without much care for ordering.
Most heartbreaking is that any mode can just insert new information
onto the mode-line without any purview, which can be really annoying.
It's also very overstimulating.
in an unintelligible format and seems to smash together a bunch of
information without much care for ordering. Most heartbreaking is
that any mode can just insert new information onto the mode-line
without any purview, which can be really annoying. It's also very
overstimulating.
Here I define a "nicer" (imo) mode-line-format which contains just the
information I need to know what that buffer does. It also looks a bit
more aesthetically pleasing from being centred along the window.
*** A better evil state tag
[[*Evil][Evil]], defined later, has a mode-line-tag for
mode-line-format. It's not awful but not exactly amazing either. So
I'm defining a little function which makes the tag for me
I've got a custom Emacs lisp package
([[file:elisp/better-mode-line.el][here]]) which sets up the default
mode line as a set of 3 segments: left, centre and right. It pads out
the mode line to achieve this.
#+begin_src emacs-lisp
(defun +mode-line/evil-state ()
"Returns either the empty string if no evil-state is defined or
the first character of the evil state capitalised"
(with-eval-after-load "evil"
(if (bound-and-true-p evil-state)
(upcase
(substring
(format "%s"
evil-state)
0 1))
"")))
#+end_src
*** +mode-line/format
Here I declare a new variable ~+mode-line/format~ which contains the
usual contents for ~mode-line-format~. Looking at the
[[info:elisp#Mode Line Top][info page]] for the mode-line, it's
essentially a list of either format strings (specially defined by
mode-line), variables or special forms. The only special form I use
here is ~:eval~ which evaluates the following expression every time
the mode-line is constructed.
#+begin_src emacs-lisp
(defvar +mode-line/format
'("%l:%c " ;; Line and column
"%p" ;; %into file
("[" ;; evil state
(:eval (+mode-line/evil-state))
"] ")
"%+" ;; Buffer state (changed or not)
"%b" ;; Buffer name
("(" ;; Major mode
(:eval (format "%s" major-mode))
") ")
"%I " ;; Buffer size (in bytes)
(:eval (if (project-current) ;; Name of current project (if any)
(project-name
(project-current))))
(vc-mode vc-mode) ;; Git branch (if any)
" "
(:eval ;; LSP information
(with-eval-after-load "eglot"
(if eglot--managed-mode
(eglot--mode-line-format))))
mode-line-misc-info ;; Any other information
)
"General format of mode line")
#+end_src
*** Left padding for the mode line
Here's the main logic for centring the entire mode-line. Essentially
just generate a string with enough spaces that the mode-line is in the
exact centre.
#+begin_src emacs-lisp
(defun +mode-line/left-padding ()
"Returns a string of spaces which will centre the mode-line if put
to the left of it."
(let* ((mode-line-size (length (format-mode-line +mode-line/format)))
(string-size (/ (- (window-width) mode-line-size) 2)))
;; ?\s means a whitespace character (why not #\Space Stallman?!)
(make-string string-size ?\s)))
#+end_src
*** mode-line-format
Put the left padded string and the rest of the format together to get
a nice little mode-line.
#+begin_src emacs-lisp
(setq-default mode-line-format
`((:eval (+mode-line/left-padding))
,@+mode-line/format))
(use-package better-mode-line
:load-path "elisp/"
:demand t
:init
(setq +better-mode-line/left-segment ;; LEFT SEGMENT
'("%l:%c" ;; Line and column count
" "
"%p" ;; Percentage into buffer
("[" ;; Evil state
(:eval
(+better-mode-line/evil-state))
"]"))
+better-mode-line/centre-segment ;; CENTRE SEGMENT
'("%+" ;; Buffer state (changed or not)
"%b" ;; Buffer name
("(" ;; Major mode
(:eval (format "%s" major-mode))
")")
" "
"%I" ;; Buffer size (in bytes)
)
+better-mode-line/right-segment ;; RIGHT SEGMENT
'((:eval (if (project-current) ;; Name of current project (if any)
(project-name
(project-current))))
(vc-mode vc-mode) ;; Git branch (if any)
" "
(:eval ;; LSP information
(with-eval-after-load "eglot"
(if eglot--managed-mode
(eglot--mode-line-format))))
mode-line-misc-info ;; Any other information
))
:config
(+better-mode-line/setup-mode-line))
#+end_src
** Mouse
Who uses a mouse? 🤮

View File

@@ -0,0 +1,89 @@
;;; better-mode-line.el --- A better mode-line system designed by me -*- lexical-binding: t; -*-
;; Copyright (C) 2024 Aryadev Chavali
;; Author: Aryadev Chavali <aryadev@aryadevchavali.com>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; There are 3 lists for the left, centre and right of the mode-line. They're
;; the same as mode-line-format in terms of general schema as they're fed
;; directly into that variable. Padding strings are automatically generated
;; based on these segments so be sure to set these.
;;; Code:
(defun +better-mode-line/evil-state ()
"Returns either the empty string if no evil-state is defined or
the first character of the evil state capitalised"
(with-eval-after-load "evil"
(if (bound-and-true-p evil-state)
(upcase
(substring
(format "%s"
evil-state)
0 1))
"")))
(defvar +better-mode-line/left-segment nil
"List of elements that are placed on the left of the mode-line")
(defvar +better-mode-line/centre-segment nil
"List of elements that should be on the centre of the mode-line")
(defvar +better-mode-line/right-segment nil
"List of elements that should be on the right of the mode-line")
(defconst +better-mode-line/--minimum-padding 4
"Minimum size of padding string.")
(defun +better-mode-line/--left->centre-padding ()
"Returns a string which pads the centre segment perfectly relative
to the left segment."
(let* ((left-segment-size (length (format-mode-line +better-mode-line/left-segment)))
(centre-segment-size (length (format-mode-line +better-mode-line/centre-segment)))
(padding-size (- (/ (window-width) 2) (/ centre-segment-size 2) left-segment-size)))
(make-string (if (< padding-size +better-mode-line/--minimum-padding)
+better-mode-line/--minimum-padding
padding-size)
?\s)))
(defun +better-mode-line/--centre->right-padding ()
"Returns a string which pads the right segment perfectly relative
to the centre segment"
(let* ((centre-segment-size (length (format-mode-line +better-mode-line/centre-segment)))
(right-segment-size (length (format-mode-line +better-mode-line/right-segment)))
(padding-size (- (/ (window-width) 2) (/ centre-segment-size 2) right-segment-size)))
(make-string (if (< padding-size +better-mode-line/--minimum-padding)
+better-mode-line/--minimum-padding
padding-size)
?\s)))
(defun +better-mode-line/setup-mode-line ()
"Call this to setup the mode-line when:
- first loading the package.
- segments are updated."
(setq-default mode-line-format
`(,@+better-mode-line/left-segment
(:eval (+better-mode-line/--left->centre-padding))
,@+better-mode-line/centre-segment
(:eval (+better-mode-line/--centre->right-padding))
,@+better-mode-line/right-segment)))
(provide 'better-mode-line)
;;; better-mode-line.el ends here