#+TITLE:  Emacs Graphical Display Configuration
#+AUTHOR: Howard X. Abrams
#+DATE:   2020-09-10
#+FILETAGS: :emacs:

A literate programming file to configure the Emacs UI.

#+BEGIN_SRC emacs-lisp :exports none
  ;;; ha-display --- Emacs UI configuration. -*- lexical-binding: t; -*-
  ;;
  ;; © 2020-2022 Howard X. Abrams
  ;;   This work is 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
* Dashboard
The [[https://github.com/emacs-dashboard/emacs-dashboard][emacs-dashboard]] project makes a nicer startup screen. It requires [[https://github.com/purcell/page-break-lines][page-break-lines]] (which is a nice project):
#+BEGIN_SRC emacs-lisp
  (use-package page-break-lines)
#+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

#+BEGIN_SRC emacs-lisp
  (use-package dashboard
    :init
    (defun ha-dashboard-version ()
      (let ((smaller-version (replace-regexp-in-string
                     (rx " (" (zero-or-more any) eol) "" (emacs-version))))
        (string-replace "\n" "" smaller-version)))

    (setq dashboard-banner-logo-title
          (format "Emacs %s ⸺ %s"
                  (if (and (fboundp 'native-comp-available-p)
                           (native-comp-available-p))
                      "with Native Compilation" "")
                  (ha-dashboard-version))
          dashboard-startup-banner "~/other/hamacs/support/levitating-gnu.png"
          dashboard-center-content t
          dashboard-set-init-info t
          dashboard-projects-switch-function 'projectile-persp-switch-project
          dashboard-items '((projects . 5)
                            ;; (agenda . 5)
                            (bookmarks . 5)))
    :config
    (dashboard-setup-startup-hook)

    (setq dashboard-footer-messages (list (ha--dad-joke))))
#+END_SRC

I would appreciate seeing if my Emacs installation has the features that I expect:
#+BEGIN_SRC emacs-lisp
  (defun ha-hamacs-features (&optional iconic)
    "Simple display of features I'm most keen about.
  If ICONIC is non-nil, return a string of icons."
    (interactive)
    (let* ((png-icon  (all-the-icons-material "image"))
           (svg-icon  (all-the-icons-alltheicon "svg"))
           (tls-icon  (all-the-icons-faicon "expeditedssl"))
           (json-icon (all-the-icons-fileicon "jsx"))
           (mag-icon  (all-the-icons-faicon "magic"))
           (jit-icon  (all-the-icons-faicon "cog"))
           (results (s-join " "
              (list (when (and (fboundp 'native-comp-available-p)
                               (native-comp-available-p)) (if iconic jit-icon "Native-Compilation"))
                    (when (image-type-available-p 'svg)   (if iconic svg-icon "SVG"))
                    (when (image-type-available-p 'png)   (if iconic png-icon "PNG"))
                    (when (gnutls-available-p)            (if iconic tls-icon "TLS"))
                    (when (json-available-p)              (if iconic json-icon "JSON"))
                    (when (fboundp 'imagemagick-types)    (if iconic mag-icon "ImageMagick"))))))
      (if (called-interactively-p)
          (message "Enabled features: %s" results)
        results)))
#+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 ~F6~), but also, this automatically highlights the cursor line with specific /actions/ , like changing windows.

#+BEGIN_SRC emacs-lisp
  (use-package pulsar
    :straight (:type git :protocol ssh :host gitlab :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
                              forward-page
                              backward-page
                              scroll-up-command
                              scroll-down-command
                              windmove-right
                              windmove-left
                              windmove-up
                              windmove-down
                              windmove-swap-states-right
                              windmove-swap-states-left
                              windmove-swap-states-up
                              windmove-swap-states-down
                              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-magenta)
    (pulsar-delay 0.055)
    :bind ("<f6>" . pulsar-pulse-line))
#+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 "#333333"))
#+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 :tangle no
(add-to-list 'initial-frame-alist '(fullscreen . maximized))
#+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/:
  | Similarities | Regular                    |
  |--------------+----------------------------|
  | ()[]{}<>«»‹› | ABCDEFGHIJKLMNOPQRSTUVWXYZ |
  | 6bB8&        | abcdefghijklmnopqrstuvwxyz |
  | 0ODdoaoOQGC  | 0123456789                 |
  | I1tilIJL     | ~!@#$%^&*+                 |
  | !¡ij         | `'"‘’“”.,;:…               |
  | 5$§SsS5      | ()[]{}—-_=<>/\             |
  | 17ZzZ2       | ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ   |
  | 9gqpG6       | αβγδεζηθικλμνξοπρστυφχψω   |
  | hnmMN        |                            |
  | uvvwWuuwvy   |                            |
  | x×X          |  #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";                              |
  | ...          |                            |


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 (they usually are):
#+BEGIN_SRC emacs-lisp
  (defvar ha-fixed-font
    (when window-system
      (cond
       ((x-list-fonts "Hack Nerd Font") "Hack Nerd Font")
       ((x-list-fonts "Cousine Nerd Font") "Cousine Nerd Font")
       ((x-list-fonts "Iosevka Nerd Font") "Iosevka Nerd Font")
       ((x-list-fonts "Iosevka")           "Iosevka")
       ((x-list-fonts "FantasqueSansMono Nerd Font") "FantasqueSansMono Nerd Font")
       ((x-list-fonts "Monoid Nerd Font")  "Monoid Nerd Font")
       ((x-list-fonts "Hasklig")           "Hasklig")
       ((x-list-fonts "Cascadia Code PL")  "Cascadia Code PL")
       ((x-list-fonts "Source Code Pro")   "Source Code Pro")
       ((x-list-fonts "Anonymous Pro")     "Anonymous Pro")
       (t "monospaced")))
    "My fixed width font based on what is installed, `nil' if not defined.")
#+END_SRC

Force something as well:
#+BEGIN_SRC emacs-lisp :tangle no
(setq ha-fixed-font "Hack Nerd Font")
#+END_SRC

I probably don't need to have such a ranking system, as chances are really good that I'll have all of them installed. Still.
#+BEGIN_SRC emacs-lisp
(defvar ha-variable-font
  (when window-system
    (cond ((x-list-fonts "Overpass")        "Overpass")
          ((x-list-fonts "Source Sans Pro") "Source Sans Pro")
          ((x-list-fonts "Lucida Grande")   "Lucida Grande")
          ((x-list-fonts "Verdana")         "Verdana")
          ((x-family-fonts "Sans Serif")    "Sans Serif")
          (nil (warn "Cannot find a Sans Serif Font.  Install Source Sans Pro."))))
  "My variable width font available to org-mode files and whatnot.")
#+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 16))

  (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)
  (global-set-key (kbd "s-0") 'font-size-monitor-default)
  (global-set-key (kbd "s-9") 'font-size-laptop-default)
#+END_SRC

* Emojis, Icons and Whatnot
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]]. Currently, my systems, seems to work just 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

Note, in Doom, is appears we have a =ligatures= module.
We'll start using that instead, but changing it in [[file:general-programming.org][general-programming]] file.

* Technical Artifacts :noexport:

Let's provide a name so that the file can be required:

#+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