diff options
Diffstat (limited to 'emacs/libs')
-rw-r--r-- | emacs/libs/center-helm-buffer.el | 55 | ||||
-rw-r--r-- | emacs/libs/lambda-line.el | 1825 | ||||
-rw-r--r-- | emacs/libs/minad.el | 89 | ||||
m--------- | emacs/libs/nano-emacs | 0 | ||||
-rw-r--r-- | emacs/libs/penumbra-theme.el | 512 | ||||
m--------- | emacs/libs/slime | 0 | ||||
-rw-r--r-- | emacs/libs/utils.el | 17 |
7 files changed, 2498 insertions, 0 deletions
diff --git a/emacs/libs/center-helm-buffer.el b/emacs/libs/center-helm-buffer.el new file mode 100644 index 0000000..85f8438 --- /dev/null +++ b/emacs/libs/center-helm-buffer.el @@ -0,0 +1,55 @@ +;;; package --- Center the helm buffer to the emacs window +;;; Commentary: + +;;; Code: + +(defun my-helm-display-frame-center (buffer &optional resume) + "Display `BUFFER' in a separate frame which centered in parent frame. + +I don't know what's RESUME." + (if (not (display-graphic-p)) + ;; Fallback to default when frames are not usable. + (helm-default-display-buffer buffer) + (setq helm--buffer-in-new-frame-p t) + (let* ((parent (selected-frame)) + (frame-pos (frame-position parent)) + (parent-left (car frame-pos)) + (parent-top (cdr frame-pos)) + (width (/ (frame-width parent) 2)) + (height (/ (frame-height parent) 3)) + tab-bar-mode + (default-frame-alist + (if resume + (buffer-local-value 'helm--last-frame-parameters + (get-buffer buffer)) + `((parent . ,parent) + (width . ,width) + (height . ,height) + (undecorated . ,helm-use-undecorated-frame-option) + (left-fringe . 0) + (right-fringe . 0) + (tool-bar-lines . 0) + (line-spacing . 0) + (desktop-dont-save . t) + (no-special-glyphs . t) + (inhibit-double-buffering . t) + (tool-bar-lines . 0) + (left . ,(+ parent-left (/ (* (frame-char-width parent) (frame-width parent)) 4))) + (top . ,(+ parent-top (/ (* (frame-char-width parent) (frame-height parent)) 2))) + (title . "Helm") + (vertical-scroll-bars . nil) + (menu-bar-lines . 0) + (fullscreen . nil) + (visible . ,(null helm-display-buffer-reuse-frame)) + ;; (internal-border-width . ,(if IS-MAC 1 0)) + ))) + display-buffer-alist) + (set-face-background 'internal-border (face-foreground 'default)) + (helm-display-buffer-popup-frame buffer default-frame-alist)) + (helm-log-run-hook 'helm-window-configuration-hook))) + +(setq helm-display-function 'my-helm-display-frame-center) + + +(provide 'center-helm-buffer) +;;; center-helm-buffer.el ends here diff --git a/emacs/libs/lambda-line.el b/emacs/libs/lambda-line.el new file mode 100644 index 0000000..acbd660 --- /dev/null +++ b/emacs/libs/lambda-line.el @@ -0,0 +1,1825 @@ +;;; lambda-line.el --- A custom status line -*- lexical-binding: t -*- + +;; Author: Colin McLear +;; Maintainer: Colin McLear +;; Version: 0.2.0 +;; Package-Requires: ((emacs "27.1")) +;; Homepage: https://github.com/Lambda-Emacs/lambda-line +;; Keywords: mode-line faces + +;; This file is NOT part of GNU Emacs + +;; 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: + +;; lambda-line is a minimal, though opinionated, status-line (i.e. in Emacs the +;; information display either in the mode-line and/or header-line) for use as +;; either header or footer in a buffer. The structure of the status-line takes +;; the following form: [ status | name (primary) tertiary | secondary ] + +;; Usage: M-x lambda-line-mode + +;;; Code: + +(require 'face-remap) +(require 'cl-lib) +(require 'all-the-icons) + +;;;; Group + +(defgroup lambda-line nil + "lambda-line group" + :group 'mode-line + :link '(url-link :tag "Homepage" "https://github.com/Lambda-Emacs/lambda-line")) + +;;;; Custom Variable Settings + +(defcustom lambda-line-window-width-limit 0.25 + "The limit of the window width. +If `window-width' is smaller than the limit, some information won't be +displayed. It can be an integer or a float number. `nil' means no limit." + :type '(choice integer + float + (const :tag "Disable" nil)) + :group 'lambda-line) + +(defcustom lambda-line-position 'bottom + "Default modeline position (top or bottom)" + :type '(choice + (const :tag "Nil" nil) + (const :tag "Top" top) + (const :tag "Bottom" bottom)) + :group 'lambda-line) + +(defcustom lambda-line-prefix t + "Include a prefix icon to indicate buffer status in the status-line." + :type 'boolean + :group 'lambda-line) + +(defcustom lambda-line-prefix-padding t + "Include prefix padding." + :type 'boolean + :group 'lambda-line) + +(defcustom lambda-line-user-mode nil + "User supplied mode to be evaluated for modeline." + :type '(choice (const nil) function) + :group 'lambda-line) + +(defcustom lambda-line-abbrev nil + "If t then show abbreviated mode symbol in modeline. +Default is nil. To change the values of the major-mode symbols +see the value of `lambda-line-abbrev-alist'" + :group 'lambda-line + :type 'boolean) + +(defcustom lambda-line-git-diff-mode-line t + "If t then show diff lines in modeline." + :group 'lambda-line + :type 'boolean) + +(defcustom lambda-line-vc-symbol "" + "Symbol to use in buffers visiting files under version control" + :group 'lambda-line + :type 'string) + +;; Visual Bell +(defcustom lambda-line-visual-bell t + "If t then use `lambda-line-visual-bell'." + :group 'lambda-line + :type 'boolean) + +;; Invert status faces +;; This make lambda-line look more like nano-modeline +(defcustom lambda-line-status-invert nil + "If t then invert the colors to get a box effect for the corner of the status line." + :group 'lambda-line + :type 'boolean) + +;; Mode line symbols +(defcustom lambda-line-gui-ro-symbol " ⨂" ;; ⬤◯⨂ + "Modeline gui read-only symbol." + :group 'lambda-line + :type 'string) + +(defcustom lambda-line-gui-mod-symbol " ⬤" ;; ⨀⬤ + "Modeline gui modified symbol." + :group 'lambda-line + :type 'string) + +(defcustom lambda-line-gui-rw-symbol " ◯" ; λ ◉ ◎ ⬤◯ + "Modeline gui read-write symbol." + :group 'lambda-line + :type 'string) + +(defcustom lambda-line-tty-ro-symbol " 𝛌 " + "Modeline tty read-only symbol." + :group 'lambda-line + :type 'string) + +(defcustom lambda-line-tty-mod-symbol " 𝛌 " + "Modeline tty read-only symbol." + :group 'lambda-line + :type 'string) + +(defcustom lambda-line-tty-rw-symbol " 𝛌 " + "Modeline tty read-write symbol." + :group 'lambda-line + :type 'string) + +(defcustom lambda-line-truncate-value 30 + "Value of modeline truncate-length function." + :group 'lambda-line + :type 'integer) + +(defcustom lambda-line-hspace " " + "Space adjustment for right end of modeline." + :type 'string + :group 'lambda-line) + +(defcustom lambda-line-space-top +.35 + "Space adjustment for top of status-line. +Positive is upwards" + :type 'float + :group 'lambda-line) + +(defcustom lambda-line-space-bottom -.5 + "Space adjustment for bottom of status-line. +Negative is downwards." + :type 'float + :group 'lambda-line) + +(defcustom lambda-line-symbol-position .067 + "Space adjustment for symbol in status-line. +Negative is downwards." + :type 'float + :group 'lambda-line) + +(defcustom lambda-line-syntax t + "Show flycheck/flymake report in status-line." + :type 'boolean + :group 'lambda-line) + +(defcustom lambda-line-flycheck-label "Issues: " + "Show with flycheck/flymake issues count." + :type 'string + :group 'lambda-line) + +(defcustom lambda-line-icon-time nil + "When set to non-nil show the time as an icon clock. +Time info is only shown `display-time-mode' is non-nil" + :type 'boolean + :group 'lambda-line) + +(defcustom lambda-line-time-day-and-date-format " %H:%M %Y-%m-%e " + "`format-time-string'." + :type 'string + :group 'lambda-line) + +(defcustom lambda-line-time-format " %H:%M " + "`format-time-string'." + :type 'string + :group 'lambda-line) + +(defcustom lambda-line-time-icon-format " %s" + "`format-time-string'." + :type 'string + :group 'lambda-line) + +(defcustom lambda-line-display-group-start "(" + "Modeline display group start indicator." + :group 'lambda-line + :type 'string) + +(defcustom lambda-line-display-group-end ")" + "Modeline display group end indicator." + :group 'lambda-line + :type 'string) + +(defcustom lambda-line-mode-formats + '(;; with :mode-p first + (imenu-list-mode :mode-p lambda-line-imenu-list-mode-p + :format lambda-line-imenu-list-mode) + (org-capture-mode :mode-p lambda-line-org-capture-mode-p + :format lambda-line-org-capture-mode + :on-activate lambda-line-org-capture-activate + :on-deactivate lambda-line-org-capture-deactivate) + (prog-mode :mode-p lambda-line-prog-mode-p + :format lambda-line-prog-mode + :on-activate lambda-line-prog-activate + :on-deactivate lambda-line-prog-deactivate) + (mu4e-dashboard-mode :mode-p lambda-line-mu4e-dashboard-mode-p + :format lambda-line-mu4e-dashboard-mode) + (messages-mode :mode-p lambda-line-messages-mode-p + :format lambda-line-messages-mode) + (message-mode :mode-p lambda-line-message-mode-p + :format lambda-line-message-mode) + (term-mode :mode-p lambda-line-term-mode-p + :format lambda-line-term-mode) + (vterm-mode :mode-p lambda-line-vterm-mode-p + :format lambda-line-term-mode) + (eshell-mode :mode-p lambda-line-eshell-mode-p + :format lambda-line-eshell-mode) + (buffer-menu-mode :mode-p lambda-line-buffer-menu-mode-p + :format lambda-line-buffer-menu-mode + :on-activate lambda-line-buffer-menu-activate + :on-deactivate lambda-line-buffer-menu-deactivate) + (calendar-mode :mode-p lambda-line-calendar-mode-p + :format lambda-line-calendar-mode + :on-activate lambda-line-calendar-activate + :on-deactivate lambda-line-calendar-deactivate) + (completion-list-mode :mode-p lambda-line-completion-list-mode-p + :format lambda-line-completion-list-mode) + (deft-mode :mode-p lambda-line-deft-mode-p + :format lambda-line-deft-mode) + (doc-view-mode :mode-p lambda-line-doc-view-mode-p + :format lambda-line-doc-view-mode) + (elfeed-search-mode :mode-p lambda-line-elfeed-search-mode-p + :format lambda-line-elfeed-search-mode + :on-activate lambda-line-elfeed-search-activate + :on-deactivate lambda-line-elfeed-search-deactivate) + (elfeed-show-mode :mode-p lambda-line-elfeed-show-mode-p + :format lambda-line-elfeed-show-mode) + (elpher-mode :mode-p lambda-line-elpher-mode-p + :format lambda-line-elpher-mode + :on-activate lambda-line-elpher-activate) + (help-mode :mode-p lambda-line-help-mode-p + :format lambda-line-help-mode) + (helpful-mode :mode-p lambda-line-helpful-mode-p + :format lambda-line-help-mode) + (info-mode :mode-p lambda-line-info-mode-p + :format lambda-line-info-mode + :on-activate lambda-line-info-activate + :on-deactivate lambda-line-info-deactivate) + (magit-mode :mode-p lambda-line-magit-mode-p + :format lambda-line-magit-mode) + (mu4e-compose-mode :mode-p lambda-line-mu4e-compose-mode-p + :format lambda-line-mu4e-compose-mode) + (mu4e-headers-mode :mode-p lambda-line-mu4e-headers-mode-p + :format lambda-line-mu4e-headers-mode) + (mu4e-loading-mode :mode-p lambda-line-mu4e-loading-mode-p + :format lambda-line-mu4e-loading-mode) + (mu4e-main-mode :mode-p lambda-line-mu4e-main-mode-p + :format lambda-line-mu4e-main-mode) + (mu4e-view-mode :mode-p lambda-line-mu4e-view-mode-p + :format lambda-line-mu4e-view-mode) + (org-agenda-mode :mode-p lambda-line-org-agenda-mode-p + :format lambda-line-org-agenda-mode) + + (org-clock-mode :mode-p lambda-line-org-clock-mode-p + :format lambda-line-org-clock-mode + :on-activate lambda-line-org-clock-activate + :on-deactivate lambda-line-org-clock-deactivate) + (pdf-view-mode :mode-p lambda-line-pdf-view-mode-p + :format lambda-line-pdf-view-mode) + (fundamental-mode :mode-p lambda-line-fundamental-mode-p + :format lambda-line-fundamental-mode) + (text-mode :mode-p lambda-line-text-mode-p + :format lambda-line-text-mode) + + ;; hooks only go last + (ein-notebook-mode :on-activate lambda-line-ein-notebook-activate + :on-deactivate lambda-line-ein-notebook-deactivate) + (esh-mode :on-activate lambda-line-esh-activate + :on-deactivate lambda-line-esh-deactivate) + (ispell-mode :on-activate lambda-line-ispell-activate + :on-deactivate lambda-line-ispell-deactivate) + (mu4e-mode :on-activate lambda-line-mu4e-activate + :on-deactivate lambda-line-mu4e-deactivate)) + + "Modes to be evalued for modeline. +KEY mode name, for reference only. Easier to do lookups and/or replacements. +:MODE-P the function to check if :FORMAT needs to be used, first one wins. +:ON-ACTIVATE and :ON-DEACTIVATE do hook magic on enabling/disabling the mode. +" + :type '(alist :key-type symbol + :value-type (plist :key-type (choice (const :mode-p) + (const :format) + (const :on-activate) + (const :on-deactivate)) + :value-type function)) + :group 'lambda-line) + +(defcustom lambda-line-mode-format-activate-hook nil + "Add hooks on activation of the mode. +This is for those modes that define their own status-line." + :type 'hook + :options '(turn-on-auto-fill flyspell-mode) + :group 'lambda-line) + +(defcustom lambda-line-mode-format-deactivate-hook nil + "Remove hooks on de-activation of the mode. +This is for those modes that define their own status-line." + :type 'hook + :options '(turn-on-auto-fill flyspell-mode) + :group 'lambda-line) + +(defcustom lambda-line-default-mode-format 'lambda-line-default-mode + "Default mode to evaluate. +This is if no match could be found in `lambda-lines-mode-formats'" + :type 'function + :group 'lambda-line) + +;;;; Faces +;;;;; Line Faces + +(defface lambda-line-active + '((t (:inherit (mode-line)))) + "Modeline face for active modeline." + :group 'lambda-line-active) + +(defface lambda-line-inactive + '((t (:inherit (mode-line-inactive)))) + "Modeline face for inactive line." + :group 'lambda-line-inactive) + +(defface lambda-line-hspace-active + '((t (:invisible t :family "Monospace" :inherit (mode-line)))) + "Face for vertical spacer in active line.") + +(defface lambda-line-hspace-inactive + '((t (:invisible t :family "Monospace" :inherit (mode-line-inactive)))) + "Face for vertical spacer in inactive line.") + +(defface lambda-line-active-name + '((t (:inherit (mode-line)))) + "Modeline face for active name element." + :group 'lambda-line-active) + +(defface lambda-line-inactive-name + '((t (:inherit (mode-line-inactive)))) + "Modeline face for inactive name element." + :group 'lambda-line-inactive) + +(defface lambda-line-active-primary + '((t (:weight light :inherit (mode-line)))) + "Modeline face for active primary element." + :group 'lambda-line-active) + +(defface lambda-line-inactive-primary + '((t (:inherit (mode-line-inactive)))) + "Modeline face for inactive primary element." + :group 'lambda-line-inactive) + +(defface lambda-line-active-secondary + '((t (:inherit mode-line))) + "Modeline face for active secondary element." + :group 'lambda-line-active) + +(defface lambda-line-inactive-secondary + '((t (:inherit (mode-line-inactive)))) + "Modeline face for inactive secondary element." + :group 'lambda-line-inactive) + +(defface lambda-line-active-tertiary + '((t (:inherit mode-line))) + "Modeline face for active tertiary element." + :group 'lambda-line-active) + +(defface lambda-line-inactive-tertiary + '((t (:inherit (mode-line-inactive)))) + "Modeline face for inactive tertiary element." + :group 'lambda-line-inactive) + + +;;;;; Status Bar Faces + +;; lambda-line uses a colored symbol to indicate the status of the buffer + +(defface lambda-line-active-status-RO + '((t (:inherit (mode-line) :foreground "yellow" (when lambda-line-status-invert :inverse-video t)))) + "Modeline face for active READ-ONLY element." + :group 'lambda-line-active) + +(defface lambda-line-inactive-status-RO + '((t (:inherit (mode-line-inactive) :foreground "light gray" (when lambda-line-status-invert :inverse-video t)))) + "Modeline face for inactive READ-ONLY element." + :group 'lambda-line-inactive) + +(defface lambda-line-active-status-RW + '((t (:inherit (mode-line) :foreground "green" (when lambda-line-status-invert :inverse-video t)))) + "Modeline face for active READ-WRITE element." + :group 'lambda-line-active) + +(defface lambda-line-inactive-status-RW + '((t (:inherit (mode-line-inactive) :foreground "light gray" (when lambda-line-status-invert :inverse-video t)))) + "Modeline face for inactive READ-WRITE element." + :group 'lambda-line-inactive) + +(defface lambda-line-active-status-MD + '((t (:inherit (mode-line) :foreground "red" (when lambda-line-status-invert :inverse-video t)))) + "Modeline face for active MODIFIED element." + :group 'lambda-line-active) + +(defface lambda-line-inactive-status-MD + '((t (:inherit (mode-line-inactive) :foreground "light gray" (when lambda-line-status-invert :inverse-video t)))) + "Modeline face for inactive MODIFIED element." + :group 'lambda-line-inactive) + + +;;;;; Bell Faces + +(defface lambda-line-visual-bell '((t (:background "red3"))) + "Face to use for the mode-line when `lambda-line-visual-bell-config' is used." + :group 'lambda-line) + +;;;; Setup Functions + +;;;;; Visual bell for mode line + +;; See https://github.com/hlissner/emacs-doom-themes for the basic idea + +(defun lambda-line-visual-bell-fn () + "Blink the status-line red briefly. Set `ring-bell-function' to this to use it." + (let ((lambda-line--bell-cookie (if (eq lambda-line-position 'bottom) + (face-remap-add-relative 'mode-line 'lambda-line-visual-bell) + (face-remap-add-relative 'header-line 'lambda-line-visual-bell))) + (force-mode-line-update t)) + (run-with-timer 0.15 nil + (lambda (cookie buf) + (with-current-buffer buf + (face-remap-remove-relative cookie) + (force-mode-line-update t))) + lambda-line--bell-cookie + (current-buffer)))) + +(defun lambda-line-visual-bell-config () + "Enable flashing the status-line on error." + (setq ring-bell-function #'lambda-line-visual-bell-fn + visible-bell t)) + +;;;;; Abbreviate Major-Mode +;; Source: https://www.masteringemacs.org/article/hiding-replacing-modeline-strings + +(defcustom lambda-line-abbrev-alist + `((dired-mode . "Dir") + (emacs-lisp-mode . "𝛌") + (fundamental-mode . "F") + (helpful-mode . "") + (help-mode . "") + (lisp-interaction-mode . "λΙ") + (markdown-mode . "MD") + (magit-mode . "MG") + (nxhtml-mode . "NX") + (prog-mode . "PR") + (python-mode . "PY") + (text-mode . "TX")) + "Alist for `lambda-line--abbrev'. + +When you add a new element to the alist, keep in mind that you +must pass the correct minor/major mode symbol and a string you +want to use in the modeline *as substitute for* the original." + :type '(alist + :key-type (symbol :tag "Major mode") + :value-type (string :tag "Abbreviation")) + :group 'lambda-line) + +(defun lambda-line--abbrev () + (cl-loop for abbrev in lambda-line-abbrev-alist + do (let* ((mode (car abbrev)) + (mode-str (cdr abbrev)) + (old-mode-str (cdr (assq mode minor-mode-alist)))) + (when old-mode-str + (setcar old-mode-str mode-str)) + ;; major mode + (when (eq mode major-mode) + (setq mode-name mode-str))))) + +;; Set abbrev (default is nil) +(when lambda-line-abbrev + (add-hook 'after-change-major-mode-hook #'lambda-line--abbrev)) + +;;;;; Mode Name +(defun lambda-line-user-mode-p () + "Should the user supplied mode be called for modeline?" + lambda-line-user-mode) + +(defun lambda-line-mode-name () + "Return current major mode name." + (format-mode-line mode-name)) + +;;;;; String Truncate +(defun lambda-line-truncate (str size &optional ellipsis) + "If STR is longer than SIZE, truncate it and add ELLIPSIS." + + (let ((ellipsis (or ellipsis "…"))) + (if (> (length str) size) + (format "%s%s" (substring str 0 (- size (length ellipsis))) ellipsis) + str))) + +;;;;; Branch display +;; ------------------------------------------------------------------- +(defun lambda-line-project-name () + "Return name of project without path." + (file-name-nondirectory (directory-file-name (if (vc-root-dir) (vc-root-dir) "-")))) + +(defun lambda-line-vc-project-branch () + "Show project and branch name for file. +Otherwise show '-'." + (let ((backend (vc-backend buffer-file-name))) + (concat + (if buffer-file-name + (if vc-mode + (let ((project-name (lambda-line-project-name))) + ;; Project name + (unless (string= "-" project-name) + (concat + ;; Divider + (propertize " •" 'face `(:inherit fringe)) + (format " %s" project-name)))))) + + ;; Show branch + (if vc-mode + (concat + lambda-line-vc-symbol (substring-no-properties vc-mode ; + (+ (if (eq backend 'Hg) 2 3) 2))) nil)))) + +;;;;; Dir display +;; From https://amitp.blogspot.com/2011/08/emacs-custom-mode-line.html +(defun lambda-line-shorten-directory (dir max-length) + "Show up to `max-length' characters of a directory name `dir'." + (let ((path (reverse (split-string (abbreviate-file-name dir) "/"))) + (output "")) + (when (and path (equal "" (car path))) + (setq path (cdr path))) + (while (and path (< (length output) (- max-length 4))) + (setq output (concat (car path) "/" output)) + (setq path (cdr path))) + (when path + (setq output (concat "…/" output))) + output)) + +;;;;; Git diff in modeline +;; https://cocktailmake.github.io/posts/emacs-modeline-enhancement-for-git-diff/ +(when lambda-line-git-diff-mode-line + (defadvice vc-git-mode-line-string (after plus-minus (file) compile activate) + "Show the information of git diff in status-line" + (setq ad-return-value + (concat ad-return-value + (let ((plus-minus (vc-git--run-command-string + file "diff" "--numstat" "--"))) + (if (and plus-minus + (string-match "^\\([0-9]+\\)\t\\([0-9]+\\)\t" plus-minus)) + (concat + " " + (format "+%s" (match-string 1 plus-minus)) + (format "-%s" (match-string 2 plus-minus))) + "")))))) + +;;;;; Git Parse Repo Status +;; See https://kitchingroup.cheme.cmu.edu/blog/2014/09/19/A-git-status-Emacs-modeline/ +(defun lambda-line-git-parse-status () + "Display the status of the repo." + (interactive) + (let ((U 0) ; untracked files + (M 0) ; modified files + (O 0) ; other files + (U-files "") + (M-files "") + (O-files "")) + (dolist (line (split-string + (shell-command-to-string "git status --porcelain") + "\n")) + (cond + + ;; ignore empty line at end + ((string= "" line) nil) + + ((string-match "^\\?\\?" line) + (setq U (+ 1 U)) + (setq U-files (concat U-files "\n" line))) + + ((string-match "^ M" line) + (setq M (+ 1 M)) + (setq M-files (concat M-files "\n" line)) + ))) + + ;; construct propertized string + (concat + (propertize + (format "M:%d" M) + 'face (if (> M 0) + 'error + 'success) + 'help-echo M-files) + (propertize "|" 'face 'magit-dimmed) + (propertize + (format "?:%d" U) + 'face (if (> U 0) + 'warning + 'success) + 'help-echo U-files)))) + +;;;;; Flycheck/Flymake Segment +(defvar-local lambda-line--flycheck-text nil) +(defun lambda-line--update-flycheck-segment (&optional status) + "Update `lambda-line--flycheck-text' against the reported flycheck STATUS." + (setq lambda-line--flycheck-text + (pcase status + ('finished (if flycheck-current-errors + (let-alist (flycheck-count-errors flycheck-current-errors) + (let ((sum (+ (or .error 0) (or .warning 0)))) + (propertize (concat lambda-line-flycheck-label + (number-to-string sum) + " ") + 'face (if .error + 'error + 'warning)))) + (propertize "Good " 'face 'success))) + ('running (propertize "Checking " 'face 'info)) + ('errored (propertize "Error " 'face 'error)) + ('interrupted (propertize "Paused " 'face 'fringe)) + ('no-checker "")))) + +(defun lambda-line-check-syntax () + "Display syntax-checking information from flymake/flycheck in the mode-line (if available)." + (if (and (>= emacs-major-version 28) + (boundp 'flymake-mode) + flymake-mode) + (concat (format-mode-line flymake-mode-line-format) " ") + lambda-line--flycheck-text)) + +;;;;; Display-time-mode +(defun lambda-line-install-clockface-fonts () + "Install ClockFace fonts on the local system. + +Thanks to the Doom Emacs project, for the basis of this +cross-platform font dowload/install code." + (interactive) + (let ((on-mac (eq system-type 'darwin)) + (on-linux (memq system-type '(gnu gnu/linux gnu/kfreebsd berkeley-unix))) + (on-windows (memq system-type '(cygwin windows-nt ms-dos))) + (name "ClockFace") + (url-format "https://ocodo.github.io/ClockFace-font/%s") + (fonts-list '("ClockFace-Regular.ttf" + "ClockFaceRect-Regular.ttf" + "ClockFaceSolid-Regular.ttf" + "ClockFaceRectSolid-Regular.ttf"))) + (unless (yes-or-no-p + (format + "Download%sthe ClockFace fonts, continue?" + (if on-windows + " " + " and install "))) + (user-error "Aborted Download of ClockFace fonts")) + (let* ((font-dest + (cond (on-linux + (expand-file-name + "fonts/" (or (getenv "XDG_DATA_HOME") + "~/.local/share"))) + (on-mac + (expand-file-name "~/Library/Fonts/")))) + (known-dest-p (stringp font-dest)) + (font-dest (or font-dest (read-directory-name "Font installation directory: " "~/")))) + (unless (file-directory-p font-dest) + (mkdir font-dest t)) + (dolist (font fonts-list) + (url-copy-file (format url-format font) + (expand-file-name font font-dest) + t)) + (when known-dest-p + (message "Font downloaded, updating font cache... Using <fc-cache -f -v> ") + (shell-command-to-string "fc-cache -f -v")) + (if on-windows + (when (y-or-n-p "The %S font was downloaded, Windows users must install manually.\n\nOpen windows explorer?") + (call-process "explorer.exe" nil nil nil font-dest)) + (message "Successfully %s %S fonts to %S!" + (if known-dest-p + "installed" + "downloaded") + name font-dest))))) + +(defun lambda-line-clockface-select-font () + "Select clockface icon font." + (interactive) + (let ((font (completing-read + "Select clockface icon font: " + '("ClockFace" + "ClockFaceSolid" + "ClockFaceRect" + "ClockFaceRectSolid")))) + (lambda-line-clockface-update-fontset font))) + +(defun lambda-line-clockface-update-fontset (&optional font) + "Use ClockFace font for unicode #xF0000..F008F. +Optionally use another clockface font." + (set-fontset-font + "fontset-default" + (cons (decode-char 'ucs #xF0000) + (decode-char 'ucs #xF008F)) + (or font "ClockFace"))) + +;; Usage example for testing +;; - exal each one after font installation to test. +;; (uses the complete font name now) +;; +;; [x] (lambda-line-clockface-update-fontset "ClockFace") +;; [x] (lambda-line-clockface-update-fontset "ClockFaceRect") +;; [x] (lambda-line-clockface-update-fontset "ClockFaceRectSolid") +;; [x] (lambda-line-clockface-update-fontset "ClockFaceSolid") + +;; Need to add some note about Doom Emacs font-set modification for the user: +;; +;; E.g. +;; +;; Doom Emacs will reset fontset-default when fonts are resized +;; (e.g. after `doom/increase-font-size' or `doom/decrease-font-size') +;; +;; So it's necessary to use `lambda-line-clockface-update-fontset' after such events have +;; completed. +;; +;; (I haven't found a working solution, i.e. using the Doom hook `after-setting-font-hook' doesn't work.) + +(defun lambda-line-clockface-icons-unicode (hours minutes) + "Return ClockFace icon unicode for HOURS and MINUTES." + (let* ((minute (- minutes (% minutes 5))) + (offset (round (+ (* (% hours 12) 12) (* 12 (/ minute 60.0)))))) + (+ offset #xF0000))) + +(defun lambda-line-time () + "Display the time when `display-time-mode' is non-nil." + (when display-time-mode + (let* ((time-unicode + (cl-destructuring-bind (_ minute hour &rest n) (decode-time) + (lambda-line-clockface-icons-unicode hour minute)))) + (concat + (unless lambda-line-icon-time + (if display-time-day-and-date + (propertize (format-time-string lambda-line-time-day-and-date-format)) + (propertize (format-time-string lambda-line-time-format ) 'face `(:height 0.9)))) + (propertize + (format lambda-line-time-icon-format (char-to-string time-unicode) + 'display '(raise 0))))))) + +;;;;; Status +(defun lambda-line-status () + "Return buffer status, one of 'read-only, 'modified or 'read-write." + + (let ((read-only (when (not (or (derived-mode-p 'vterm-mode) + (derived-mode-p 'term-mode) + (derived-mode-p 'Info-mode) + (derived-mode-p 'help-mode) + (derived-mode-p 'helpful-mode) + (derived-mode-p 'elfeed-search) + (derived-mode-p 'elfeed-show))) + buffer-read-only)) + (modified (and buffer-file-name (buffer-modified-p)))) + (cond (modified 'modified) + (read-only 'read-only) + (t 'read-write)))) + +;;;;; Compose Status-Line +(defun lambda-line-compose (status name primary tertiary secondary) + "Compose a string with provided information. +Each section is first defined, along with a measure of the width of the status-line. +STATUS, NAME, PRIMARY, and SECONDARY are always displayed. TERTIARY is displayed only in some modes." + (let* ((window (get-buffer-window (current-buffer))) + + (name-max-width (max 12 + (- (window-body-width) + (round (* 0.8 (length primary))) + (length tertiary) + (length secondary)))) + + (name (if (and (stringp name) (> (length name) name-max-width)) + (format "…%s" (substring name (- (length name) name-max-width -1))) + name)) + + (status (or status (lambda-line-status))) + + (active (eq window lambda-line--selected-window)) + + (prefix (cond ((eq lambda-line-prefix nil) "") + (t + (cond ((derived-mode-p 'term-mode) " >_") + ((derived-mode-p 'vterm-mode) " >_") + ((derived-mode-p 'eshell-mode) " λ:") + ((derived-mode-p 'Info-mode) " ℹ") + ((derived-mode-p 'help-mode) " ") + ((derived-mode-p 'helpful-mode) " ") + ((eq status 'read-only) + (if (display-graphic-p) lambda-line-gui-ro-symbol + lambda-line-tty-ro-symbol)) + ((eq status 'read-write) (if (display-graphic-p) lambda-line-gui-rw-symbol + lambda-line-tty-rw-symbol)) + ((eq status 'modified) (if (display-graphic-p) lambda-line-gui-mod-symbol + lambda-line-tty-mod-symbol)) + ((window-dedicated-p) (if (display-graphic-p) " ––" " --")) + ;; otherwise just use rw symbol + (t (if (display-graphic-p) lambda-line-gui-rw-symbol + lambda-line-tty-rw-symbol)))))) + + (face-modeline (if active + 'lambda-line-active + 'lambda-line-inactive)) + (face-prefix (if (not prefix) face-modeline + (if active + (cond ((eq status 'read-only) 'lambda-line-active-status-RO) + ((eq status 'read-write) 'lambda-line-active-status-RW) + ((eq status 'modified) 'lambda-line-active-status-MD) + ((or (derived-mode-p 'term-mode) + (derived-mode-p 'vterm-mode) + (derived-mode-p 'eshell-mode)) + 'lambda-line-active-status-MD) + ((or (derived-mode-p 'Info-mode) + (derived-mode-p 'help-mode) + (derived-mode-p 'helpful-mode)) + 'lambda-line-active-status-RO) + (t 'lambda-line-active)) + (cond ((eq status 'read-only) 'lambda-line-inactive-status-RO) + ((eq status 'read-write) 'lambda-line-inactive-status-RW) + ((eq status 'modified) 'lambda-line-inactive-status-MD) + ((or (derived-mode-p 'term-mode) + (derived-mode-p 'vterm-mode) + (derived-mode-p 'eshell-mode) + (derived-mode-p 'Info-mode) + (derived-mode-p 'help-mode) + (derived-mode-p 'helpful-mode)) + 'lambda-line-inactive-status-RW) + (t 'lambda-line-inactive))))) + (face-name (if active + 'lambda-line-active-name + 'lambda-line-inactive-name)) + (face-primary (if active + 'lambda-line-active-primary + 'lambda-line-inactive-primary)) + (face-secondary (if active + 'lambda-line-active-secondary + 'lambda-line-inactive-secondary)) + (face-tertiary (if active + 'lambda-line-active-tertiary + 'lambda-line-inactive-tertiary)) + (left + ;; special face for special mode prefixes + (concat + (propertize prefix 'face face-prefix 'display `(raise ,lambda-line-symbol-position)) + ;; this matters for inverse-video! + (propertize " " 'face face-prefix 'display `(raise ,lambda-line-space-top)) + + (when lambda-line-prefix-padding + (propertize " " 'face face-modeline)) + + (propertize name 'face face-name) + + (propertize " " 'face (if active 'lambda-line-active + 'lambda-line-inactive) + 'display `(raise ,lambda-line-space-bottom)) + + (propertize primary 'face face-primary))) + + (right (concat tertiary (propertize secondary 'face face-secondary) (propertize lambda-line-hspace 'face face-modeline))) + + (right-len (length (format-mode-line right)))) + (concat + left + (propertize " " 'face face-modeline 'display `(space :align-to (- right ,right-len))) + right))) + +;;;; Mode Functions +;;;; Default display +(defun lambda-line-default-mode () + "Compose the default status line." + (let ((buffer-name (format-mode-line (if buffer-file-name + (file-name-nondirectory (buffer-file-name)) + "%b"))) + (mode-name (lambda-line-mode-name)) + (branch (lambda-line-vc-project-branch)) + (position (format-mode-line "%l:%c:%o"))) + (lambda-line-compose (lambda-line-status) + (lambda-line-truncate buffer-name lambda-line-truncate-value) + (concat lambda-line-display-group-start + mode-name + (when branch + branch) + lambda-line-display-group-end) + "" + ;; Narrowed buffer + (concat (if (buffer-narrowed-p) + (concat + (propertize "⇥ " 'face `(:inherit lambda-line-inactive-secondary)) + position " ") + position) + (lambda-line-time))))) + +;;;;; Prog Mode +;; --------------------------------------------------------------------- +(defun lambda-line-prog-mode-p () + (derived-mode-p 'prog-mode)) + +(defun lambda-line-prog-mode () + (let ((buffer-name (format-mode-line (if buffer-file-name (file-name-nondirectory (buffer-file-name)) "%b"))) + (mode-name (lambda-line-mode-name)) + (branch (lambda-line-vc-project-branch)) + (position (format-mode-line "%l:%c:%o"))) + (lambda-line-compose (lambda-line-status) + (lambda-line-truncate buffer-name lambda-line-truncate-value) + (concat lambda-line-display-group-start mode-name + (when branch branch) + lambda-line-display-group-end) + + (if lambda-line-syntax + (lambda-line-check-syntax) "") + + (concat + ;; Narrowed buffer + (when (buffer-narrowed-p) + (propertize "⇥ " 'face `(:inherit lambda-line-inactive-secondary))) + (if lambda-line-syntax + (if (or (boundp 'flycheck-mode) + (boundp 'flymake-mode)) + ;; (concat position lambda-line-hspace) + position) + position) + + (lambda-line-time))))) + +(defun lambda-line-prog-activate () + "Setup flycheck hooks." + (add-hook 'flycheck-status-changed-functions #'lambda-line--update-flycheck-segment) + (add-hook 'flycheck-mode-hook #'lambda-line--update-flycheck-segment) + (when lambda-line-git-diff-mode-line + (add-hook 'after-save-hook #'vc-refresh-state))) + +(defun lambda-line-prog-deactivate () + "Remove flycheck hooks." + (remove-hook 'flycheck-status-changed-functions #'lambda-line--update-flycheck-segment) + (remove-hook 'flycheck-mode-hook #'lambda-line--update-flycheck-segment) + (when lambda-line-git-diff-mode-line + (remove-hook 'after-save-hook #'vc-refresh-state))) + +;;;;; Fundamental Mode + +(defun lambda-line-fundamental-mode-p () + (derived-mode-p 'fundamental-mode)) + +(defun lambda-line-fundamental-mode () + (lambda-line-default-mode)) + +;;;;; Text Mode + +(defun lambda-line-text-mode-p () + (derived-mode-p 'text-mode)) + +(defun lambda-line-text-mode () + (lambda-line-default-mode)) + + +;;;;; Help (& Helpful) Mode +(defun lambda-line-help-mode-p () + (derived-mode-p 'help-mode)) + +(defun lambda-line-helpful-mode-p () + (derived-mode-p 'helpful-mode)) + +(defun lambda-line-help-mode () + (lambda-line-compose "HELP" + (format-mode-line "%b") + "" + "" + (format-mode-line "%l:%c:%o"))) + + +;;;;; Info Display +;; --------------------------------------------------------------------- +(defun lambda-line-info-breadcrumbs () + (let ((nodes (Info-toc-nodes Info-current-file)) + (cnode Info-current-node) + (node Info-current-node) + (crumbs ()) + (depth Info-breadcrumbs-depth) + line) + (save-excursion + (while (> depth 0) + (setq node (nth 1 (assoc node nodes))) + (if node (push node crumbs)) + (setq depth (1- depth))) + (setq crumbs (cons "Top" (if (member (pop crumbs) '(nil "Top")) + crumbs (cons nil crumbs)))) + (forward-line 1) + (dolist (node crumbs) + (let ((text + (if (not (equal node "Top")) node + (format "%s" + (if (stringp Info-current-file) + (file-name-sans-extension + (file-name-nondirectory Info-current-file)) + Info-current-file))))) + (setq line (concat line (if (null line) "" " > ") + (if (null node) "..." text))))) + (if (and cnode (not (equal cnode "Top"))) + (setq line (concat line (if (null line) "" " > ") cnode))) + line))) + +(defun lambda-line-info-mode-p () + (derived-mode-p 'Info-mode)) + +(defun lambda-line-info-mode () + (lambda-line-compose "INFO" + "" + (concat lambda-line-display-group-start + (lambda-line-info-breadcrumbs) + lambda-line-display-group-end) + "" + "" + )) + +(defun lambda-line-info-activate () + (if (eq lambda-line-position 'top) + (setq Info-use-header-line nil))) + +(defun lambda-line-info-deactivate () + (custom-reevaluate-setting 'Info-use-header-line)) + +;;;; Term & Vterm +;; --------------------------------------------------------------------- +;; term +(defun lambda-line-term-mode-p () + (derived-mode-p 'term-mode)) + +;; vterm +(defun lambda-line-vterm-mode-p () + (derived-mode-p 'vterm-mode)) + +(defun lambda-line-term-mode () + (lambda-line-compose " >_ " + "Terminal" + (concat lambda-line-display-group-start + (file-name-nondirectory shell-file-name) + lambda-line-display-group-end) + nil + (concat (lambda-line-shorten-directory default-directory 32) + (lambda-line-time)))) + + +;; --------------------------------------------------------------------- + +(defun lambda-line-get-ssh-host (_str) + (let ((split-defdir (split-string default-directory))) + (if (equal (length split-defdir) 1) + (car (split-string (shell-command-to-string "hostname") "\n")) + (cadr split-defdir)))) + +(defun lambda-line-ssh-mode () + (lambda-line-compose " >_ " + "Terminal" + (concat lambda-line-display-group-start + (lambda-line-get-ssh-host default-directory) + lambda-line-display-group-end) + nil + (concat (lambda-line-shorten-directory (car (last (split-string default-directory ":"))) 32) + (lambda-line-time)))) + +;;;; Eshell +;; --------------------------------------------------------------------- +(defun lambda-line-eshell-mode-p () + (derived-mode-p 'eshell-mode)) + +(defun lambda-line-eshell-mode () + (lambda-line-compose " >_ " + "Eshell" + (concat lambda-line-display-group-start + (buffer-name) + lambda-line-display-group-end) + "" + (concat (lambda-line-shorten-directory default-directory 32) + (lambda-line-time)))) + +(defun lambda-line-esh-activate () + (with-eval-after-load 'esh-mode + (setq eshell-status-in-mode-line nil))) + +(defun lambda-line-esh-deactivate () + (custom-reevaluate-setting 'eshell-status-in-mode-line)) + +;;;; Messages Buffer Mode +;; --------------------------------------------------------------------- +(defun lambda-line-messages-mode-p () + (derived-mode-p 'messages-buffer-mode)) + +(defun lambda-line-messages-mode () + (lambda-line-compose (lambda-line-status) + "*Messages*" + "" + "" + (concat "" (lambda-line-time)))) + +;;;; Message Mode +;; --------------------------------------------------------------------- +(defun lambda-line-message-mode-p () + (derived-mode-p 'message-mode)) + +(defun lambda-line-message-mode () + (lambda-line-compose (lambda-line-status) + "Message" "(Draft)" nil (lambda-line-time))) + +;;;; Docview Mode +;;--------------------------------------------------------------------- +(defun lambda-line-doc-view-mode-p () + (derived-mode-p 'doc-view-mode)) + +(defun lambda-line-doc-view-mode () + (let ((buffer-name (format-mode-line "%b")) + (mode-name (lambda-line-mode-name)) + (branch (lambda-line-vc-project-branch)) + (page-number (concat + (number-to-string (doc-view-current-page)) "/" + (or (ignore-errors + (number-to-string (doc-view-last-page-number))) + "???")))) + (lambda-line-compose + (lambda-line-status) + buffer-name + (concat lambda-line-display-group-start mode-name + branch + lambda-line-display-group-end) + nil + (concat page-number + (lambda-line-time))))) + +;;;; PDF View Mode +;; --------------------------------------------------------------------- +(defun lambda-line-pdf-view-mode-p () + (derived-mode-p 'pdf-view-mode)) + +(with-eval-after-load 'pdf-tools + (require 'pdf-view)) + +(defun lambda-line-pdf-view-mode () + (let ((buffer-name (format-mode-line "%b")) + (mode-name (lambda-line-mode-name)) + (branch (lambda-line-vc-project-branch)) + (page-number (concat + (number-to-string (eval `(pdf-view-current-page))) "/" + (or (ignore-errors + (number-to-string (pdf-cache-number-of-pages))) + "???")))) + (lambda-line-compose (lambda-line-status) + buffer-name + (concat lambda-line-display-group-start mode-name + lambda-line-display-group-end) + "" + (concat page-number " " (lambda-line-time))))) + +;;;; MenuMode + +(defun lambda-line-buffer-menu-mode-p () + (derived-mode-p 'buffer-menu-mode)) + +(defun lambda-line-buffer-menu-mode () + (let ((buffer-name "Buffer list") + (mode-name (lambda-line-mode-name)) + (position (format-mode-line "%l:%c:%o"))) + + (lambda-line-compose (lambda-line-status) + buffer-name "" nil (concat position lambda-line-hspace (lambda-line-time))))) + +;;;; Imenu-List +(defun lambda-line-imenu-list-mode-p () + (derived-mode-p 'imenu-list-major-mode)) + +(defun lambda-line-imenu-list-mode () + (let ( + ;; We take into account the case of narrowed buffers + (buffer-name (buffer-name imenu-list--displayed-buffer)) + (branch (lambda-line-vc-project-branch)) + (position (format-mode-line "%l:%c"))) + (lambda-line-compose (lambda-line-status) + buffer-name + "(imenu list)" + "" + ""))) +;;;; Completion +;; --------------------------------------------------------------------- +(defun lambda-line-completion-list-mode-p () + (derived-mode-p 'completion-list-mode)) + +(defun lambda-line-completion-list-mode () + (let ((buffer-name (format-mode-line "%b")) + (mode-name (lambda-line-mode-name)) + (position (format-mode-line "%l:%c:%o"))) + + (lambda-line-compose (lambda-line-status) + buffer-name "" nil (concat position lambda-line-hspace)))) + +;;;; Deft Mode + +(with-eval-after-load 'deft + (defun lambda-line--deft-print-header () + (force-mode-line-update) + (widget-insert "\n"))) + +(defun lambda-line-deft-mode-p () + (derived-mode-p 'deft-mode)) + +(defun lambda-line-deft-mode () + (let ((prefix " DEFT ") + (primary "Search:") + (filter (if deft-filter-regexp + (deft-whole-filter-regexp) "<filter>")) + (matches (if deft-filter-regexp + (format "%d matches" (length deft-current-files)) + (format "%d notes" (length deft-all-files))))) + (lambda-line-compose prefix primary filter nil matches))) + +;;;; Calendar Mode +;; --------------------------------------------------------------------- +(defun lambda-line-calendar-mode-p () + (derived-mode-p 'calendar-mode)) + +(defun lambda-line-calendar-mode () "") + +;; Calendar (no header, only overline) +(with-eval-after-load 'calendar + (defun lambda-line-calendar-setup-header () + (setq header-line-format "") + (face-remap-add-relative + 'header-line `(:overline ,(face-foreground 'default) + :height 0.5 + :background ,(face-background 'default))))) + +(defun lambda-line-calendar-activate () + (with-eval-after-load 'calendar + (add-hook 'calendar-initial-window-hook + #'lambda-line-calendar-setup-header))) + +(defun lambda-line-calendar-deactivate () + (remove-hook 'calendar-initial-window-hook + #'lambda-line-calendar-setup-header)) + +;;;; Org Capture +;; --------------------------------------------------------------------- +(defun lambda-line-org-capture-mode-p () + (bound-and-true-p org-capture-mode)) + +(defun lambda-line-org-capture-mode () + (lambda-line-compose (lambda-line-status) + "Capture" + (concat lambda-line-display-group-start + (org-capture-get :description) + lambda-line-display-group-end) + nil + "Finish: C-c C-c, refile: C-c C-w, cancel: C-c C-k ")) + + +(defun lambda-line-org-capture-turn-off-header-line () + (setq-local header-line-format (default-value 'header-line-format)) + (message nil)) + +(defun lambda-line-org-capture-activate () + (with-eval-after-load 'org-capture + (add-hook 'org-capture-mode-hook + #'lambda-line-org-capture-turn-off-header-line))) + +(defun lambda-line-org-capture-deactivate () + (remove-hook 'org-capture-mode-hook + #'lambda-line-org-capture-turn-off-header-line)) + + +;;;; Org Agenda +;; --------------------------------------------------------------------- +(defun lambda-line-org-agenda-mode-p () + (derived-mode-p 'org-agenda-mode)) + +(defun lambda-line-org-agenda-mode () + (let ((lambda-line-icon-time t)) + (lambda-line-compose (lambda-line-status) + "Agenda" + (concat lambda-line-display-group-start (format "%S" org-agenda-current-span) lambda-line-display-group-end) + "" + (concat (format-time-string "%A, %d %B %Y") + (lambda-line-time) + (format-time-string " %H:%M"))))) + +;;;; Org Clock +;; --------------------------------------------------------------------- +(defun lambda-line-org-clock-mode-p () + (and (boundp 'org-mode-line-string) + (stringp org-mode-line-string))) + +(defun lambda-line-org-clock-mode () + (let ((buffer-name (format-mode-line "%b")) + (mode-name (lambda-line-mode-name)) + (branch (lambda-line-vc-project-branch)) + (position (format-mode-line "%l:%c:%o"))) + (lambda-line-compose (lambda-line-status) + buffer-name + (concat lambda-line-display-group-start + mode-name + (when branch + branch) + lambda-line-display-group-end) + "" + (concat + ;; Narrowed buffer + (when (buffer-narrowed-p) + (propertize "⇥ " 'face `(:inherit lambda-line-inactive-secondary))) + org-mode-line-string + " " + nil + position + lambda-line-hspace)))) + +(defun lambda-line-org-clock-out () + (setq org-mode-line-string nil) + (force-mode-line-update)) + +(defun lambda-line-org-clock-activate () + (with-eval-after-load 'org-clock + (add-hook 'org-clock-out-hook #'lambda-line-org-clock-out))) + +(defun lambda-line-org-clock-deactivate () + (remove-hook 'org-clock-out-hook + #'lambda-line-org-clock-out)) + +;;;; Elfeed +;; --------------------------------------------------------------------- +(defun lambda-line-elfeed-search-mode-p () + (derived-mode-p 'elfeed-search-mode)) + +(defun lambda-line-elfeed-search-mode () + (let* ((status "NEWS") + (no-database (zerop (elfeed-db-last-update))) + (update (> (elfeed-queue-count-total) 0)) + + (name (cond (no-database "No database") + (update "Update:") + (t "Search:"))) + (primary (cond (no-database "") + (update + (let ((total (elfeed-queue-count-total)) + (in-process (elfeed-queue-count-active))) + (format "%d jobs pending, %d active" + (- total in-process) in-process))) + (t (let* ((db-time (seconds-to-time (elfeed-db-last-update))) + (unread)) + (cond (elfeed-search-filter-active "") + ((string-match-p "[^ ]" elfeed-search-filter) + elfeed-search-filter) + ("")))))) + (secondary (concat + (cond + ((zerop (elfeed-db-last-update)) "") + ((> (elfeed-queue-count-total) 0) "") + (t (elfeed-search--count-unread))) + (lambda-line-time)))) + + (lambda-line-compose status name primary nil secondary))) + +;; Elfeed uses header-line, we need to tell it to use our own format +(defun lambda-line-elfeed-setup-header () + (setq header-line-format (default-value 'header-line-format))) + +(defun lambda-line-elfeed-search-activate () + (with-eval-after-load 'elfeed + (if (eq lambda-line-position 'top) + (setq elfeed-search-header-function #'lambda-line-elfeed-setup-header)))) + +(defun lambda-line-elfeed-search-deactivate () + (if (boundp 'elfeed-search-header-function) + (setq elfeed-search-header-function #'elfeed-search--header))) + +;; --------------------------------------------------------------------- +(defun lambda-line-elfeed-show-mode-p () + (derived-mode-p 'elfeed-show-mode)) + +(defun lambda-line-elfeed-show-mode () + (let* ((title (elfeed-entry-title elfeed-show-entry)) + (tags (elfeed-entry-tags elfeed-show-entry)) + (tags-str (mapconcat #'symbol-name tags ", ")) + (tag (if tags + (concat lambda-line-display-group-start + tags-str + lambda-line-display-group-end) + " ")) + (date (seconds-to-time (elfeed-entry-date elfeed-show-entry))) + (feed (elfeed-entry-feed elfeed-show-entry)) + (entry-author (elfeed-meta elfeed-show-entry :author)) + (feed-title (if entry-author + (concat entry-author " (" (elfeed-feed-title feed) ")") + (elfeed-feed-title feed)))) + (lambda-line-compose + "" + (lambda-line-truncate title 65) + tag + "" + (format-time-string "%Y-%m-%d %H:%M:%S" date)))) + + +;;;; Mu4e + +(defun lambda-line-mu4e-last-query () + "Get the most recent mu4e query or nil if there is none." + (if (fboundp 'mu4e-last-query) + (mu4e-last-query) + mu4e~headers-last-query)) + +(defun lambda-line-mu4e-context () + "Return the current mu4e context as a non propertized string." + (if (> (length (mu4e-context-label)) 0) + (concat + lambda-line-display-group-start + (substring-no-properties (mu4e-context-label) 1 -1) + lambda-line-display-group-end) + "(none)")) + +(defun lambda-line-mu4e-server-props () + "Encapsulates the call to the variable mu4e-/~server-props +depending on the version of mu4e." + (if (version< mu4e-mu-version "1.6.0") + mu4e~server-props + mu4e--server-props)) + +(defun lambda-line-mu4e-activate () + (with-eval-after-load 'mu4e + (advice-add 'mu4e~header-line-format :override #'lambda-line))) + +(defun lambda-line-mu4e-deactivate () + (advice-remove #'mu4e~header-line-format #'lambda-line)) + +;; --------------------------------------------------------------------- +(defun lambda-line-mu4e-dashboard-mode-p () + (bound-and-true-p mu4e-dashboard-mode)) + +(defun lambda-line-mu4e-dashboard-mode () + (lambda-line-compose (lambda-line-status) + (format "%d messages" + (plist-get (lambda-line-mu4e-server-props) :doccount)) + "" + "" + (lambda-line-time))) + +;; --------------------------------------------------------------------- +(defun lambda-line-mu4e-loading-mode-p () + (derived-mode-p 'mu4e-loading-mode)) + +(defun lambda-line-mu4e-loading-mode () + (lambda-line-compose (lambda-line-status) + (format-time-string "%A %d %B %Y, %H:%M ") + "" + "Loading..." + (lambda-line-mu4e-context))) + +;; --------------------------------------------------------------------- +(defun lambda-line-mu4e-main-mode-p () + (derived-mode-p 'mu4e-main-mode)) + +(defun lambda-line-mu4e-main-mode () + (lambda-line-compose (lambda-line-status) + (format-time-string "%A %d %B %Y, %H:%M ") + "" + "" + (lambda-line-mu4e-context))) + +;; --------------------------------------------------------------------- +(defun lambda-line-mu4e-compose-mode-p () + (derived-mode-p 'mu4e-compose-mode)) + +(defun lambda-line-mu4e-compose-mode () + (lambda-line-compose (lambda-line-status) + (format-mode-line "%b") + "" + "" + (format "[%s] " + (lambda-line-mu4e-quote + (mu4e-context-name (mu4e-context-current)))))) + +;; --------------------------------------------------------------------- +(defun lambda-line-mu4e-quote (str) + (if (version< mu4e-mu-version "1.8.0") + (mu4e~quote-for-modeline str) + (mu4e-quote-for-modeline str))) + +(defun lambda-line-mu4e-headers-mode-p () + (derived-mode-p 'mu4e-headers-mode)) + +(defun lambda-line-mu4e-headers-mode () + (let ((mu4e-modeline-max-width 80)) + (lambda-line-compose + (lambda-line-status) + "Search:" + (or (lambda-line-mu4e-quote + (lambda-line-mu4e-last-query)) "") + "" + (concat + (format "[%s] " + (lambda-line-mu4e-quote + (mu4e-context-name (mu4e-context-current)))) + (or (lambda-line-time) ""))))) + +;; --------------------------------------------------------------------- +(defun lambda-line-mu4e-view-mode-p () + (derived-mode-p 'mu4e-view-mode)) + +(defun lambda-line-mu4e-view-mode () + (let* ((msg (mu4e-message-at-point)) + (subject (mu4e-message-field msg :subject)) + (from (mu4e~headers-contact-str (mu4e-message-field msg :from))) + (date (mu4e-message-field msg :date))) + (lambda-line-compose (lambda-line-status) + (or from "") + (concat lambda-line-display-group-start + (lambda-line-truncate (or subject "") 50 "…") + lambda-line-display-group-end) + "" + (concat (or (format-time-string mu4e-headers-date-format date) "") " ")))) + +(defun lambda-line-mu4e-activate () + (with-eval-after-load 'mu4e + (advice-add 'mu4e~header-line-format :override #'lambda-line))) + +(defun lambda-line-mu4e-deactivate () + (advice-remove #'mu4e~header-line-format #'lambda-line)) + +;;;; Ein + +(defun lambda-line-ein-notebook-mode () + (let ((buffer-name (format-mode-line "%b"))) + (lambda-line-compose (if (ein:notebook-modified-p) "MD" "RW") + buffer-name + "" + "" + (concat + (ein:header-line) + (lambda-line-time))))) + +;; since the EIN library itself is constantly re-rendering the notebook, and thus +;; re-setting the header-line-format, we cannot use the lambda-line function to set +;; the header format in a notebook buffer. Fortunately, EIN exposes the +;; ein:header-line-format variable for just this purpose. + +(defun lambda-line-ein-notebook-activate () + (with-eval-after-load 'ein + (if (eq lambda-line-position 'top) + (setq ein:header-line-format '((:eval (lambda-line-ein-notebook-mode))))))) + +(defun lambda-line-ein-notebook-deactivate () + (if (boundp 'ein:header-line-format) + (setq ein:header-line-format '(:eval (ein:header-line))))) + + +;;;; Buffer Menu Mode +;; --------------------------------------------------------------------- +(defun lambda-line-buffer-menu-mode-p () + (derived-mode-p 'buffer-menu-mode)) + +(defun lambda-line-buffer-menu-mode () + (let ((buffer-name "Buffer list") + (mode-name (lambda-line-mode-name)) + (position (format-mode-line "%l:%c"))) + + (lambda-line-compose nil + buffer-name + "" + nil + (concat + position + (lambda-line-time))))) + +;;(defun buffer-menu-mode-header-line () +;; (face-remap-add-relative +;; 'header-line `(:background ,(face-background 'nano-subtle)))) +;;(add-hook 'Buffer-menu-mode-hook +;; #'buffer-menu-mode-header-line) + +(defun lambda-line-buffer-menu-activate () + (if (eq lambda-line-position 'top) + (setq Buffer-menu-use-header-line nil))) + +(defun lambda-line-buffer-menu-deactivate () + (custom-reevaluate-setting 'Buffer-menu-use-header-line)) + +;;;; Elpher Mode +;; --------------------------------------------------------------------- +(defun lambda-line-elpher-mode-p () + (derived-mode-p 'elpher-mode)) + +(defun lambda-line-elpher-mode () + (let* ((display-string (elpher-page-display-string elpher-current-page)) + (sanitized-display-string (replace-regexp-in-string "%" "%%" display-string)) + (address (elpher-page-address elpher-current-page)) + (tls-string (if (and (not (elpher-address-about-p address)) + (member (elpher-address-protocol address) + '("gophers" "gemini"))) + "(TLS encryption)" + ""))) + (lambda-line-compose nil + sanitized-display-string + tls-string + nil + (lambda-line-time)))) + +(defun lambda-line-elpher-activate () + (with-eval-after-load 'elpher + (setq elpher-use-header nil))) + +;;;; Ispell Mode +;; --------------------------------------------------------------------- +(defun lambda-line-enlarge-ispell-choices-buffer (buffer) + (when (string= (buffer-name buffer) "*Choices*") + (with-current-buffer buffer + ;; (enlarge-window +2) + (setq-local header-line-format nil) + (setq-local mode-line-format nil)))) + +(defun lambda-line-ispell-activate () + (with-eval-after-load 'ispell + (advice-add #'ispell-display-buffer :after + #'lambda-line-enlarge-ispell-choices-buffer))) + +(defun lambda-line-ispell-deactivate () + (advice-remove #'ispell-display-buffer + #'lambda-line-enlarge-ispell-choices-buffer)) + +;;;; Eldoc +;; --------------------------------------------------------------------- +;; `eldoc-minibuffer-message' changes `mode-line-format' but status-line when +;; `lambda-line-position' is `top' fails to display info. Solution is to move +;; eldoc messages to the minibuffer/echo area. +(when (eq lambda-line-position 'top) + (setq eldoc-message-function #'message)) + +;;;; Magit +;; --------------------------------------------------------------------- +(defun lambda-line-magit-mode-p () + (derived-mode-p 'magit-mode)) + +;; Add functions to parse repo every N seconds +(defvar lambda-line-git-parse-last-update (float-time) "Last time we updated") +(defvar lambda-line-git-parse-update-interval 15 "Minimum time between update in seconds") +(defvar lambda-line-git-parse "" "Last value of the parse") + +(defun lambda-line-magit-mode () + (let* ((buffer-name (format-mode-line + (if buffer-file-name + (file-name-nondirectory (buffer-file-name)) + "%b"))) + (mode-name (lambda-line-mode-name)) + (project (file-name-nondirectory (directory-file-name (magit-toplevel)))) + (branch (magit-get-current-branch)) + (status (lambda-line-git-parse-status))) + (lambda-line-compose (lambda-line-status) + mode-name + (concat lambda-line-display-group-start + project + lambda-line-vc-symbol + branch + lambda-line-display-group-end) + status + ""))) + + +;;;; Setup Lambda-line +;; --------------------------------------------------------------------- +(defun lambda-line-face-clear (face) + "Clear FACE" + (set-face-attribute face nil + :foreground 'unspecified :background 'unspecified + :family 'unspecified :slant 'unspecified + :weight 'unspecified :height 'unspecified + :underline 'unspecified :overline 'unspecified + :box 'unspecified :inherit 'unspecified)) + +;; --------------------------------------------------------------------- +(defvar lambda-line--saved-mode-line-format nil) +(defvar lambda-line--saved-header-line-format nil) +(defvar lambda-line--selected-window nil) + +(defun lambda-line--update-selected-window () + "Update selected window (before mode-line is active)" + (setq lambda-line--selected-window (selected-window))) + +(defun lambda-line () + "Build and set the modeline." + (let* ((format + '((:eval + (funcall + (or (catch 'found + (dolist (elt lambda-line-mode-formats) + (let* ((config (cdr elt)) + (mode-p (plist-get config :mode-p)) + (format (plist-get config :format))) + (when mode-p + (when (funcall mode-p) + (throw 'found format)))))) + lambda-line-default-mode-format)))))) + (if (eq lambda-line-position 'top) + (progn + (setq header-line-format format) + (setq-default header-line-format format)) + (progn + (setq mode-line-format format) + (setq-default mode-line-format format))))) + +(defun lambda-line-update-windows () + "Hide the mode line depending on the presence of a window +below or a buffer local variable 'no-mode-line'." + (dolist (window (window-list)) + (with-selected-window window + (with-current-buffer (window-buffer window) + (if (or (not (boundp 'no-mode-line)) (not no-mode-line)) + (setq mode-line-format + (cond ((one-window-p t) (list "")) + ((eq (window-in-direction 'below) (minibuffer-window)) (list "")) + ((not (window-in-direction 'below)) (list "")) + (t nil)))))))) + +(defun lambda-line-mode--activate () + "Activate lambda-line." + + ;; Save current mode-line and header-line + (unless lambda-line--saved-mode-line-format + (setq lambda-line--saved-mode-line-format mode-line-format) + (setq lambda-line--saved-header-line-format header-line-format)) + + (dolist (elt lambda-line-mode-formats) + (let* ((config (cdr elt)) + (fn (plist-get config :on-activate))) + (when fn (funcall fn)))) + + (run-hooks 'lambda-line-mode-format-activate-hook) + + ;; Update selected window + (lambda-line--update-selected-window) + ;; (setq lambda-line--selected-window (selected-window)) + + (setq mode-line-format nil) + (setq-default mode-line-format nil) + (setq header-line-format nil) + (setq-default header-line-format nil) + + (lambda-line) + + ;; Use lambda-line-visual-bell when var is set to t + (when lambda-line-visual-bell + (lambda-line-visual-bell-config)) + + ;; This hooks is necessary to register selected window because when + ;; a modeline is evaluated, the corresponding window is always selected. + (add-hook 'post-command-hook #'lambda-line--update-selected-window) + + ;; This hooks hide the modeline for windows having a window below them + ;; Disabled for the time being, + ;; -> see https://github.com/rougier/nano-modeline/issues/24 + ;; (add-hook 'window-configuration-change-hook #'lambda-line-update-windows) + + (force-mode-line-update t)) + +;; Deactivate status-line +(defun lambda-line-mode--deactivate () + "Deactivate lambda-line and restore default mode-line." + + (dolist (elt lambda-line-mode-formats) + (let* ((config (cdr elt)) + (fn (plist-get config :on-deactivate))) + (when fn (funcall fn)))) + + (run-hooks 'lambda-line-mode-format-deactivate-hook) + + (remove-hook 'post-command-hook + #'lambda-line--update-selected-window) + (remove-hook 'window-configuration-change-hook + #'lambda-line-update-windows) + + ;; Deactivate lambda-line-visual-bell + (setq lambda-line-visual-bell nil) + + (setq mode-line-format lambda-line--saved-mode-line-format) + (setq-default mode-line-format lambda-line--saved-mode-line-format) + (setq header-line-format lambda-line--saved-header-line-format) + (setq-default header-line-format lambda-line--saved-header-line-format)) + +;;;; Lambda-line minor mode + +;; Store the default mode-line format +(defvar lambda-line--default-mode-line mode-line-format) + +;;;###autoload +(define-minor-mode lambda-line-mode + "Toggle lambda-line on or off." + :group 'lambda-line + :global t + :lighter nil + + (if lambda-line-mode + (lambda-line-mode--activate) + (lambda-line-mode--deactivate)) + + ;; Run any registered hooks + (run-hooks 'lambda-line-mode-hook)) + +;;; Provide: +(provide 'lambda-line) + +;;; lambda-line.el ends here diff --git a/emacs/libs/minad.el b/emacs/libs/minad.el new file mode 100644 index 0000000..3b9ca4e --- /dev/null +++ b/emacs/libs/minad.el @@ -0,0 +1,89 @@ +;;; package --- Summary + +;;; Commentary: + +;; This loads vertico, corfu, orderless, etc. +;; All from https://github.com/minad + + +;;; Code: + +(require 'package) + +(use-package corfu + :ensure t + :custom + (corfu-cycle t) + :hook ((prog-mode . corfu-mode) + (shell-mode . corfu-mode) + (eshell-mode . corfu-mode)) + :init (global-corfu-mode)) + +(use-package orderless + :ensure t + :init + ;; Configure a custom style dispatcher (see the Consult wiki) + (setq orderless-style-dispatchers nil + orderless-component-separator #'orderless-escapable-split-on-space) + (setq completion-styles '(orderless basic) + completion-category-defaults nil + completion-category-overrides '((file (styles basic partial-completion))))) + +(setq completion-styles '(orderless basic)) + + +;; Use dabbrev with Corfu! +(use-package dabbrev + ;; Swap M-/ and C-M-/ + :bind (("M-/" . dabbrev-expand) + ("C-M-/" . dabbrev-completion))) + +;; Enable richer annotations using the Marginalia package +(use-package marginalia + :ensure t + ;; Either bind `marginalia-cycle` globally or only in the minibuffer + ;; :bind (("M-A" . marginalia-cycle) + ;; :map minibuffer-local-map + ;; ("M-A" . marginalia-cycle)) + + ;; The :init configuration is always executed (Not lazy!) + :init + + ;; Must be in the :init section of use-package such that the mode gets + ;; enabled right away. Note that this forces loading the package. + (marginalia-mode)) + +(use-package vertico + :ensure t + ;; Special recipe to load extensions conveniently + :straight (vertico :files (:defaults "extensions/*") + :includes (vertico-indexed + vertico-flat + vertico-grid + vertico-mouse + vertico-quick + vertico-buffer + vertico-repeat + vertico-reverse + vertico-directory + vertico-multiform + vertico-unobtrusive + )) + ;; :general + ;; (:keymaps 'vertico-map + ;; "<tab>" #'vertico-insert ; Choose selected candidate + ;; "<escape>" #'minibuffer-keyboard-quit ; Close minibuffer + ;; ;; NOTE 2022-02-05: Cycle through candidate groups + ;; "C-M-n" #'vertico-next-group + ;; "C-M-p" #'vertico-previous-group) + :custom + (vertico-count 12) ; Number of candidates to display + (vertico-resize t) + (vertico-cycle nil) ; Go from last to first candidate and first to last (cycle)? + :config + (vertico-mode) + (vertico-reverse-mode)) + +(provide 'minad) + +;;; minad.el ends here diff --git a/emacs/libs/nano-emacs b/emacs/libs/nano-emacs new file mode 160000 +Subproject 185894da71aeab33e52a1bedcde6cea4b148436 diff --git a/emacs/libs/penumbra-theme.el b/emacs/libs/penumbra-theme.el new file mode 100644 index 0000000..e8e6acf --- /dev/null +++ b/emacs/libs/penumbra-theme.el @@ -0,0 +1,512 @@ +;;; penumbra-theme.el --- A color theme based on Acme & Sam from Plan 9 -*- lexical-binding: t; -*- + +;; Copyright (C) 2020 Ian Yi-En Pan + +;; Author: Ian Y.E. Pan +;; URL: https://github.com/ianpan870102/acme-emacs-theme +;; Version: 1.0.0 + +;; 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 <http://www.gnu.org/licenses/>. + +;;; Commentary: +;; A color theme for Emacs based on Acme & Sam from Plan 9 + +;;; Credits: +;; This theme was modified from John Louis Del Rosario's plan9-theme.el + +;;; Code: + +(defgroup penumbra-theme nil + "Options for penumbra theme." + :group 'faces) + +(defcustom penumbra-theme-black-fg nil + "If non-nil, foreground will be pure black instead of the default dark grey." + :group 'penumbra-theme + :type 'boolean) + +(deftheme penumbra "A color theme based on Penumbra & Sam") + +;;; Color palette + +(let ((class '((class color) (min-colors 89))) + (bg "#FFF7ED") ; default bg + (bg-alt "#FFFDFB") + (bg-dark "#F2E6D4") + (fg (if penumbra-theme-black-fg "#000000" "#24272B")) ; default fg + (fg-alt "#B8B09A") + (fg-dark "#988D6D") + (fg-light "#CCCCB7") + (highlight "#E8EB98") + (highlight-alt "#E8EBC8") + + ;; Standardized palette + (penumbra-cyan "#00B3C2") + (penumbra-cyan-light "#00C4D7") + (penumbra-red "#DF7F78") + (penumbra-red-light "#F58C81") + (penumbra-yellow "#9CA748") + (penumbra-yellow-light "#A9B852") + (penumbra-green "#50B584") + (penumbra-green-alt "#54C794") + (penumbra-green-light "#54C794") + (penumbra-blue "#61A3E6") + (penumbra-blue-light "#6EB2FD") + (penumbra-purple "#A48FE1") + (penumbra-purple-light "#B69CF6")) + +;;; Theme Faces + (custom-theme-set-faces + 'penumbra + +;;;; Built-in + +;;;;; basic coloring + `(button ((t (:underline t)))) + `(link ((t (:foreground "#0066cc":weight normal)))) + `(highlight ((t (:inherit link :underline t)))) ; link hover + `(link-visited ((t (:foreground ,penumbra-purple :underline t :weight normal)))) + `(default ((t (:foreground ,fg :background ,bg)))) + `(cursor ((t (:foreground ,bg :background ,fg)))) + `(escape-glyph ((t (:foreground ,penumbra-cyan-light :bold nil)))) + `(fringe ((t (:foreground ,fg :background ,bg)))) + `(line-number ((t (:foreground ,fg :background ,bg-alt)))) + `(line-number-current-line ((t (:foreground ,fg :background ,bg-alt)))) + `(header-line ((t (:foreground ,fg :background ,penumbra-blue-light :box t)))) + `(success ((t (:foreground ,penumbra-green :weight normal)))) + `(warning ((t (:foreground ,penumbra-red :weight normal)))) + `(error ((t (:foreground ,penumbra-red :bold t)))) + +;;;;; compilation + `(compilation-column-face ((t (:foreground ,penumbra-yellow :background ,penumbra-yellow-light)))) + `(compilation-column-number ((t (:foreground ,penumbra-yellow :background ,penumbra-yellow-light)))) + `(compilation-error-face ((t (:foreground ,penumbra-red :weight normal :underline t)))) + `(compilation-face ((t (:foreground ,fg)))) + `(compilation-info-face ((t (:foreground ,penumbra-blue)))) + `(compilation-info ((t (:foreground ,penumbra-blue :underline t)))) + `(compilation-line-face ((t (:foreground ,penumbra-purple)))) + `(compilation-line-number ((t (:foreground ,penumbra-yellow :background ,penumbra-yellow-light)))) + `(compilation-message-face ((t (:foreground ,penumbra-blue)))) + `(compilation-warning-face ((t (:foreground ,penumbra-yellow :weight normal :underline t)))) + `(compilation-mode-line-exit ((t (:foreground ,penumbra-cyan :weight normal)))) + `(compilation-mode-line-fail ((t (:foreground ,penumbra-red :weight normal)))) + `(compilation-mode-line-run ((t (:foreground ,penumbra-purple :weight normal)))) + +;;;;; grep + `(grep-context-face ((t (:foreground ,fg-alt)))) + `(grep-error-face ((t (:foreground ,penumbra-red :weight normal :underline t)))) + `(grep-hit-face ((t (:foreground ,penumbra-purple :weight normal)))) + `(grep-match-face ((t (:foreground ,penumbra-cyan :weight normal)))) + `(match ((t (:background ,penumbra-cyan :foreground ,penumbra-cyan-light)))) + +;;;;; ag + `(ag-hit-face ((t (:foreground ,penumbra-green :weight normal)))) + `(ag-match-face ((t (:foreground ,penumbra-cyan :background ,penumbra-cyan-light :weight normal)))) + +;;;;; isearch + `(isearch ((t (:foreground ,fg :weight normal :background ,penumbra-cyan-light)))) + `(isearch-fail ((t (:foreground ,fg :weight normal :background ,penumbra-red)))) + `(lazy-highlight ((t (:foreground ,fg :weight normal :background ,penumbra-blue-light)))) + + `(menu ((t (:foreground ,bg :background ,fg)))) + `(minibuffer-prompt ((t (:foreground ,fg :weight normal)))) + `(region ((,class (:foreground ,fg :background ,highlight :extend nil)))) + `(secondary-selection ((t (:background ,penumbra-green-light)))) + `(trailing-whitespace ((t (:background ,penumbra-red-light)))) + `(vertical-border ((t (:foreground ,penumbra-cyan)))) + +;;;;; font lock + `(font-lock-builtin-face ((t (:foreground ,fg :weight normal)))) + `(font-lock-function-name-face ((t (:foreground ,fg :weight normal)))) + `(font-lock-string-face ((t (:foreground ,penumbra-red)))) + `(font-lock-keyword-face ((t (:foreground ,penumbra-blue :weight bold)))) ; if, else, for, while, return... + `(font-lock-type-face ((t (:foreground ,fg :weight bold)))) ; int, float, string, void... + `(font-lock-constant-face ((t (:foreground ,fg :weight bold)))) ; NULL, nullptr, true, false... + `(font-lock-variable-name-face ((t (:foreground ,fg :weight normal)))) + `(font-lock-comment-face ((t (:foreground ,penumbra-green :italic nil)))) + `(font-lock-comment-delimiter-face ((t (:foreground ,penumbra-green :italic nil)))) + `(font-lock-doc-face ((t (:foreground ,penumbra-yellow :italic nil)))) + `(font-lock-negation-char-face ((t (:foreground ,penumbra-red :weight normal)))) + `(font-lock-preprocessor-face ((t (:foreground ,penumbra-red :weight normal)))) + `(font-lock-regexp-grouping-construct ((t (:foreground ,penumbra-purple :weight normal)))) + `(font-lock-regexp-grouping-backslash ((t (:foreground ,penumbra-purple :weight normal)))) + `(font-lock-warning-face ((t (:foreground ,penumbra-red :weight normal)))) + +;;;;; table + `(table-cell ((t (:background ,bg-alt)))) + +;;;;; ledger + `(ledger-font-directive-face ((t (:foreground ,penumbra-cyan)))) + `(ledger-font-periodic-xact-face ((t (:inherit ledger-font-directive-face)))) + `(ledger-font-posting-account-face ((t (:foreground ,penumbra-blue)))) + `(ledger-font-posting-amount-face ((t (:foreground ,penumbra-red)))) + `(ledger-font-posting-date-face ((t (:foreground ,penumbra-red :weight normal)))) + `(ledger-font-payee-uncleared-face ((t (:foreground ,penumbra-purple)))) + `(ledger-font-payee-cleared-face ((t (:foreground ,fg)))) + `(ledger-font-payee-pending-face ((t (:foreground ,penumbra-yellow)))) + `(ledger-font-xact-highlight-face ((t (:background ,bg-alt)))) + +;;;; Third-party + + +;;;;; anzu + `(anzu-mode-line ((t (:foreground ,penumbra-yellow :background ,penumbra-yellow-light :weight normal)))) + +;;;;; clojure-mode + `(clojure-interop-method-face ((t (:inherit font-lock-function-name-face)))) + +;;;;; clojure-test-mode + `(clojure-test-failure-face ((t (:foreground ,penumbra-red :weight normal :underline t)))) + `(clojure-test-error-face ((t (:foreground ,penumbra-red :weight normal :underline t)))) + `(clojure-test-success-face ((t (:foreground ,penumbra-green :weight normal :underline t)))) + +;;;;; diff + `(diff-added ((,class (:foreground ,fg :background ,penumbra-green-light)) + (t (:foreground ,fg :background ,penumbra-green-light)))) + `(diff-changed ((t (:foreground ,penumbra-yellow)))) + `(diff-context ((t (:foreground ,fg)))) + `(diff-removed ((,class (:foreground ,fg :background ,penumbra-red-light)) + (t (:foreground ,fg :background ,penumbra-red-light)))) + `(diff-refine-added ((t :inherit diff-added :background ,penumbra-green-light :weight bold :underline t))) + `(diff-refine-change ((t :inherit diff-changed :weight normal))) + `(diff-refine-removed ((t :inherit diff-removed :background ,penumbra-red-light :weight bold :underline t))) + `(diff-header ((,class (:foreground ,fg :weight normal)) + (t (:foreground ,penumbra-purple-light :weight normal)))) + `(diff-file-header ((,class (:foreground ,fg :background ,penumbra-cyan-light :weight normal)) + (t (:foreground ,fg :background ,penumbra-cyan-light :weight normal)))) + `(diff-hunk-header ((,class (:foreground ,penumbra-green :weight normal)) + (t (:foreground ,penumbra-green :weight normal)))) +;;;;; dired/dired+/dired-subtree + `(dired-directory ((t (:foreground ,penumbra-blue :weight bold)))) + `(diredp-display-msg ((t (:foreground ,penumbra-blue)))) + `(diredp-compressed-file-suffix ((t (:foreground ,penumbra-purple)))) + `(diredp-date-time ((t (:foreground ,penumbra-green)))) + `(diredp-deletion ((t (:foreground ,penumbra-red)))) + `(diredp-deletion-file-name ((t (:foreground ,penumbra-red)))) + `(diredp-dir-heading ((t (:foreground ,penumbra-blue :background ,penumbra-blue-light :weight bold)))) + `(diredp-dir-priv ((t (:foreground ,penumbra-blue)))) + `(diredp-exec-priv ((t (:foreground ,penumbra-yellow)))) + `(diredp-executable-tag ((t (:foreground ,penumbra-yellow)))) + `(diredp-file-name ((t (:foreground ,fg)))) + `(diredp-file-suffix ((t (:foreground ,penumbra-yellow)))) + `(diredp-flag-mark ((t (:foreground ,penumbra-cyan)))) + `(diredp-flag-mark-line ((t (:foreground ,penumbra-cyan)))) + `(diredp-ignored-file-name ((t (:foreground ,fg-light)))) + `(diredp-link-priv ((t (:foreground ,penumbra-purple)))) + `(diredp-mode-line-flagged ((t (:foreground ,penumbra-yellow)))) + `(diredp-mode-line-marked ((t (:foreground ,penumbra-yellow)))) + `(diredp-no-priv ((t (:foreground ,fg)))) + `(diredp-number ((t (:foreground ,penumbra-blue)))) + `(diredp-other-priv ((t (:foreground ,fg)))) + `(diredp-rare-priv ((t (:foreground ,fg)))) + `(diredp-read-priv ((t (:foreground ,fg)))) + `(diredp-symlink ((t (:foreground ,fg :background ,penumbra-blue-light)))) + `(diredp-write-priv ((t (:foreground ,fg)))) + `(diredp-dir-name ((t (:foreground ,penumbra-blue :weight bold)))) + `(dired-subtree-depth-1-face ((t (:background ,bg)))) + `(dired-subtree-depth-2-face ((t (:background ,bg)))) + `(dired-subtree-depth-3-face ((t (:background ,bg)))) + +;;;;; elfeed + `(elfeed-search-date-face ((t (:foreground ,penumbra-blue)))) + `(elfeed-search-title-face ((t (:foreground ,fg)))) + `(elfeed-search-unread-title-face ((t (:foreground ,fg)))) + `(elfeed-search-feed-face ((t (:foreground ,penumbra-green)))) + `(elfeed-search-tag-face ((t (:foreground ,penumbra-red)))) + `(elfeed-search-unread-count-face ((t (:foreground ,fg)))) + +;;;;; erc + `(erc-default-face ((t (:foreground ,fg)))) + `(erc-header-line ((t (:inherit header-line)))) + `(erc-action-face ((t (:inherit erc-default-face)))) + `(erc-bold-face ((t (:inherit erc-default-face :weight normal)))) + `(erc-underline-face ((t (:underline t)))) + `(erc-error-face ((t (:inherit font-lock-warning-face)))) + `(erc-prompt-face ((t (:foreground ,penumbra-green :background ,penumbra-green-light :weight normal)))) + `(erc-timestamp-face ((t (:foreground ,penumbra-green :background ,penumbra-green-light)))) + `(erc-direct-msg-face ((t (:inherit erc-default)))) + `(erc-notice-face ((t (:foreground ,fg-light)))) + `(erc-highlight-face ((t (:background ,highlight)))) + `(erc-input-face ((t (:foreground ,fg :background ,bg-alt)))) + `(erc-current-nick-face ((t (:foreground ,fg :background ,penumbra-cyan-light :weight normal + :box (:line-width 1 :style released-button))))) + `(erc-nick-default-face ((t (:weight normal :background ,bg-alt)))) + `(erc-my-nick-face ((t (:foreground ,fg :background ,penumbra-cyan-light :weight normal + :box (:line-width 1 :style released-button))))) + `(erc-nick-msg-face ((t (:inherit erc-default)))) + `(erc-fool-face ((t (:inherit erc-default)))) + `(erc-pal-face ((t (:foreground ,penumbra-purple :weight normal)))) + `(erc-dangerous-host-face ((t (:inherit font-lock-warning-face)))) + `(erc-keyword-face ((t (:foreground ,penumbra-yellow :weight normal)))) + + ;;;;; evil + `(evil-search-highlight-persist-highlight-face ((t (:inherit lazy-highlight)))) + +;;;;; flx + `(flx-highlight-face ((t (:foreground ,penumbra-yellow :background ,penumbra-green-light + :weight normal :underline t)))) + +;;;;; company + `(company-tooltip ((t (:background ,penumbra-blue-light)))) + `(company-tooltip-selection ((t (:background ,penumbra-cyan-light)))) + `(company-tooltip-common ((t (:foreground ,penumbra-blue :bold t)))) + `(company-tooltip-annotation ((t (:foreground ,penumbra-yellow :italic t)))) ; parameter hints etc. + `(company-scrollbar-fg ((t (:background ,penumbra-cyan)))) + `(company-scrollbar-bg ((t (:background ,penumbra-cyan-light)))) + `(company-preview-common ((t (:foreground ,fg :background ,penumbra-cyan-light)))) + +;;;;; highlight-symbol + `(highlight-symbol-face ((t (:background ,bg-alt)))) + +;;;;; highlight-numbers + `(highlight-numbers-number ((t (:foreground ,penumbra-blue)))) + +;;;;; highlight-operators + `(highlight-operators-face ((t (:foreground ,fg)))) + +;;;;; hl-todo + `(hl-todo ((t (:inverse-video t)))) + +;;;;; hl-line-mode + `(hl-line ((,class (:background ,bg-alt)))) + +;;;;; hl-sexp + `(hl-sexp-face ((,class (:background ,bg-alt)))) + +;;;;; ido-mode + `(ido-first-match ((t (:foreground ,fg :weight normal)))) + `(ido-only-match ((t (:foreground ,fg :weight normal)))) + `(ido-subdir ((t (:foreground ,penumbra-blue)))) + `(ido-indicator ((t (:foreground ,penumbra-yellow)))) + +;;;;; ido-vertical + `(ido-vertical-first-match-face ((t (:foreground ,fg :background ,penumbra-cyan-light :weight normal)))) + `(ido-vertical-only-match-face ((t (:foreground ,penumbra-red :background ,penumbra-red-light :weight normal)))) + `(ido-vertical-match-face ((t (:foreground ,fg :background ,penumbra-green-light + :weight normal :underline t)))) + +;;;;; indent-guide + `(indent-guide-face ((t (:foreground ,highlight)))) + +;;;;; ivy + `(ivy-current-match ((t (:background ,penumbra-blue-light :underline t :extend t)))) + `(ivy-minibuffer-match-face-1 ((t (:background ,bg-alt)))) + `(ivy-minibuffer-match-face-2 ((t (:background ,penumbra-cyan-light)))) + `(ivy-minibuffer-match-face-3 ((t (:background ,penumbra-purple-light)))) + `(ivy-minibuffer-match-face-3 ((t (:background ,penumbra-blue-light)))) + +;;;;; js2-mode + `(js2-warning ((t (:underline ,penumbra-yellow)))) + `(js2-error ((t (:foreground ,penumbra-red :weight normal)))) + `(js2-jsdoc-tag ((t (:foreground ,penumbra-purple)))) + `(js2-jsdoc-type ((t (:foreground ,penumbra-blue)))) + `(js2-jsdoc-value ((t (:foreground ,penumbra-cyan)))) + `(js2-function-param ((t (:foreground ,fg)))) + `(js2-external-variable ((t (:foreground ,penumbra-cyan)))) + +;;;;; linum-mode + `(linum ((t (:foreground ,fg-light)))) + +;;;;; lsp-mode + `(lsp-face-highlight-textual ((t (:background ,bg-dark)))) + `(lsp-face-highlight-read ((t (:background ,penumbra-purple-light)))) + `(lsp-face-highlight-write ((t (:background ,penumbra-green-light)))) + +;;;;; magit + `(magit-section-heading ((t (:foreground ,penumbra-cyan :background ,penumbra-blue-light + :weight normal :underline t)))) + `(magit-section-highlight ((t (:background ,bg-alt)))) + `(magit-section-heading-selection ((t (:background ,highlight)))) + `(magit-filename ((t (:foreground ,fg)))) + `(magit-hash ((t (:foreground ,penumbra-yellow :weight normal)))) + `(magit-tag ((t (:foreground ,penumbra-purple :weight normal)))) + `(magit-refname ((t (:foreground ,penumbra-purple :weight normal)))) + `(magit-head ((t (:foreground ,penumbra-green :weight normal)))) + `(magit-branch-local ((t (:foreground ,penumbra-blue :background ,penumbra-blue-light + :weight normal)))) + `(magit-branch-remote ((t (:foreground ,penumbra-green :background ,penumbra-green-light + :weight normal)))) + `(magit-branch-current ((t (:foreground ,penumbra-cyan :background ,penumbra-cyan-light + :weight normal + :box (:line-width 1 :color ,penumbra-cyan))))) + `(magit-diff-file-heading ((t (:foreground ,fg :weight normal)))) + `(magit-diff-file-heading-highlight ((t (:background ,bg-alt)))) + `(magit-diff-file-heading-selection ((t (:foreground ,penumbra-red :background ,highlight)))) + `(magit-diff-hunk-heading ((t (:foreground ,penumbra-blue :background ,penumbra-blue-light :weight normal :underline t)))) + `(magit-diff-hunk-heading-highlight ((t (:background ,penumbra-cyan-light)))) + `(magit-diff-added ((t (:foreground ,penumbra-green :background ,penumbra-green-light)))) + `(magit-diff-removed ((t (:foreground ,penumbra-red :background ,penumbra-red-light)))) + `(magit-diff-context ((t (:foreground ,fg-dark :background nil)))) + `(magit-diff-added-highlight ((t (:foreground ,penumbra-green :background ,penumbra-green-light)))) + `(magit-diff-removed-highlight ((t (:foreground ,penumbra-red :background ,penumbra-red-light)))) + `(magit-diff-context-highlight ((t (:foreground ,fg-dark :background ,bg-alt)))) + `(magit-diffstat-added ((t (:foreground ,penumbra-green :background ,penumbra-green-light :weight normal)))) + `(magit-diffstat-removed ((t (:foreground ,penumbra-red :background ,penumbra-red-light :weight normal)))) + `(magit-log-author ((t (:foreground ,penumbra-blue :weight normal)))) + `(magit-log-date ((t (:foreground ,penumbra-purple :weight normal)))) + `(magit-log-graph ((t (:foreground ,penumbra-red :weight normal)))) + `(magit-blame-heading ((t (:foreground ,fg-dark :background ,bg-alt)))) + +;;;;; paren-face + `(parenthesis ((t (:foreground "#CCCCB7")))) + +;;;;; project-explorer + `(pe/file-face ((t (:foreground ,fg)))) + `(pe/directory-face ((t (:foreground ,penumbra-blue :weight normal)))) + +;;;;; rainbow-delimiters + `(rainbow-delimiters-depth-1-face ((t (:foreground ,penumbra-green)))) + `(rainbow-delimiters-depth-2-face ((t (:foreground ,penumbra-blue)))) + `(rainbow-delimiters-depth-3-face ((t (:foreground ,penumbra-red)))) + +;;;;; show-paren + `(show-paren-mismatch ((t (:foreground ,penumbra-yellow :background ,penumbra-red :weight normal)))) + `(show-paren-match ((t (:foreground ,fg :background ,penumbra-cyan-light :weight normal)))) + +;;;;; mode-line/sml-mode-line + `(mode-line ((,class (:foreground ,fg :background ,penumbra-blue-light :box t)))) + `(mode-line-inactive ((t (:foreground ,fg :background ,bg-dark :box t)))) + `(mode-line-buffer-id ((t (:foreground ,fg :weight bold)))) ; associated buffer/file name + `(sml/global ((t (:foreground ,fg)))) + `(sml/modes ((t (:foreground ,penumbra-green :background ,penumbra-green-light)))) + `(sml/filename ((t (:foreground ,penumbra-red)))) + `(sml/folder ((t (:foreground ,fg)))) + `(sml/prefix ((t (:foreground ,fg)))) + `(sml/read-only ((t (:foreground ,fg)))) + `(sml/modified ((t (:foreground ,penumbra-red :weight normal)))) + `(sml/outside-modified ((t (:background ,penumbra-red :foreground ,penumbra-red-light :weight normal)))) + `(sml/line-number ((t (:foreground ,fg :weight normal)))) + `(sml/col-number ((t (:foreground ,fg :weight normal)))) + `(sml/vc ((t (:foreground ,fg :weight normal)))) + `(sml/vc-edited ((t (:foreground ,penumbra-red :weight normal)))) + `(sml/git ((t (:foreground ,fg :weight normal)))) + +;;;;; sh + `(sh-heredoc-face ((t (:foreground ,penumbra-purple)))) + +;;;;; web-mode + `(web-mode-builtin-face ((t (:inherit ,font-lock-builtin-face)))) + `(web-mode-comment-face ((t (:inherit ,font-lock-comment-face)))) + `(web-mode-constant-face ((t (:inherit ,font-lock-constant-face)))) + `(web-mode-doctype-face ((t (:inherit ,font-lock-comment-face)))) + `(web-mode-folded-face ((t (:underline t)))) + `(web-mode-function-name-face ((t (:foreground ,fg :weight normal)))) + `(web-mode-html-attr-name-face ((t (:foreground ,fg)))) + `(web-mode-html-attr-value-face ((t (:inherit ,font-lock-string-face)))) + `(web-mode-html-tag-face ((t (:foreground ,penumbra-blue)))) + `(web-mode-keyword-face ((t (:inherit ,font-lock-keyword-face)))) + `(web-mode-preprocessor-face ((t (:inherit ,font-lock-preprocessor-face)))) + `(web-mode-string-face ((t (:inherit ,font-lock-string-face)))) + `(web-mode-type-face ((t (:inherit ,font-lock-type-face)))) + `(web-mode-variable-name-face ((t (:inherit ,font-lock-variable-name-face)))) + `(web-mode-server-background-face ((t (:background ,penumbra-green-light)))) + `(web-mode-server-comment-face ((t (:inherit web-mode-comment-face)))) + `(web-mode-server-string-face ((t (:foreground ,penumbra-red)))) + `(web-mode-symbol-face ((t (:inherit font-lock-constant-face)))) + `(web-mode-warning-face ((t (:inherit font-lock-warning-face)))) + `(web-mode-whitespaces-face ((t (:background ,penumbra-red-light)))) + `(web-mode-block-face ((t (:background ,penumbra-green-light)))) + `(web-mode-current-element-highlight-face ((t (:foreground ,fg :background ,penumbra-blue-light)))) + `(web-mode-json-key-face ((,class (:inherit font-lock-string-face)))) + `(web-mode-json-context-face ((,class (:inherit font-lock-string-face :bold t)))) + +;;;;; which-func-mode + `(which-func ((t (:foreground ,penumbra-purple :background ,penumbra-purple-light)))) + +;;;;; yascroll + `(yascroll:thumb-text-area ((t (:background ,highlight)))) + `(yascroll:thumb-fringe ((t (:background ,bg :foreground ,bg + :box (:line-width 1 :style released-button))))) + +;;;;; Org + `(org-level-1 ((t (:background ,penumbra-blue-light :foreground ,penumbra-blue :weight bold :overline t)))) + `(org-level-2 ((t (:background ,penumbra-blue-light :foreground ,penumbra-cyan :weight bold :overline t)))) + `(org-level-3 ((t (:background ,penumbra-blue-light :foreground ,penumbra-blue :weight bold :overline t)))) + `(org-level-4 ((t (:background ,penumbra-blue-light :foreground ,penumbra-cyan)))) + `(org-level-5 ((t (:background ,penumbra-blue-light :foreground ,penumbra-blue)))) + `(org-level-6 ((t (:background ,penumbra-blue-light :foreground ,penumbra-cyan)))) + `(org-level-7 ((t (:background ,penumbra-blue-light :foreground ,penumbra-blue)))) + `(org-level-8 ((t (:background ,penumbra-blue-light :foreground ,penumbra-cyan)))) + `(org-document-title ((t (:height 1.2 :foreground ,penumbra-blue :weight bold :underline t)))) ; #TITLE + `(org-meta-line ((t (:foreground ,penumbra-green)))) + `(org-document-info ((t (:foreground ,penumbra-cyan :weight normal)))) + `(org-document-info-keyword ((t (:foreground ,penumbra-cyan)))) + `(org-todo ((t (:foreground ,penumbra-yellow :background ,bg-alt :weight normal :box (:line-width 1 :style released-button))))) + `(org-done ((t (:foreground ,penumbra-green :background ,penumbra-green-light :weight normal :box (:style released-button))))) + `(org-date ((t (:foreground ,penumbra-purple)))) + `(org-table ((t (:foreground ,penumbra-purple)))) + `(org-formula ((t (:foreground ,penumbra-blue :background ,bg-alt)))) + `(org-code ((t (:foreground ,penumbra-red :background ,bg-alt)))) + `(org-verbatim ((t (:foreground ,fg :background ,bg-alt :underline t)))) + `(org-special-keyword ((t (:foreground ,penumbra-cyan)))) + `(org-agenda-date ((t (:foreground ,penumbra-cyan)))) + `(org-agenda-structure ((t (:foreground ,penumbra-purple)))) + `(org-block ((t (:foreground ,fg :background ,bg-alt :extend t)))) + `(org-block-background ((t (:background ,bg-alt :extend t)))) + `(org-block-begin-line ((t (:foreground ,fg-alt :background ,bg-dark :italic t :extend t)))) + `(org-block-end-line ((t (:foreground ,fg-alt :background ,bg-dark :italic t :extend t)))) + +;;;;; origami + `(origami-fold-replacement-face ((t (:foreground ,penumbra-red :background ,penumbra-red-light + :box (:line-width -1))))) + +;;;;; git-gutter + `(git-gutter:added ((t (:background ,penumbra-green-alt :foreground ,penumbra-green-alt :weight normal)))) + `(git-gutter:deleted ((t (:background ,penumbra-red :foreground ,penumbra-red :weight normal)))) + `(git-gutter:modified ((t (:background ,penumbra-yellow :foreground ,penumbra-yellow :weight normal)))) + `(git-gutter-fr:added ((t (:background ,penumbra-green-alt :foreground ,penumbra-green-alt :weight normal)))) + `(git-gutter-fr:deleted ((t (:background ,penumbra-red :foreground ,penumbra-red :weight normal)))) + `(git-gutter-fr:modified ((t (:background ,penumbra-yellow :foreground ,penumbra-yellow :weight normal)))) + +;;;;; diff-hl + `(diff-hl-insert ((t (:background ,penumbra-green-alt :foreground ,penumbra-green-alt)))) + `(diff-hl-delete ((t (:background ,penumbra-red :foreground ,penumbra-red)))) + `(diff-hl-change ((t (:background ,penumbra-yellow :foreground ,penumbra-yellow)))) + +;;;;; mu4e, mail + `(mu4e-header-highlight-face ((t (:background ,highlight)))) + `(mu4e-unread-face ((t (:foreground ,penumbra-blue :weight normal)))) + `(mu4e-flagged-face ((t (:foreground ,penumbra-red :background ,penumbra-red-light :weight normal)))) + `(mu4e-compose-separator-face ((t (:foreground ,penumbra-green)))) + `(mu4e-header-value-face ((t (:foreground ,fg)))) + `(message-header-name ((t (:foreground ,penumbra-purple :weight normal)))) + `(message-header-to ((t (:foreground ,penumbra-blue)))) + `(message-header-subject ((t (:foreground ,penumbra-blue)))) + `(message-header-other ((t (:foreground ,penumbra-blue)))) + `(message-cited-text ((t (:inherit font-lock-comment-face)))) + +;;;;; term-mode (vterm too) + `(term ((,class (:foreground ,fg :background ,bg)))) + `(term-color-black ((,class (:foreground ,fg :background ,fg)))) + `(term-color-blue ((,class (:foreground ,penumbra-blue :background ,penumbra-blue)))) + `(term-color-red ((,class (:foreground ,penumbra-red :background ,penumbra-red)))) + `(term-color-green ((,class (:foreground ,penumbra-green :background ,penumbra-green)))) + `(term-color-yellow ((,class (:foreground ,penumbra-yellow :background ,penumbra-yellow)))) + `(term-color-magenta ((,class (:foreground ,penumbra-purple :background ,penumbra-purple)))) + `(term-color-cyan ((,class (:foreground ,penumbra-cyan :background ,penumbra-cyan)))) + `(term-color-white ((,class (:foreground ,fg :background ,fg)))) + +;;;;; fill-column-indicator + `(fci-rule-color ((t (:foreground ,highlight-alt)))) + `(fill-column-indicator ((t (:foreground ,highlight-alt)))))) + +;;;###autoload +(when (and (boundp 'custom-theme-load-path) load-file-name) + (add-to-list 'custom-theme-load-path + (file-name-as-directory (file-name-directory load-file-name)))) + +(provide-theme 'penumbra) +(provide 'penumbra-theme) + +;;; penumbra-theme.el ends here diff --git a/emacs/libs/slime b/emacs/libs/slime new file mode 160000 +Subproject 6ef28864d4a6b4d9390dbd0cac64f2a56582682 diff --git a/emacs/libs/utils.el b/emacs/libs/utils.el new file mode 100644 index 0000000..df0c464 --- /dev/null +++ b/emacs/libs/utils.el @@ -0,0 +1,17 @@ +;;; utils.el --- Utility package +;;; Commentary: +;; None + +;;; Code: +(require 'org-table) + +(defun csv-to-table (file) + "Turn a csv with ; separator in FILE to table." + (with-temp-buffer + (erase-buffer) + (insert-file-contents file nil 0 500) + (org-table-convert-region (point-min) (point-max) ";") + (buffer-string))) + +(provide 'utils) +;;; utils.el ends here |