421 lines
18 KiB
Org Mode
421 lines
18 KiB
Org Mode
#+TITLE: Emacs Graphical Display Configuration
|
||
#+AUTHOR: Howard X. Abrams
|
||
#+DATE: 2020-09-10
|
||
|
||
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
|
||
|
||
And let’s 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))
|
||
#+end_src
|
||
* 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-percent-position nil)
|
||
:config
|
||
(doom-modeline-mode +1))
|
||
|
||
(use-package doom-themes)
|
||
#+end_src
|
||
* 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-pulse-functions '(recenter-top-bottom
|
||
move-to-window-line-top-bottom
|
||
reposition-window
|
||
bookmark-jump
|
||
other-window
|
||
delete-window
|
||
delete-other-windows
|
||
aw-delete-window
|
||
forward-page
|
||
backward-page
|
||
scroll-up-command
|
||
scroll-down-command
|
||
evil-window-right
|
||
evil-window-left
|
||
evil-window-up
|
||
evil-window-down
|
||
aw-move-window
|
||
aw-swap-window
|
||
aw-copy-window
|
||
aw-split-window-vert
|
||
aw-split-window-horz
|
||
aw-split-window-fair
|
||
ha-new-window
|
||
winum-select-window-1
|
||
winum-select-window-2
|
||
winum-select-window-3
|
||
winum-select-window-4
|
||
winum-select-window-5
|
||
winum-select-window-6
|
||
winum-select-window-7
|
||
winum-select-window-8
|
||
winum-select-window-9
|
||
winner-undo
|
||
winner-redo
|
||
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))
|
||
(pulsar-face 'pulsar-generic)
|
||
(pulsar-delay 0.05)
|
||
:bind ("<f8>" . pulsar-pulse-line)
|
||
:config (pulsar-global-mode 1))
|
||
#+end_src
|
||
* Themes
|
||
One does get used to a particular collection of colors. Mine is Tomorrow:
|
||
#+begin_src emacs-lisp
|
||
(use-package color-theme-sanityinc-tomorrow)
|
||
#+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 ()
|
||
(interactive)
|
||
(load-theme 'sanityinc-tomorrow-night t)
|
||
(set-face-attribute 'region nil :background "#000096")
|
||
(set-face-attribute 'mode-line nil :background "black")
|
||
(set-face-attribute 'mode-line-inactive nil :background "#444444"))
|
||
#+end_src
|
||
|
||
But, when feeling adventurous, I /sometimes/ take my laptop outside:
|
||
|
||
#+begin_src emacs-lisp
|
||
(defun laptop-in-the-sun ()
|
||
(interactive)
|
||
(load-theme 'sanityinc-tomorrow-day t)
|
||
(set-face-attribute 'region nil :background "orange1")
|
||
(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:
|
||
|
||
#+begin_src emacs-lisp
|
||
(laptop-inside)
|
||
#+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 shouldn’t 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 I’m 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
|
||
* 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
|
||
"Cascadia Code PL" ; funky font with litagures and a dotted 0
|
||
"Hack Nerd Font" ; clean font, but no litagures!?
|
||
"FiraCode Nerd Font" ; has litagures
|
||
"Cousine Nerd Font"
|
||
"Iosevka Nerd Font"
|
||
"Iosevka"
|
||
"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))
|
||
'("Literata" ; Clean, readable with litagures
|
||
"XCharter" ; https://fontesk.com/xcharter-typeface/
|
||
"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))
|
||
'("Overpass" "Source Sans Pro"
|
||
"Lucida Grande" "Verdana"
|
||
"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 18))
|
||
|
||
(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 14))
|
||
|
||
(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
|
||
** 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
|
||
* Emojis, Icons and Whatnot
|
||
Display these two symbols as one:
|
||
#+begin_src emacs-lisp
|
||
(add-hook 'text-mode-hook (lambda ()
|
||
(dolist (pair '(("!?" . "‽")
|
||
("->" . ?→)
|
||
("<-" . ?←)
|
||
("=>" . ?⇒)))
|
||
(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 I’m 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
|
||
((string-equal system-type "darwin")
|
||
(cond
|
||
((member "Apple Symbols" (font-family-list)) "Apple Symbols")))
|
||
((string-equal system-type "gnu/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:nil todo:nil tasks:nil tags:nil date:nil
|
||
#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil
|
||
#+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js
|