init
3 files changed, 274 insertions(+), 0 deletions(-)

A => README.org
A => screenshot.png
A => xc-look-mode-line.el
A => README.org +16 -0
@@ 0,0 1,16 @@ 
+* xaltsc's config mode line
+
+[[./screenshot.png]]
+
+A simple vim-like mode-line with special faces for evil.
+
+Names of the faces come from [[https://github.com/nvim-lualine/lualine.nvim][Lualine]].
+
+The default theme is based off [[https://carbondesignsystem.com/guidelines/color/overview][IBM's Carbon Design Language]].
+
+** Usage
+
+#+BEGIN_SRC emacs-lisp
+  (require 'xc-look-mode-line)
+  (setq-default mode-line-format xc-line/mode-line)
+#+END_SRC

          
A => screenshot.png +0 -0

        
A => xc-look-mode-line.el +258 -0
@@ 0,0 1,258 @@ 
+;; -*- lexical-binding: t; -*-
+
+;; copyright xaltsc 2022
+;; Default colours based off IBM's Carbon Design Language
+
+(defgroup xc-line nil
+  "lel"
+  :group 'mode-line)
+
+(defface xc-line-part-a-normal
+   '((t (:background "#0043ce"
+         :foreground "#f2f4f8"
+         :bold t :extend t)))
+   "Face for the leftmost part when Evil is in normal mode"
+   :group 'xc-line)
+(defface xc-line-part-a-insert
+   '((t (:background "#f1c21b"
+         :foreground "#21272a"
+         :bold t)))
+   "Face for the leftmost part when Evil is in insert mode"
+   :group 'xc-line)
+(defface xc-line-part-a-visual
+   '((t (:background "#007d79"
+         :foreground "#f2f4f8"
+         :bold t)))
+  "Face for the leftmost part when Evil is in visual mode"
+   :group 'xc-line)
+(defface xc-line-part-a-replace
+   '((t (:background "#da1e28"
+         :foreground "#f2f4f8"
+         :bold t)))
+  "Face for the leftmost part when Evil is in replace mode"
+   :group 'xc-line)
+(defface xc-line-part-a-operator
+   '((t (:background "#21272a"
+         :foreground "#f2f4f8"
+         :bold t)))
+  "Face for the leftmost part when Evil is in operator mode"
+   :group 'xc-line)
+(defface xc-line-part-a-emacs
+   '((t (:background "#8a3ffc"
+         :foreground "#f2f4f8"
+         :bold t)))
+  "Face for the leftmost part when Evil is in Emacs mode"
+   :group 'xc-line)
+(defface xc-line-part-a-motion
+   '((t (:inherit xc-line-part-a-operator)))
+  "Face for the leftmost part when Evil is in motion mode"
+   :group 'xc-line)
+(defface xc-line-part-b
+   '((t (:background "#c1c7cd" :foreground "#343a3f")))
+  "Face for the second leftmost part"
+   :group 'xc-line)
+(defface xc-line-part-c
+   '((t (:foreground "#4d5558")))
+  "Face for the third leftmost part"
+   :group 'xc-line)
+
+(defface xc-line-part-x
+   '((t (:inherit (xc-line-part-c))))
+  "Face for the third rightmost part"
+   :group 'xc-line)
+(defface xc-line-part-y
+   '((t (:inherit (xc-line-part-b))))
+  "Face for the second rightmost part"
+   :group 'xc-line)
+
+(defface xc-line-part-z-normal
+   '((t (:inherit (xc-line-part-a-normal))))
+  "Face for the rightmost part when Evil is in normal mode"
+   :group 'xc-line)
+(defface xc-line-part-z-insert
+   '((t (:inherit (xc-line-part-a-insert))))
+  "Face for the rightmost part when Evil is in insert mode"
+   :group 'xc-line)
+(defface xc-line-part-z-visual
+   '((t (:inherit (xc-line-part-a-visual))))
+  "Face for the rightmost part when Evil is in visual mode"
+   :group 'xc-line)
+(defface xc-line-part-z-replace
+   '((t (:inherit (xc-line-part-a-replace))))
+  "Face for the rightmost part when Evil is in replace mode"
+   :group 'xc-line)
+(defface xc-line-part-z-operator
+   '((t (:inherit (xc-line-part-a-operator))))
+  "Face for the rightmost part when Evil is in operator mode"
+   :group 'xc-line)
+(defface xc-line-part-z-emacs
+   '((t (:inherit (xc-line-part-a-emacs))))
+  "Face for the rightmost part when Evil is in Emacs mode"
+   :group 'xc-line)
+(defface xc-line-part-z-motion
+   '((t (:inherit (xc-line-part-a-motion))))
+  "Face for the rightmost part when Evil is in motion mode"
+   :group 'xc-line)
+(defface xc-line-container
+   '((t (:box (:line-width (-1 . 7)
+               :style flat-button))))
+  "Additional face applied to all the components of the mode line"
+  :group 'xc-line)
+
+
+(defcustom xc-line-separator " · "
+   "Divider string between segments in a part")
+
+(defcustom xc-line-modified "+"
+   "Icon for when the buffer has been modified")
+
+(defcustom xc-line-readonly ""
+    "Icon for when the buffer is read-only")
+
+(require 's)
+(require 'dash)
+
+(defun --escape-percent-construct (string)
+   (s-replace "%" "%%" string))
+
+;(defun --merge-face-in-list (sexp face-to-merge)
+;  (let ((head (car sexp)))
+;    (if (eq :propertize head)
+;        (let* ((copied-sexp (-copy sexp))
+;               (face-field (plist-get copied-sexp 'face))
+;;          (if face-field
+;              (cond
+;               ((and (listp face-field) (not (memq face-to-merge face-field)))
+;                (plist-put copied-sexp 'face
+;                    (append face-field (list face-to-merge))
+;               ((not (or (listp face-field) (eq face-field face-to-merge)))
+;                (plist-put copied-sexp 'face (list face-field face-to-merge))
+;               (t copied-sexp)
+;              (plist-put copied-sexp 'face face-to-merge)
+;     sexp))
+
+;(defun --merge-face-properties (sexp face-to-merge)
+;  (if (proper-list-p sexp)
+;      (mapcar (-cut --merge-face-properties <> face-to-merge)
+;              (--merge-face-in-list sexp face-to-merge)
+;      sexp)))
+;
+(defun xc-line/centre-space (right-length)
+   "Creates the space for the centre of the mode line"
+   `(:propertize " " display (space :align-to (- right ,right-length))))
+
+(defun xc-line/format-part-expand-symbols (sym)
+    "Expands symbols when they are bound"
+    (if (and (symbolp sym) (boundp sym))
+        (symbol-value sym)
+        sym))
+
+(defun format-and-escape (format-spec)
+   (--escape-percent-construct (format-mode-line format-spec)))
+
+(defun xc-line/format-part (part face &optional extra-right-space-p)
+  "Formats `part' of the mode line while adding the face `face' at the end of
+   the face text property of its components. Adds an extra space at the end if
+   `extra-right-space-p' is non-nil.
+
+   Returns the resulting string."
+  (let* ((part-elt (if (and (listp part) (eq (car part) :multi))
+                       (-interpose xc-line-separator
+                                   (mapcar #'xc-line/format-part-expand-symbols
+                                           (cdr part)))
+                       part))
+         (formatted-part (format-and-escape
+                          (list " " part-elt " "
+                               (and extra-right-space-p " "))))
+         (f-p-length (length formatted-part)))
+    (add-face-text-property 0 f-p-length face t formatted-part)
+    formatted-part))
+
+;    (part-w-face `(:eval (--merge-face-properties ',part-elt ',face)))
+;    `(:propertize (" " ,part-w-face " " ,)
+;            face ,face))
+
+(defun xc-line/get-face-for-mode (seg-identifier)
+  "Gets the correct face for the segment `seg-identifier' according to the
+   current `evil-state'"
+
+  (let ((face-string (format "xc-line-part-%s-%s" seg-identifier evil-state)))
+    (intern face-string)))
+
+(defun xc-line/format-left (a b c)
+  "Makes the left part of the mode line"
+  (let ((a-propd (xc-line/format-part a (xc-line/get-face-for-mode 'a)))
+        (b-propd (xc-line/format-part b 'xc-line-part-b))
+        (c-propd (xc-line/format-part c 'xc-line-part-c)))
+    (list a-propd b-propd c-propd)))
+
+(defun xc-line/format-right (x y z)
+  "Makes the right part of the mode line"
+  (let ((x-propd (xc-line/format-part x 'xc-line-part-x))
+        (y-propd (xc-line/format-part y 'xc-line-part-y))
+        (z-propd (xc-line/format-part z (xc-line/get-face-for-mode 'z) t)))
+    (list x-propd y-propd z-propd)))
+
+(defun xc-line/format (left right)
+  "Makes the mode line format"
+
+  (let* ((middle (xc-line/centre-space
+                  (- (length (format-mode-line right)) 1)))
+         (mode-line-string (format-and-escape (list left middle right)))
+         (mls-length (length mode-line-string)))
+     (add-face-text-property 0 mls-length 'xc-line-container t mode-line-string)
+     mode-line-string))
+
+(setq xc-line/seg-evil
+  '(:eval (s-pad-right 3 " " (plist-get '(normal "NOR"
+                                          insert "INS"
+                                          visual "VIS"
+                                          operator "OP"
+                                          replace "REP"
+                                          motion "MOT"
+                                          emacs "EMX")
+                                evil-state))))
+
+(defun xc-line/seg-buffer-status ()
+   (let ((modified (if (buffer-modified-p) xc-line-modified ""))
+         (readonly (if buffer-read-only    xc-line-readonly "")))
+     (format "%s%s" modified readonly)))
+
+(setq xc-line/seg-buffer
+   '("%b" (:eval (xc-line/seg-buffer-status))))
+
+(setq xc-line/seg-major-mode
+   'mode-name)
+
+(setq xc-line/seg-minor-modes
+   'minor-mode-alist)
+
+(defun --xc-line/try-trim (obj)
+   (let ((maybe-str (or (and (symbolp obj) (boundp obj) (symbol-value obj))
+                        obj)))
+     (if (stringp maybe-str) (s-trim maybe-str) maybe-str)))
+
+(setq xc-line/seg-misc-info
+      '(:eval (mapcar #'--xc-line/try-trim global-mode-string)))
+
+
+(setq xc-line/seg-progress
+      '(:eval (downcase (--escape-percent-construct
+                            (format-mode-line '(-3 "%p"))))))
+
+(setq xc-line/seg-position
+      '(:eval (--escape-percent-construct
+                  (s-pad-left 6 " " (format-mode-line "%l:%c")))))
+
+(defcustom xc-line/mode-line
+    '(:eval (xc-line/format
+             (xc-line/format-left xc-line/seg-evil
+                                  xc-line/seg-misc-info
+                                  xc-line/seg-buffer)
+             (xc-line/format-right xc-line/seg-minor-modes
+                                   xc-line/seg-progress
+                                   (list :multi xc-line/seg-position
+                                                xc-line/seg-major-mode))))
+  "xaltsc's config mode-line")
+
+(provide 'xc-look-mode-line)