2024-07-13 08:33:36 -04:00
2024-07-13 08:33:36 -04:00
2021-05-04 20:28:39 -04:00
2023-11-23 12:58:23 -05:00
2021-04-26 09:08:04 -04:00
2023-11-23 12:58:23 -05:00

Personal Emacs Configuration

Welcome

My personal configuration of Emacs, written as an Org Mode document.

Run the block below with C-c C-c to tangle code blocks to config file.

NOT IN USE

(org-mode-restart)
(org-babel-tangle)

Configuration Variables

;; Font Sizes
(defvar sb/default-font-size 110)
(defvar sb/default-variable-font-size 110)
(defvar sb/modeline-height 10)

;; Font Names
(defvar sb/source-code-font "MonaspiceNe NF")
(defvar sb/document-font "Cantarell")

Package System Setup

Package Sources and Initialization

;; Initialize package sources
(require 'package)

(setq package-archives '(
                         ("melpa" . "https://melpa.org/packages/")
                         ("gnu-elpa"  . "https://elpa.gnu.org/packages/")
                         ("nongnu-elpa"  . "https://elpa.nongnu.org/nongnu/")
                        )
)

(package-initialize)
(unless package-archive-contents
  (package-refresh-contents)
)

;; Initialize use-package on non-Linux platforms
(unless (package-installed-p 'use-package)
  (package-install 'use-package)
)

(require 'use-package)
(setq use-package-always-ensure t)

Auto Update Packages

(use-package auto-package-update
  :init
  (auto-package-update-maybe)
)

Basic UI Configuration

Disable Unnecessary Visual Elements

Disable some visual elements that are not necessary like startup message, scrollbar, toolbar, tooltips, menu bar, etc. Turn on the visual bell and add some breathing room.

(setq inhibit-startup-message t) ; Disable startup message

(scroll-bar-mode -1)  ; Disable visible scrollbar
(tool-bar-mode -1)    ; Disable the toolbar
(tooltip-mode -1)     ; Disable tooltips
(set-fringe-mode 10)  ; Give some breathing room

(menu-bar-mode -1)    ; Disable the menu bar

(setq visible-bell t) ; Set up the visible bell

Line Numbers

;; Line Numbers
(column-number-mode)
(global-display-line-numbers-mode t)

;; Disable line numbers for some modes
(dolist (mode '(
                org-mode-hook
                term-mode-hook
                shell-mode-hook
                eshell-mode-hook
                )
        )
  (add-hook mode (lambda () (display-line-numbers-mode 0)))
)

Font Configuration

Setup FiraCode and Cantarell fonts with specified size.

;; Set the default font
(set-face-attribute 'default nil :font sb/source-code-font :height sb/default-font-size)

;; Set the fixed pitch font
(set-face-attribute 'fixed-pitch nil :font sb/source-code-font :height sb/default-font-size)

;; Set the variable pitch font
(set-face-attribute 'variable-pitch nil :font sb/document-font :height sb/default-font-size :weight 'regular)

Ligature Support

Add ligature support using Fira Code symbols.

NOTE: The first time you load your configuration on a new machine, you'll need to run the following command interactively so that ligature symbols display correctly:

M-x fira-code-mode-install-fonts RET

(use-package fira-code-mode
  :custom
  ;; List of ligatures to turn off
  (fira-code-mode-disabled-ligatures '(
                                       "[]" "#{" "#(" "#_" "#_(" "x"
                                       )
  ) 
  ;; Enables fira-code-mode automatically for programming major modes
  :hook prog-mode
)

Tab Width

(setq-default tab-width 4)

Keybindings

Custom Functions

(defun reload-config ()
  (interactive)
  (load-file user-init-file)
  (revert-buffer t t)
)

General

;; Make ESC quit prompts
(global-set-key (kbd "<escape>") 'keyboard-escape-quit)

;; General (for easy keybindings)
(use-package general
  :config
  (general-create-definer sb/leader-keys
    :keymaps '(normal insert visual emacs)
    :prefix "SPC"
    :global-prefix "C-SPC"
  )

  (sb/leader-keys
    "o"  '(:ignore t :which-key "org-mode quick access")
    "oa" '(org-agenda :which-key "org agenda")
    "oc" '(org-capture :which-key "org capture")
    ;; "t"  '(:ignore t :which-key "toggles")
    ;; "tc" '(comment-line :which-key "toggle comment")
    "s"  '(:ignore s :which-key "settings")
    "sr" '(reload-config :which-key "reload config")
    "ss" '(hydra-text-scale/body :which-key "scale text")
    "st" '(counsel-load-theme :which-key "choose theme")
  )
)

(general-define-key
 "C-M-j" 'counsel-switch-buffer
)

Evil Keybindings

;; Evil Keybindings
(use-package evil
  :init
  (setq evil-want-integration t)
  (setq evil-want-keybinding nil)
  (setq evil-want-C-u-scroll t)
  (setq evil-want-C-i-jump nil)
  :config
  (evil-mode 1)
  (define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)
  (define-key evil-insert-state-map (kbd "C-h") 'evil-delete-backward-char-and-join)

  ;; Use visual line motions even outside of visual-line-mode buffers
  (evil-global-set-key 'motion "j" 'evil-next-visual-line)
  (evil-global-set-key 'motion "k" 'evil-previous-visual-line)

  (evil-set-initial-state 'messages-buffer-mode 'normal)
  (evil-set-initial-state 'dashboard-mode 'normal)
)

(use-package evil-collection
  :after evil
  :config
  (evil-collection-init)
)

;; Easymotion
(use-package evil-easymotion
  :config
  (evilem-default-keybindings "SPC")
)

UI Configuration

Color Theme

;; Dracula Doom Theme
(use-package doom-themes
  :init (load-theme 'doom-dracula t)
)

;; ;; Dracula Pro Theme
;; (add-to-list 'custom-theme-load-path "~/.config/emacs/themes")
;; (load-theme 'dracula-pro t)

Better Modeline

;; Doom Modeline
(use-package doom-modeline
  :ensure t
  :init (doom-modeline-mode 1)
  :custom ((doom-modeline-height sb/modeline-height))
)

Dashboard

;; Emacs Dashboard
(use-package dashboard
  :ensure t
  :config
  (dashboard-setup-startup-hook)
  :init
  ;; Banner Title
  (setq dashboard-banner-logo-title "Welcome to Emacs Dashboard")
  ;; Banner Logo
  (setq dashboard-startup-banner 'logo)
  ;; Widgets
  (setq dashboard-items '((recents . 5)
                          (bookmarks . 5)
                          (projects . 5)
                          (registers . 5)))
  ;; Show Heading & File Icons
  (setq dashboard-set-heading-icons t)
  (setq dashboard-set-file-icons t)
  ;; Show info about packages loaded and init time
  (setq dashboard-set-init-info t)
  ;; Use with counsel-projectile
  (setq dashboard-projects-switch-function 'counsel-projectile-switch-project-by-name)
)

Which Key

(use-package which-key
  :init (which-key-mode)
  :diminish which-key-mode
  :config
  (setq which-key-idle-delay 1)
)

Ivy and Counsel

NOTE: The first time you load your configuration on a new machine, you may need to run the following command interactively so that mode line icons display correctly:

M-x all-the-icons-install-fonts RET

;; Ivy Autocompletion
(use-package ivy
  :diminish
  :bind (
         ("C-s" . swiper)
         :map ivy-minibuffer-map
         ("TAB" . ivy-alt-done)
         ("C-l" . ivy-alt-done)
         ("C-j" . ivy-next-line)
         ("C-k" . ivy-previous-line)
         :map ivy-switch-buffer-map
         ("C-k" . ivy-previous-line)
         ("C-l" . ivy-done)
         ("C-d" . ivy-switch-buffer-kill)
         :map ivy-reverse-i-search-map
         ("C-k" . ivy-previous-line)
         ("C-d" . ivy-reverse-i-search-kill)
        )
  :config
  (ivy-mode 1)
)

;; All the Icons Ivy Rich
(use-package all-the-icons-ivy-rich
  :ensure t
  :after counsel-projectile
  :init (all-the-icons-ivy-rich-mode 1)
)

;; Ivy Rich
(use-package ivy-rich
  :ensure t
  :init (ivy-rich-mode 1)
)

;; Counsel
(use-package counsel
  :bind (("C-M-j" . 'counsel-switch-buffer)
         :map minibuffer-local-map
         ("C-r" . 'counsel-minibuffer-history))
  :config
  (counsel-mode 1)
)

Helpful Help Commands

;; Helpful
(use-package helpful
  :custom
  (counsel-describe-function-function #'helpful-callable)
  (counsel-describe-variable-function #'helpful-variable)
  :bind
  ([remap describe-function] . counsel-describe-function)
  ([remap describe-command] . helpful-command)
  ([remap describe-variable] . counsel-describe-variable)
  ([remap describe-key] . helpful-key)
)

Text Scaling

Use Hydra to design a transient key binding for quickly adjusting the scale of the text on screen.

;; Hydra
(use-package hydra)

(defhydra hydra-text-scale (:timeout 4)
  "scale text"
  ("j" text-scale-increase "in")
  ("k" text-scale-decrease "out")
  ("f" nil "finished" :exit t)
)

Highlight Indent Guides

(use-package highlight-indent-guides
  :hook (prog-mode . highlight-indent-guides-mode)
  :hook (text-mode . highlight-indent-guides-mode)
  :init
  (setq highlight-indent-guides-method 'fill)
  (setq highlight-indent-guides-responsive 'stack)
  (setq highlight-indent-guides-delay 0)
)

Org Mode

Better Font Faces

(defun sb/org-font-setup ()
  ;; ;; Replace list hyphen with dot
  ;; (font-lock-add-keywords 'org-mode
  ;;                         '(("^ *\\([-]\\) "
  ;;                            (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))

  ;; Set faces for heading levels
  (dolist (face '((org-level-1 . 1.2)
                  (org-level-2 . 1.1)
                  (org-level-3 . 1.05)
                  (org-level-4 . 1.0)
                  (org-level-5 . 1.1)
                  (org-level-6 . 1.1)
                  (org-level-7 . 1.1)
                  (org-level-8 . 1.1)))
    (set-face-attribute (car face) nil :font "Cantarell" :weight 'regular :height (cdr face))
  )

  ;; Ensure that anything that should be fixed-pitch in Org files appears that way
  (set-face-attribute 'org-block nil :foreground nil :inherit 'fixed-pitch)
  (set-face-attribute 'org-code nil   :inherit '(shadow fixed-pitch))
  (set-face-attribute 'org-table nil   :inherit '(shadow fixed-pitch))
  (set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch))
  (set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch))
  (set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch))
  (set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch)
)

Main Config

(defun sb/org-mode-setup ()
  (org-indent-mode)
  (variable-pitch-mode 1)
  (auto-fill-mode 0)
  (visual-line-mode 1)
  (setq evil-auto-indent nil)
  (setq org-edit-src-content-indentation 0)
)

(use-package org
  :hook (org-mode . sb/org-mode-setup)
  :config
  ;; Change elipsis to down arrow
  (setq org-ellipsis " ▾")

  ;; Org Agenda Settings
  (setq org-agenda-start-with-log-mode t)
  (setq org-log-done 'time)
  (setq org-log-into-drawer t)

  ;; Org Agenda Files
  (setq org-agenda-files
        '(
          "~/OrgFiles/Tasks.org"
          ;; "~/OrgFiles/Habits.org"
          ;; "~/OrgFiles/Birthdays.org"
         )
  )

  ;; Org Habit Tracker
  (require 'org-habit)
  (add-to-list 'org-modules 'org-habit)
  (setq org-habit-graph-column 60)

  ;; Org TODO Keywords
  (setq org-todo-keywords
        '(
          (sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!)")
          (sequence "BACKLOG(b)" "PLAN(p)" "READY(r)" "ACTIVE(a)" "REVIEW(v)" "WAIT(w@/!)" "HOLD(h)" "|" "COMPLETED(c)" "CANC(k@)")
         )
  )

  ;; ;; Move tasks between documents
  ;; (setq org-refile-targets
  ;;   '(("Archive.org" :maxlevel . 1)
  ;;     ("Tasks.org" :maxlevel . 1)))

  ;; ;; Save Org buffers after refiling!
  ;; (advice-add 'org-refile :after 'org-save-all-org-buffers)

  ;; ;; Org Tags
  ;; (setq org-tag-alist
  ;;   '((:startgroup)
  ;;      ; Put mutually exclusive tags here
  ;;      (:endgroup)
  ;;      ("@errand" . ?E)
  ;;      ("@home" . ?H)
  ;;      ("@work" . ?W)
  ;;      ("agenda" . ?a)
  ;;      ("planning" . ?p)
  ;;      ("publish" . ?P)
  ;;      ("batch" . ?b)
  ;;      ("note" . ?n)
  ;;      ("idea" . ?i)))

  ;; Configure custom agenda views
  (setq org-agenda-custom-commands
   '(("d" "Dashboard"
     ((agenda "" ((org-deadline-warning-days 7)))
      (todo "NEXT"
        ((org-agenda-overriding-header "Next Tasks")))
      (tags-todo "agenda/ACTIVE" ((org-agenda-overriding-header "Active Projects")))))

    ("n" "Next Tasks"
     ((todo "NEXT"
        ((org-agenda-overriding-header "Next Tasks")))))

    ;; ("W" "Work Tasks" tags-todo "+work-email")

    ;; ;; Low-effort next actions
    ;; ("e" tags-todo "+TODO=\"NEXT\"+Effort<15&+Effort>0"
    ;;  ((org-agenda-overriding-header "Low Effort Tasks")
    ;;   (org-agenda-max-todos 20)
    ;;   (org-agenda-files org-agenda-files)))

    ("w" "Workflow Status"
     ((todo "WAIT"
            ((org-agenda-overriding-header "Waiting on External")
             (org-agenda-files org-agenda-files)))
      (todo "REVIEW"
            ((org-agenda-overriding-header "In Review")
             (org-agenda-files org-agenda-files)))
      (todo "PLAN"
            ((org-agenda-overriding-header "In Planning")
             (org-agenda-todo-list-sublevels nil)
             (org-agenda-files org-agenda-files)))
      (todo "BACKLOG"
            ((org-agenda-overriding-header "Project Backlog")
             (org-agenda-todo-list-sublevels nil)
             (org-agenda-files org-agenda-files)))
      (todo "READY"
            ((org-agenda-overriding-header "Ready for Work")
             (org-agenda-files org-agenda-files)))
      (todo "ACTIVE"
            ((org-agenda-overriding-header "Active Projects")
             (org-agenda-files org-agenda-files)))
      (todo "COMPLETED"
            ((org-agenda-overriding-header "Completed Projects")
             (org-agenda-files org-agenda-files)))
      (todo "CANC"
            ((org-agenda-overriding-header "Cancelled Projects")
             (org-agenda-files org-agenda-files))))))
  )

  ;; Org Capture Templates
  (setq org-capture-templates
    `(("t" "Tasks / Projects")
      ("tt" "Task" entry (file+olp "~/OrgFiles/Tasks.org" "Inbox")
           "* TODO %?\n  %U\n  %a\n  %i" :empty-lines 1)

      ("j" "Journal Entries")
      ("jj" "Journal" entry
           (file+olp+datetree "~/OrgFiles/Journal.org")
           "\n* %<%I:%M %p> - Journal :journal:\n\n%?\n\n"
           ;; ,(dw/read-file-as-string "~/Notes/Templates/Daily.org")
           :clock-in :clock-resume
           :empty-lines 1)
      ("jm" "Meeting" entry
           (file+olp+datetree "~/OrgFiles/Journal.org")
           "* %<%I:%M %p> - %a :meetings:\n\n%?\n\n"
           :clock-in :clock-resume
           :empty-lines 1)

      ;; ("w" "Workflows")
      ;; ("we" "Checking Email" entry (file+olp+datetree "~/OrgFiles/Journal.org")
      ;;      "* Checking Email :email:\n\n%?" :clock-in :clock-resume :empty-lines 1)

      ;; ("m" "Metrics Capture")
      ;; ("mw" "Weight" table-line (file+headline "~/OrgFiles/Metrics.org" "Weight")
      ;;  "| %U | %^{Weight} | %^{Notes} |" :kill-buffer t)
     )
  )

  ;; ;; Keybinding for going directly to journal entry
  ;; (define-key global-map (kbd "C-c j")
  ;;   (lambda () (interactive) (org-capture nil "jj")))

  (sb/org-font-setup)
)

Heading Bullets

  (use-package org-bullets
    :after org
    :hook (org-mode . org-bullets-mode)
    :custom
    (org-bullets-bullet-list '("◉" "○" "●" "○" "●" "○" "●"))
    :init
    (setq inhibit-compacting-font-caches t)
  )

Center Org Buffers

NOT IN USE

(defun sb/org-mode-visual-fill ()
  (setq visual-fill-column-width 100
        visual-fill-column-center-text t)
  (visual-fill-column-mode 1)
)

(use-package visual-fill-column
  :hook (org-mode . sb/org-mode-visual-fill)
)

Configure Babel Languages

(org-babel-do-load-languages
  'org-babel-load-languages
  '((emacs-lisp . t)
    (makefile . t)
    (python . t))
)

(push '("conf-unix" . conf-unix) org-src-lang-modes)

Structure Templates

;; This is needed as of Org 9.2
(require 'org-tempo)

(add-to-list 'org-structure-template-alist '("sh" . "src shell"))
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("py" . "src python"))
(add-to-list 'org-structure-template-alist '("hs" . "src haskell"))
(add-to-list 'org-structure-template-alist '("cf" . "src config"))

Auto-Tangle

Automatically tangle code blocks in file everytime it is saved. Add #+auto_tangle: t to the org document to enable this.

(use-package org-auto-tangle
  :defer t
  :hook (org-mode . org-auto-tangle-mode)
)

Development

Commenting

(use-package evil-nerd-commenter
  :bind ("M-/" . evilnc-comment-or-uncomment-lines)
)

Languages

Language Modes

Fish Shell
(use-package fish-mode)
Git Attributes
(use-package gitattributes-mode)
Git Config
(use-package gitconfig-mode)
Git Ignore
(use-package gitignore-mode)
Haskell
(use-package haskell-mode)
Vimrc
(use-package vimrc-mode)
C / C++
(use-package cc-mode)

Language Servers

(defun sb/lsp-mode-setup ()
  (setq lsp-headerline-breadcrumb-segments '(path-up-to-project file symbols))
  (lsp-headerline-breadcrumb-mode)
)

(use-package lsp-mode
  :commands (lsp lsp-deferred)
  :hook (lsp-mode . sb/lsp-mode-setup)
  :init
  (setq lsp-keymap-prefix "C-c l") ;; Or 'C-l', 's-l'
  :config
  (lsp-enable-which-key-integration t)
)

(use-package lsp-ui
  :hook (lsp-mode . lsp-ui-mode)
  :custom
  (lsp-ui-doc-position 'bottom)
)

(use-package lsp-treemacs
  :after lsp
)

(use-package lsp-ivy)

Company Mode

(use-package company
  :after lsp-mode
  :hook (lsp-mode . company-mode)
  :bind
  (:map company-active-map
        ("<tab>" . company-complete-selection))
  (:map lsp-mode-map
        ("<tab>" . company-indent-or-complete-common))
  :custom
  (company-minimum-prefix-length 1)
  (company-idle-delay 0.0)
)

(use-package company-box
  :hook (company-mode . company-box-mode)
)

Projectile

;; Projectile
(use-package projectile
  :diminish projectile-mode
  :config (projectile-mode)
  :custom ((projectile-completion-system 'ivy))
  :bind-keymap
  ("C-c p" . projectile-command-map)
  :init
  (setq projectile-project-search-path '("~/Projects/" "~/.config/" "~/.xmonad/"))
  (setq projectile-switch-project-action #'projectile-dired)
)

(use-package counsel-projectile
  :config (counsel-projectile-mode)
)

Magit

  ;; Magit
  (use-package magit
    :custom
    (magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)
  )

NOT IN USE

NOTE: evil-magit was removed from MELPA and now a part of evil-collection

(use-package evil-magit
  :after magit
)

;; NOTE: Make sure to configure a GitHub token before using this package!
;; - https://magit.vc/manual/forge/Token-Creation.html#Token-Creation
;; - https://magit.vc/manual/ghub/Getting-Started.html#Getting-Started
(use-package forge)

Rainbow Delimeters

;; Rainbow Delimiters
(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode)
)
Description
Personal build of emacs
Readme 149 KiB
Languages
Emacs Lisp 100%