hamacs/ha-display.org
Howard Abrams a9ce3c1d27 Fixed a "race condition" startup bug
I wanted to have an icon associated with the major mode hydra, but the
display system wasn't available at this time. So, now we can override it.
2024-08-10 21:58:05 -07:00

535 lines
22 KiB
Org Mode
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#+title: Emacs Graphical Display Configuration
#+author: Howard X. Abrams
#+date: 2020-09-10
#+tags: emacs macos
A literate programming file to configure the Emacs UI.
#+begin_src emacs-lisp :exports none
;;; ha-display --- Emacs UI configuration. -*- lexical-binding: t; -*-
;;
;; © 2020-2023 Howard X. Abrams
;; Licensed under a Creative Commons Attribution 4.0 International License.
;; See http://creativecommons.org/licenses/by/4.0/
;;
;; Author: Howard X. Abrams <http://gitlab.com/howardabrams>
;; Maintainer: Howard X. Abrams
;; Created: September 10, 2020
;;
;; This file is not part of GNU Emacs.
;;
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
;; ~/other/hamacs/ha-display.org
;; Using `find-file-at-point', and tangle the file to recreate this one .
;;
;;; Code:
#+end_src
Let's turn off the menu and other settings:
#+begin_src emacs-lisp
(when (display-graphic-p)
(context-menu-mode 1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(horizontal-scroll-bar-mode -1)
(setq visible-bell 1
frame-inhibit-implied-resize t))
#+end_src
And lets make this Emacs look more like a fancy IDE with [[https://github.com/domtronn/all-the-icons.el][all-the-icons]]:
#+begin_src emacs-lisp
(use-package all-the-icons
:if (display-graphic-p)
:config
(setq major-mode-hydra-title-generator
'(lambda (mode)
(let ((title (thread-last mode
(symbol-name)
(string-replace "-" " ")
(string-replace " mode" "")
(s-titleize))))
(s-concat ; (s-repeat 5 " ")
(all-the-icons-icon-for-mode mode :v-adjust 0.05)
" " title " Commands")))))
#+end_src
This also expands the [[file:ha-config.org::*Leader Sequences][Major Mode Hydra]] title sequence with a pretty icon.
* Mode Line
Let's install and load some of packages from the [[https://github.com/hlissner/doom-emacs][Doom Emacs]] project, like [[https://github.com/seagle0128/doom-modeline][doom-modeline]] and maybe the themes:
#+begin_src emacs-lisp
(use-package doom-modeline
:init
(setq doom-modeline-minor-modes nil
doom-modeline-buffer-encoding nil
doom-modeline-major-mode-color-icon t
doom-modeline-buffer-state-icon t
doom-modeline-buffer-modification-icon t
doom-modeline-modal 'evil
doom-modeline-lsp-icon t
doom-modeline-percent-position nil)
(doom-modeline-mode 1))
#+end_src
* Window Dimmer
To make the active window /more noticeable/, we /dim/ the in-active windows with the [[https://github.com/gonewest818/dimmer.el][dimmer project]].
#+begin_src emacs-lisp
(use-package dimmer
:custom
(dimmer-adjustment-mode :foreground)
:config
(dimmer-configure-which-key) ; Do not dim these special windows
(dimmer-configure-hydra)
(dimmer-configure-magit)
(dimmer-mode t))
#+end_src
As an interesting alternative, check out the [[https://www.emacs.dyerdwelling.family/emacs/20240208164549-emacs-selected-window-accent-mode-now-on-melpa/][selected-window-accent]] project.
* Find the Bloody Cursor
Large screen, lots of windows, so where is the cursor? While I used to use =hl-line+=, I found that the prolific [[https://protesilaos.com/][Protesilaos Stavrou]] [[https://protesilaos.com/codelog/2022-03-14-emacs-pulsar-demo/][introduced his Pulsar project]] is just what I need. Specifically, I might /loose the cursor/ and need to have it highlighted (using ~F8~), but also, this automatically highlights the cursor line with specific /actions/ , like changing windows.
#+begin_src emacs-lisp
(use-package pulsar
:straight (:host github :repo "protesilaos/pulsar")
:custom
(pulsar-face 'pulsar-generic)
(pulsar-delay 0.15)
:config
(dolist (built-in-function '(recenter-top-bottom move-to-window-line-top-bottom reposition-window
bookmark-jump other-window delete-window delete-other-windows
forward-page backward-page scroll-up-command scroll-down-command
ha-new-window tab-new tab-close tab-next org-next-visible-heading
org-previous-visible-heading org-forward-heading-same-level
org-backward-heading-same-level outline-backward-same-level
outline-forward-same-level outline-next-visible-heading
outline-previous-visible-heading outline-up-heading))
(add-to-list 'pulsar-pulse-functions built-in-function))
(when (fboundp 'winner-undo)
(add-to-list 'pulsar-pulse-functions 'winner-undo)
(add-to-list 'pulsar-pulse-functions 'winner-redo))
(when (fboundp 'winum-select-window-1)
(add-to-list 'pulsar-pulse-functions 'winum-select-window-1)
(add-to-list 'pulsar-pulse-functions 'winum-select-window-2)
(add-to-list 'pulsar-pulse-functions 'winum-select-window-3)
(add-to-list 'pulsar-pulse-functions 'winum-select-window-4)
(add-to-list 'pulsar-pulse-functions 'winum-select-window-5)
(add-to-list 'pulsar-pulse-functions 'winum-select-window-6)
(add-to-list 'pulsar-pulse-functions 'winum-select-window-7)
(add-to-list 'pulsar-pulse-functions 'winum-select-window-8)
(add-to-list 'pulsar-pulse-functions 'winum-select-window-9))
(when (fboundp 'aw-delete-window)
(add-to-list 'pulsar-pulse-functions 'aw-move-window)
(add-to-list 'pulsar-pulse-functions 'aw-swap-window)
(add-to-list 'pulsar-pulse-functions 'aw-copy-window)
(add-to-list 'pulsar-pulse-functions 'aw-split-window-vert)
(add-to-list 'pulsar-pulse-functions 'aw-split-window-horz)
(add-to-list 'pulsar-pulse-functions 'aw-split-window-fair)
(add-to-list 'pulsar-pulse-functions 'aw-delete-window))
(when (fboundp 'evil-window-right)
(add-to-list 'pulsar-pulse-functions 'evil-window-right)
(add-to-list 'pulsar-pulse-functions 'evil-window-left)
(add-to-list 'pulsar-pulse-functions 'evil-window-up)
(add-to-list 'pulsar-pulse-functions 'evil-window-down))
(pulsar-global-mode 1))
#+end_src
And if I cant find the cursor, and dont want to move it to see it, I can hit a key:
#+begin_src emacs-lisp
(use-package pulsar
:bind ("<f8>" . pulsar-pulse-line))
#+end_src
* Font Configuration
Am I ever really ever satisfied with any font? I regularly change my font based on the monospace du jour... [[http://blogs.adobe.com/typblography/2012/09/source-code-pro.html][Source Code Pro]] is attractive, and has been a staple on every programmers' screen. However, we all want ligatures, [[https://github.com/i-tu/Hasklig][Hasklig]] is a nice font that is thinner and easier to read than [[https://github.com/tonsky/FiraCode][Fira]], but [[https://typeof.net/Iosevka/][Iosevka]] seems to have it all. Oh, Microsoft just gave us [[https://docs.microsoft.com/en-us/windows/terminal/cascadia-code][Cascadia]] and that seems shiny. However, the [[https://github.com/ryanoasis/nerd-fonts][Nerd Font project]] adds the ligatures as well as all the other niceties to a font.
** Choosing a Font
I stole the following idea from [[https://protesilaos.com/dotemacs/#h:9035a1ed-e988-4731-89a5-0d9e302c3dea][Protesilaos Stavrou's dotfile configuration]], and the following should minimally be /readable/:
#+begin_example
| Similarities | Regular |
|--------------+----------------------------|
| ()[]{}<>«»‹› | ABCDEFGHIJKLMNOPQRSTUVWXYZ |
| 6bB8& | abcdefghijklmnopqrstuvwxyz |
| 0ODdoaoOQGC | 0123456789 |
| I1tilIJL | ~!@#$%^&*+ |
| !¡ij | `'"‘’“”.,;:… |
| 5$§SsS5 | ()[]{}—-_=<>/\ |
| 17ZzZ2 | ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ |
| 9gqpG6 | αβγδεζηθικλμνξοπρστυφχψω |
| hnmMN | |
| uvvwWuuwvy | |
| x×X | |
| .,·°% | |
| ¡!¿? | |
| :; | |
| `''"‘’“” | |
| —-~≈=≠+*_ | |
| …⋯ | |
| ... | |
#+end_example
The following is from [[https://source-foundry.github.io/Hack/font-specimen.html][Hack's website]]:
#+begin_src c
// The four boxing wizards jump
#include <stdio.h> // <= quickly.
int main(int argc, char **argv) {
long il1[]={1-2/3.4,5+6==7/8};
int OxFaced=0xBAD||"[{(CQUINE";
unsigned O0,l1,Z2,S5,G6,B8__XY;
printf("@$Hamburgefo%c`",'\n');
return ~7&8^9?0:l1|!"j->k+=*w";
}
#+end_src
To install a font, I use the following command on my Mac:
#+begin_src sh
brew tap homebrew/cask-fonts
brew install --cask font-hack-nerd-font
#+end_src
** Specifying a Font
My /current/ favorite font is actually the top list of fonts that may be installed on my system:
#+begin_src emacs-lisp
(defvar ha-fixed-font
(when window-system
(or
(seq-first
(seq-filter (lambda (font) (when (x-list-fonts font) font))
'("CaskaydiaCove Nerd Font" ; finally found it
;; funky font with litagures and a dotted 0
"Cascadia Code PL"
;; clean font, but no litagures!?
"Hack Nerd Font"
"FiraCode Nerd Font" ; has litagures
"Cousine Nerd Font"
"Iosevka Nerd Font"
"FantasqueSansMono Nerd Font"
"Monoid Nerd Font"
"Hasklig"
"Source Code Pro")))
"monospaced"))
"My fixed width font based on what I have installed.")
#+end_src
I probably don't need to have such a ranking system, as chances are good I have them all installed.
#+begin_src emacs-lisp
(defvar ha-variable-font
(when window-system
(or
(seq-first
(seq-filter (lambda (font) (when (x-list-fonts font) font))
'("SN Pro" ; https://supernotes.app/open-source/sn-pro
"Literata" ; Clean, readable with litagures
;; Next best can be downloaded here:
;; https://fontesk.com/xcharter-typeface/
"XCharter"
"Charter"
;; Interesting idea: "Iosevka Comfy Motion Duo"
"Serif")))
(warn "Cannot find a Serif Font. Install Source Sans Pro."))))
(defvar ha-variable-header-font
(when window-system
(or
(seq-first
(seq-filter (lambda (font) (when (x-list-fonts font) font))
'("SN Pro" "Overpass" "DejaVu Sans"
"Verdana" "Overpass"
"Source Sans Pro"
"Lucida Grande"
"Sans Serif")))
(warn "Cannot find a Sans Serif Font. Install Source Sans Pro."))))
#+end_src
Simple function that gives me the font information based on the size I need. Recently updated after reading [[https://protesilaos.com/codelog/2020-09-05-emacs-note-mixed-font-heights/][this essay]], as I wanted my =fixed-pitch= to scale along with my =variable-pitch= font.
#+begin_src emacs-lisp
(defun ha-set-favorite-font-size (size)
"Set the default font size as well as equalize the fixed and variable fonts."
(let ((fav-font (format "%s-%d" ha-fixed-font size)))
(set-face-attribute 'default nil :font fav-font)
(set-face-attribute 'fixed-pitch nil :family ha-fixed-font :inherit 'default :height 1.0)
(set-face-attribute 'variable-pitch nil :family ha-variable-font :inherit 'default :height 1.2)))
#+end_src
Define /interactive/ functions to quickly adjusting the font size based on my computing scenario:
#+begin_src emacs-lisp
(defun ha-mac-monitor-fontsize ()
"Quickly set reset my font size when I connect my laptop to a monitor on a Mac."
(interactive)
(ha-set-favorite-font-size 13))
(defun ha-linux-monitor-fontsize ()
"Quickly set reset my font size when I connect my laptop to a monitor on Linux."
(interactive)
(ha-set-favorite-font-size 12))
(defun ha-mac-laptop-fontsize ()
"Quickly set reset my font size when I disconnect my laptop to a monitor from a Mac."
(interactive)
(ha-set-favorite-font-size 32))
(defun ha-linux-laptop-fontsize ()
"Quickly set reset my font size when I disconnect my laptop to a monitor from Linux."
(interactive)
(ha-set-favorite-font-size 10))
(defun ha-imac-fontsize ()
"Quickly set reset my font size when I am on my iMac."
(interactive)
(ha-set-favorite-font-size 16))
#+end_src
Which font to choose?
#+begin_src emacs-lisp
(defun font-monitor-size-default ()
"Set the default size according to my preference."
(interactive)
(cond
((eq system-type 'gnu/linux) (ha-linux-monitor-fontsize))
((s-starts-with? "imac" system-name) (ha-imac-fontsize))
(t (ha-mac-monitor-fontsize))))
(defun font-laptop-size-default ()
"Set the default size according to my preference."
(interactive)
(if (eq system-type 'gnu/linux)
(ha-linux-laptop-fontsize)
(ha-mac-laptop-fontsize)))
(font-monitor-size-default)
#+end_src
** Mixed Pitch
[[https://github.com/emacsmirror/mixed-pitch][Mixed pitch]] is a minor mode that enables mixing fixed-pitch (also known as fixed-width or monospace) and variable-pitch (AKA “proportional”) fonts. It tries to be smart about which fonts get which face.
#+begin_src emacs-lisp
(use-package mixed-pitch
:straight (:host github :repo "jabranham/mixed-pitch")
:hook (text-mode . mixed-pitch-mode))
#+end_src
** Zooming or Increasing Font Size
Do we want to increase the size of font in a single window (using =text-scale-increase=), or globally (using my new =font-size-increase=)?
Increase or decrease the set size of the face:
#+begin_src emacs-lisp
(defun font-size-adjust (delta)
"Adjust the current frame's font size.
DELTA would be something like 1 or -1."
(interactive "nFont size difference: ")
(when (null delta) (setq delta 1))
(let* ((font-family (face-attribute 'default :font))
(font-size (font-get font-family :size))
(new-size (+ delta font-size)))
(ha-set-favorite-font-size new-size)))
(defun font-size-increase ()
"Increase the `default' font size of all frames."
(interactive)
(font-size-adjust 1))
(defun font-size-decrease ()
"Decrease the `default' font size of all frames."
(interactive)
(font-size-adjust -1))
#+end_src
And some keybindings to call them:
#+begin_src emacs-lisp
(global-set-key (kbd "s-+") 'font-size-increase)
(global-set-key (kbd "s-=") 'font-size-increase)
(global-set-key (kbd "s--") 'font-size-decrease)
#+end_src
* Themes
One does get used to a particular collection of colors. After happily using Steve Purcells port of the Tomorrow theme for many years, I decided I needed a change. First, I want Emacs to be less garish:
#+begin_src emacs-lisp
(use-package doom-themes
:config
;; Global settings (defaults)
(setq doom-themes-enable-bold t ; if nil, bold is universally disabled
doom-themes-enable-italic t) ; if nil, italics is universally disabled
(load-theme 'doom-wilmersdorf t))
#+end_src
Most of the time, Emacs is on my desk is a darkened room, so I choose the dark theme:
#+begin_src emacs-lisp
(defun laptop-inside ()
"Customize the theme for inside programming."
(interactive)
(load-theme 'doom-wilmersdorf t)
(ignore-errors
;; TODO: File in progress!
(load-file "~/other/hamacs/ha-theme-dark.el"))
(ha-word-processor-fonts))
#+end_src
But, when feeling adventurous, I /sometimes/ take my laptop outside:
#+begin_src emacs-lisp
(defun laptop-in-the-sun ()
"Customize the theme for outside programming."
(interactive)
(load-theme 'doom-ayu-light t)
(set-face-attribute 'default nil :foreground "#0c0906")
(set-face-attribute 'region nil :background "orange")
(set-face-attribute 'org-block nil :background "#f2f1ef")
(set-face-attribute 'org-block-begin-line nil :foreground "#999491" :background "#e5e4e3")
(ha-word-processor-fonts))
#+end_src
Ive been playing around with making the current window more pronounced.
This isnt needed as much with the [[*Window Dimmer][Window Dimmer]] feature, but if I do, this would be the settings:
#+begin_src emacs-lisp :tangle no
(set-face-attribute 'mode-line nil :background "#cccccc")
(set-face-attribute 'mode-line-inactive nil :background "#888888")
#+end_src
Oh, and turn off the line highlighting:
#+begin_src emacs-lisp
(global-hl-line-mode -1)
#+end_src
And of course, the default is /inside/ where it is dark and safe. Lets also wait til the world settles down before calling this.
#+begin_src emacs-lisp
(progn
(sit-for 2)
(laptop-inside))
#+end_src
** Highlight Task Labels
In code, if you drop a specific /text/ labels, we can highlight them with [[https://github.com/tarsius/hl-todo][hl-todo package]]:
#+begin_src emacs-lisp
(use-package hl-todo
:straight (:host github :repo "tarsius/hl-todo")
:init
(setq hl-todo-keyword-faces
`(("TODO" . ,(face-foreground 'warning))
("FIXME" . ,(face-foreground 'error))
("NOTE" . ,(face-foreground 'success))))
(global-hl-todo-mode 1))
#+end_src
This means that comments like the following visually standout:
TODO Attempt to validate that this shows something I need to do.
Suggests to bind some keys to =hl-todo-next= in order to jump from tag to tag, but the [[https://github.com/liuyinz/consult-todo][consult-todo]] implements that in a more visual way:
#+begin_src emacs-lisp
(use-package consult-todo
:init
(defconst consult-todo--narrow
'((?t . "TODO")
(?f . "FIXME")
(?n . "NOTE"))
"Mapping of narrow and keywords.")
:general (:states 'normal "g t" '("jump todos" . consult-todo)))
#+end_src
* Full Size Frame
Taken from [[https://emacsredux.com/blog/2020/12/04/maximize-the-emacs-frame-on-startup/][this essay]], I figured I would start the initial frame automatically in fullscreen, but not any subsequent frames (as this could be part of the capturing system).
#+begin_src emacs-lisp
(add-to-list 'initial-frame-alist '(fullscreen . maximized))
#+end_src
But when capturing, I subsequently open smaller frames that shouldnt be /odd looking/:
#+begin_src emacs-lisp
(add-to-list 'default-frame-alist '(ns-transparent-titlebar . t))
(add-to-list 'default-frame-alist '(ns-appearance . dark))
#+end_src
Now that Im using v29 of Emacs, I can /un-decorate/ the non-full-sized frames:
#+begin_src emacs-lisp
(add-to-list 'default-frame-alist '(undecorated-round . t))
#+end_src
* Emojis, Icons and Whatnot
Display these two symbols as one:
#+begin_src emacs-lisp
(add-hook 'text-mode-hook (lambda ()
(dolist (pair '(("!?" . "")
("ae" . "æ")
("AE" . "Æ")
;; If we have ligatures, why these?
;; ("->" . ?→)
;; ("<-" . ?←)
;; ("=>" . ?⇒)
))
(push pair prettify-symbols-alist))))
#+end_src
And turn the prettifier on:
#+begin_src emacs-lisp
(global-prettify-symbols-mode 1)
#+end_src
In Emacs 28.1, we have better Unicode 14 support. Which means, we need to install [[https://github.com/googlefonts/noto-emoji][Noto Color Emoji]]. My systems, seems to work fine, but Im leaving this code here in case I have issues, as I might use what Apple supplies when on a Mac (thanks [[http://xahlee.info/emacs/emacs/emacs_list_and_set_font.html][Xah Lee]]):
#+begin_src emacs-lisp
;; set font for symbols
(set-fontset-font t 'symbol
(cond
((ha-running-on-macos?)
(cond
((member "Apple Symbols" (font-family-list)) "Apple Symbols")))
((ha-running-on-linux?)
(cond
((member "Symbola" (font-family-list)) "Symbola")))))
;; set font for emoji (should come after setting symbols)
(set-fontset-font t 'emoji
(cond
((member "Apple Color Emoji" (font-family-list)) "Apple Color Emoji")
((member "Noto Color Emoji" (font-family-list)) "Noto Color Emoji")
((member "Symbola" (font-family-list)) "Symbola")))
#+end_src
Test this out: 😄 😱 😸 👸 👽 🙋
Not use what I'm doing with the [[https://github.com/domtronn/all-the-icons.el][all-the-icons]] package, but the Doom Modeline uses much of this.
#+begin_src emacs-lisp
(use-package all-the-icons)
#+end_src
*Note:* Install everything with the function, =all-the-icons-install-fonts=.
* Ligatures
Seems like getting ligatures to work in Emacs has been a Holy Grail. On Mac, I've used special builds that have hacks, but now with Emacs 27 and Harfbuzz, I should be able to get --> to look like it should.
#+begin_src emacs-lisp :tangle no
(setq prettify-symbols-unprettify-at-point 'right-edge)
(global-prettify-symbols-mode +1)
(prettify-symbols-mode +1)
#+end_src
We'll start using that instead, but setting this [[file:ha-programming.org::*Ligatures][over here]] in the programming section.
Also note that adding a /little/ extra space between lines makes text files easier to read.
#+begin_src emacs-lisp
(add-hook 'text-mode-hook (lambda () (setq-local line-spacing 0.1)))
#+end_src
* Technical Artifacts :noexport:
Let's =provide= a name so we can =require= this file:
#+begin_src emacs-lisp :exports none
(provide 'ha-display)
;;; ha-display.el ends here
#+end_src
Before you can build this on a new system, make sure that you put the cursor over any of these properties, and hit: ~C-c C-c~
#+description: A literate programming file to configure the Emacs UI.
#+property: header-args:sh :tangle no
#+property: header-args:emacs-lisp :tangle yes
#+property: header-args :results none :eval no-export :comments no :mkdirp yes
#+options: num:nil toc:t todo:nil tasks:nil tags:nil date:nil
#+options: skip:nil author:nil email:nil creator:nil timestamp:nil
#+infojs_opt: view:nil toc:t ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js