Skip to content

Latest commit

 

History

60 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

100phlecs of elisp

###########################'`################################
###########################  V##'############################
#########################V'  `V  ############################
########################V'      ,############################
#########`#############V      ,A###########################V
########' `###########V      ,###########################V',#
######V'   ###########l      ,####################V~~~~'',###
#####V'    ###########l      ##P' ###########V~~'   ,A#######
#####l      d#########l      V'  ,#######V~'       A#########
#####l      ##########l         ,####V''         ,###########
#####l        `V######l        ,###V'   .....;A##############
#####A,         `######A,     ,##V' ,A#######################
#######A,        `######A,    #V'  A########'''''##########''
##########,,,       `####A,           `#''           '''  ,,,
#############A,                               ,,,     ,######
######################oooo,                 ;####, ,#########
##################P'                   A,   ;#####V##########
#####P'    ''''       ,###             `#,     `V############
##P'                ,d###;              ##,       `V#########
##########A,,   #########A              )##,    ##A,..,ooA###
#############A, Y#########A,            )####, ,#############
###############A ############A,        ,###### ##############
###############################       ,#######V##############
###############################      ,#######################
##############################P    ,d########################
##############################'    d#########################
##############################     ##########################
##############################     ##########################
#############################P     ##########################
#############################'     ##########################
############################P      ##########################
###########################P'     ;##########################
###########################'     ,###########################
##########################       ############################
#########################       ,############################
########################        d###########P'    `Y#########
#######################        ,############        #########
######################        ,#############        #########
#####################        ,##############b.    ,d#########
####################        ,################################
###################         #################################
##################          #######################P'  `V##P'
#######P'     `V#           ###################P'
#####P'                    ,#################P'
###P'                      d##############P''
##P'                       V##############'
#P'                         `V###########'
#'                             `V##P'

Table of Contents

Preface

I primarily use org-babel because it helps with organizing. You’re at least forced to acknowledge headings. Otherwise I’d just get a messy init.el file. Which, well, maybe I’ll go back to.

Bootstrapping

Starting up

Lexical binding for certain packages & personal functions.

;; -*- lexical-binding: t -*-
;; needed for gccemacs
(setenv "LIBRARY_PATH" "/opt/homebrew/lib/gcc/11:/opt/homebrew/lib/gcc/11/gcc/aarch64-apple-darwin20/11")

(setq gc-cons-threshold (* 50 1000 1000))
  (defvar bootstrap-version)
  (let ((bootstrap-file
         (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
        (bootstrap-version 5))
    (unless (file-exists-p bootstrap-file)
      (with-current-buffer
          (url-retrieve-synchronously
           "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
           'silent 'inhibit-cookies)
        (goto-char (point-max))
        (eval-print-last-sexp)))
    (load bootstrap-file nil 'nomessage))

  (straight-use-package 'use-package)
  (setq straight-use-package-by-default t)

  (use-package no-littering)

  (setq custom-file "~/.emacs.d/custom.el")
   (if (file-exists-p custom-file)
       (message (concat  "File " (concat custom-file " already exists")))
     (with-temp-buffer (write-file custom-file)))
  (load custom-file)

More path loading

Need to get the environment set correctly, otherwise terminals won’t work or certain packages. This is for GUI emacs.

(use-package exec-path-from-shell
  :init
  (exec-path-from-shell-initialize))

(let ((default-directory "/opt/homebrew/share/emacs/site-lisp"))
  (normal-top-level-add-subdirs-to-load-path))

(autoload 'gerbil-mode "gerbil-mode" "Gerbil editing mode." t)

Diminish

To Diminish a mode is to no longer have it show up in the modeline. Useful to remove clutter from the modeline display.

(use-package diminish)

Appearance

Now that we’re loading in emacs, it’s nice to keep it clean, but not too clean.

Basic UI

Many people seem to discount the satisfaction of using the menu-bar-mode - it’s a great way to explore and remind yourself. I find myself using my mouse more than I thought I would - to scroll a buffer, click a command, resize stuff, etc.

Relative line column numbers (counting which line you’re on) helps with command chording. But of course they’re useless for some buffers, so we’ll disable them.

(menu-bar-mode t)
(scroll-bar-mode -1)
(tool-bar-mode -1)
(tooltip-mode -1)
(toggle-frame-maximized)
(set-fringe-mode 10)
(setq-default tab-width 2)
(setq-default indent-tabs-mode nil)
(setq inhibit-startup-message t)
(if (equal window-system nil)
 (menu-bar-mode -1))
(setq ring-bell-function 'ignore)

(column-number-mode t)
(setq display-line-numbers-type 'relative)

(add-hook 'prog-mode-hook (lambda()
                            (display-line-numbers-mode)
                            ))

Font

I enjoy Iosevka. The cramped nature of it can be off-putting, but after some use you can’t use anything else.

Comes with ligatures. Real easy with ligature.el - they gave me the Iosevka example below.

(set-face-attribute 'default nil :family "Iosevka Nerd Font" :height 170)
(set-face-attribute 'fixed-pitch nil :family "Iosevka Nerd Font" :height 170)
(set-face-attribute 'variable-pitch nil :family "Iosevka Nerd Font" :height 170)
(global-prettify-symbols-mode +1)

(use-package ligature
  :straight (ligature :type git :host github :repo "mickeynp/ligature.el" :files ("*.el" "*"))
  :config
  (ligature-set-ligatures '(prog-mode text-mode) '("<---" "<--"  "<<-" "<-" "->" "-->" "--->" "<->" "<-->" "<--->" "<---->" "<!--"
                                       "<==" "<===" "<=" "=>" "=>>" "==>" "===>" ">=" "<=>" "<==>" "<===>" "<====>" "<!---"
                                       "<~~" "<~" "~>" "~~>" "::" ":::" "==" "!=" "===" "!=="
                                       ":=" ":-" ":+" "<*" "<*>" "*>" "<|" "<|>" "|>" "+:" "-:" "=:" "<******>" "++" "+++"))
  (global-ligature-mode t))

rainbow-delimiter

Rainbow Parentheses/Curlies. Super nice to have in any prog file.

(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode)
  :diminish rainbow-delimiters-mode)

modeline

Using moody. Stealing some theme management :~)

(use-package moody
  :config
  (setq x-underline-at-descent-line t)
  (setq moody-mode-line-height 24)
  (moody-replace-mode-line-buffer-identification)
  (moody-replace-vc-mode)
  (moody-replace-eldoc-minibuffer-message-function))

Theme

Trying out a new theme. Was using solarized regular.

(use-package kaolin-themes)

(defun phl-theme-mods ()
  "Fix look after loading a theme"
  ;; preserve syntax highlighting
  ;; (set-face-background 'region (face-attribute 'highlight :background))
  (set-face-foreground 'region nil)
  (setq moody-line (face-attribute 'mode-line :underline))
  (set-face-attribute 'mode-line nil :overline moody-line)
  (set-face-attribute 'mode-line-inactive nil :overline moody-line)
  (set-face-attribute 'mode-line-inactive nil :underline moody-line)
  (setq show-paren-priority -50)
  (set-face-attribute 'mode-line nil :box nil)
  (set-face-attribute 'mode-line-inactive nil :box nil))

(defun phl-apply-theme (appearance)
  "Load theme, taking current system APPEARANCE into consideration."
  (mapc #'disable-theme custom-enabled-themes)
  (pcase appearance
    ('light (load-theme 'kaolin-breeze t))
    ('dark (load-theme 'kaolin-mono-dark t)))
  (phl-theme-mods)
  (phl-fix-bookmark))
(if (equal window-system nil)
    (load-theme 'kaolin-temple))
(defun phl-fix-bookmark ()
  "Set bookmark appearance after load"
  (set-face-foreground 'bookmark-face (face-attribute 'default :foreground))
  (set-face-background 'bookmark-face (face-attribute 'default :background)))

(add-hook 'bookmark-load-hook #'phl-fix-bookmark)
(add-hook 'ns-system-appearance-change-functions #'phl-apply-theme)

Discoverability / Navigation

which-key

which key is a little popup that comes after you start a key chord. Super useful, use it all the time, excessively.

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

git

It’s magit! Getting used to it, a lot nicer than grabbing a terminal, that’s for sure.

(use-package magit)
(setq magit-display-buffer-function 'magit-display-buffer-same-window-except-diff-v1)

expand region

Easy way to select what you want, mostly use it for removing chars within quotes. Maybe I don’t need it. But it seems like the embark cycle isn’t a good use case for this

(use-package expand-region
  :bind(
  ("C-=" . er/expand-region)))

keybindings

Need a place to drop some custom keys

(global-set-key (kbd "C-x M-k") #'kill-this-buffer)
(global-set-key (kbd "C-c s") #'ispell)

yes-or-no -> y-or-n

Quicker confirmations

(fset 'yes-or-no-p 'y-or-n-p)

hydra

hydra allows repeatable commands. Only use it for text size, but maybe more ideas will come or I’ll stop using this.

(use-package hydra)
(defhydra hydra-text-scale (global-map "<f2>")
  "scale text"
  ("C-p" text-scale-increase "in")
  ("C-n" text-scale-decrease "out"))

helpful

Improved help info. Getting comfortable at looking variables/functions is the way to go.

(use-package helpful
  :bind
  ([remap describe-function] . helpful-function)
  ([remap describe-command] . helpful-command)
  ([remap describe-variable] . helpful-variable)
  ([remap describe-key] . helpful-key))

complete at point/autocompletion

Autocompletion is smart for any sort of typing, isn’t it? So I enable company.

(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 3)
  (company-idle-delay 0.0))
  

yasnippet

yasnippet for code templates. Templating is sure convenient to have, wondering when I’ll make more use of it.

(use-package yasnippet
  :init (yas-global-mode 1))
(use-package doom-snippets
:after yasnippet
:straight (doom-snippets :type git :host github :repo "hlissner/doom-snippets" :files ("*.el" "*")))
(use-package common-lisp-snippets
:after yasnippet
:straight (common-lisp-snippets :type git :host github :repo "mrkkrp/common-lisp-snippets" :files ("*.el" "*")))

whole-line-or-region

whole-line-or-region is a quick swap-out to make more use of M-w instead of doing C-a C-k C-k

(use-package whole-line-or-region
  :straight (whole-line-or-region :type git :host github :repo "purcell/whole-line-or-region" :files ("*.el" "*")))
(whole-line-or-region-global-mode t)

project management

Originally used projectile, going to give project.el a try. Don’t have much to say about it at this point.

(use-package project
  :after magit
  :init
  (setq project-switch-commands
    '((project-find-file "Find file" nil)
     (project-find-regexp "Find regexp" nil)
     (project-find-dir "Find directory" nil)
     (project-vc-dir "VC-Dir" nil)
     (project-eshell "Eshell" nil)
     (magit-status "Magit" ?m))))

;; scan on startup for new projects 
(mapc
 #'project-remember-projects-under
 '("~/common-lisp"
   "~/repos"))

buffer management

tabs

Going to try out using tabs as ‘workspaces’ and just switch to eshell buffer when its needed so far so good

(setq tab-bar-show nil)
(setq tab-bar-select-tab-modifiers '(super))
(tab-bar-mode t)

Ace Window

To help move around buffers. Just going to replace C-x o.

  (use-package ace-window)

  (defvar global-keys-minor-mode-map (make-sparse-keymap)
    "global-keys-minor-mode keymap.")

  (defun phl-split-window-right ()
    (interactive)
    (split-window-right)
    (other-window 1))

  (defun phl-split-window-below ()
    (interactive)
    (split-window-below)
    (other-window 1))

  (define-key global-keys-minor-mode-map "\C-c\C-r" 'revert-buffer)
  (define-key global-keys-minor-mode-map (kbd "C-x o") 'ace-window)
  (define-key global-keys-minor-mode-map (kbd "C-x 2") 'phl-split-window-below)
  (define-key global-keys-minor-mode-map (kbd "C-x 3") 'phl-split-window-right)
;;  (define-key global-keys-minor-mode-map (kbd "M-`") 'popper-toggle-latest)
  (define-key global-keys-minor-mode-map (kbd "C-'") 'avy-goto-char-2)
  (define-minor-mode global-keys-minor-mode
    "A minor mode so that global key settings override annoying major modes."
    t "global-keys" 'global-keys-minor-mode-map)


  (global-keys-minor-mode 1)

  ;; A keymap that's supposed to be consulted before the first
  ;; minor-mode-map-alist.
  (defconst global-minor-mode-alist (list (cons 'global-keys-minor-mode
                                                global-keys-minor-mode-map)))
  (setf emulation-mode-map-alists '(global-minor-mode-alist))

  (defun my-minibuffer-setup-hook ()
    (global-keys-minor-mode 0))
  (add-hook 'minibuffer-setup-hook 'my-minibuffer-setup-hook)

  (diminish 'global-keys-minor-mode)

search completion

Originally tried out ivy, going to try out all of these other packages and see how it goes. For now I’ll use vertico after some debilitating thought. So far consult buffer preview is pretty nice.

Vertico

Vertico is Vertical completion in command searching

(use-package vertico
  :init
  (vertico-mode)
  (defun phl-minibuffer-backward-kill (arg)
    "When minibuffer is completing a file name delete up to parent
folder, otherwise delete a word."
    (interactive "p")
    (if minibuffer-completing-file-name
        (if (string-match-p "/." (minibuffer-contents))
            (zap-up-to-char (- arg) ?/)
          (delete-minibuffer-contents))
      (delete-word (- arg))))

  :bind (:map vertico-map
              ("C-f" . vertico-exit)
              :map minibuffer-local-map
              ("M-DEL" . phl-minibuffer-backward-kill))
  :custom
  (vertico-cycle t)
  (custom-set-faces '(vertico-current ((t (:background "#3a3f5a"))))))

Orderless

Orderless; any order searching

(use-package orderless
:init
(setq completion-styles '(orderless)
      completion-category-defaults nil
      completion-category-overrides '((file (styles . (partial-completion))))))

Consult

Consult; improved interfacing with emacs

;; Example configuration for Consult
(use-package consult
  ;; Replace bindings. Lazily loaded due by `use-package'.
  :bind (;; C-c bindings (mode-specific-map)
         ("C-c h" . consult-history)
         ("C-c m" . consult-mode-command)
         ("C-c b" . consult-bookmark)
         ("C-c k" . consult-kmacro)
         ;; C-x bindings (ctl-x-map)
         ("C-x M-:" . consult-complex-command)     ;; orig. repeat-complex-command
         ("C-x b" . consult-buffer)                ;; orig. switch-to-buffer
         ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
         ("C-x 5 b" . consult-buffer-other-frame)  ;; orig. switch-to-buffer-other-frame
         ;; Custom M-# bindings for fast register access
         ("M-#" . consult-register-load)
         ("M-'" . consult-register-store)          ;; orig. abbrev-prefix-mark (unrelated)
         ("C-M-#" . consult-register)
         ;; Other custom bindings
         ("M-y" . consult-yank-pop)                ;; orig. yank-pop
         ("<help> a" . consult-apropos)            ;; orig. apropos-command
         ;; M-g bindings (goto-map)
         ("M-g e" . consult-compile-error)
         ("M-g f" . consult-flymake)               ;; Alternative: consult-flycheck
         ("M-g g" . consult-goto-line)             ;; orig. goto-line
         ("M-g M-g" . consult-goto-line)           ;; orig. goto-line
         ("M-g o" . consult-outline)               ;; Alternative: consult-org-heading
         ("M-g m" . consult-mark)
         ("M-g k" . consult-global-mark)
         ("M-g i" . consult-imenu)
         ("M-g I" . consult-imenu-multi)
         ;; M-s bindings (search-map)
         ("M-s f" . consult-find)
         ("M-s F" . consult-locate)
         ("M-s g" . consult-grep)
         ("M-s G" . consult-git-grep)
         ("M-s r" . consult-ripgrep)
         ("M-s l"   . consult-line)
         ("M-s L" . consult-line-multi)
         ("M-s m" . consult-multi-occur)
         ("M-s k" . consult-keep-lines)
         ("M-s u" . consult-focus-lines)
         ;; Isearch integration
         ("M-s e" . consult-isearch-history)
         :map isearch-mode-map
         ("M-e" . consult-isearch-history)         ;; orig. isearch-edit-string
         ("M-s e" . consult-isearch-history)       ;; orig. isearch-edit-string
         ("M-s l" . consult-line)                  ;; needed by consult-line to detect isearch
         ("M-s L" . consult-line-multi))           ;; needed by consult-line to detect isearch
  :init
  (setq register-preview-delay 0
        register-preview-function #'consult-register-format)
  (advice-add #'register-preview :override #'consult-register-window)
  (advice-add #'completing-read-multiple :override #'consult-completing-read-multiple)
  (setq xref-show-xrefs-function #'consult-xref
        xref-show-definitions-function #'consult-xref)
  :config
  (consult-customize
   consult-theme
   :preview-key '(:debounce 0.2 any)
   consult-ripgrep consult-git-grep consult-grep
   consult-bookmark consult-recent-file consult-xref
   consult--source-file consult--source-project-file consult--source-bookmark
   :preview-key (kbd "M-."))
  (setq consult-narrow-key "<") ;; (kbd "C-+")

 
  (setq consult-project-root-function
        (lambda ()
          (when-let (project (project-current))
            (car (project-roots project)))))
  )
(require 'consult)
(use-package consult-yasnippet
  :bind ("C-x C-y" . consult-yasnippet))

Marginalia

Marginalia; Command info as well as keybinding for minibuffer

;; Enable richer annotations using the Marginalia package
(use-package marginalia
  :init
  (marginalia-mode))

Embark & Avy

Embark; emacs action flow & Avy; char tree movement Just adding this in since it is often paired with the others. Trying out some embark+avy combinations too.

(use-package embark
  :bind (("M-o" . embark-act)
         ("M-C-o" . embark-export))
  :config
  (setq embark-cycle-key (kbd "O"))
  ;; Optionally replace the key help with a completing-read interface
  (setq prefix-help-command #'embark-prefix-help-command)
  ;; Hide the mode line of the Embark live/completions buffers
  (add-to-list 'display-buffer-alist
               '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
                 nil
                 (window-parameters (mode-line-format . none))))
  (define-key embark-command-map "f" #'helpful-function)
  )

(defun embark-which-key-indicator ()
  "An embark indicator that displays keymaps using which-key.
    The which-key help message will show the type and value of the
    current target followed by an ellipsis if there are further
    targets."
  (lambda (&optional keymap targets prefix)
    (if (null keymap)
        (which-key--hide-popup-ignore-command)
      (which-key--show-keymap
       (if (eq (plist-get (car targets) :type) 'embark-become)
           "Become"
         (format "Act on %s '%s'%s"
                 (plist-get (car targets) :type)
                 (embark--truncate-target (plist-get (car targets) :target))
                 (if (cdr targets) "" "")))
       (if prefix
           (pcase (lookup-key keymap prefix 'accept-default)
             ((and (pred keymapp) km) km)
             (_ (key-binding prefix 'accept-default)))
         keymap)
       nil nil t (lambda (binding)
                   (not (string-suffix-p "-argument" (cdr binding))))))))

(setq embark-indicators
      '(embark-which-key-indicator
        embark-highlight-indicator
        embark-isearch-highlight-indicator))

(defun embark-hide-which-key-indicator (fn &rest args)
  "Hide the which-key indicator immediately when using the completing-read prompter."
  (which-key--hide-popup-ignore-command)
  (let ((embark-indicators
         (remq #'embark-which-key-indicator embark-indicators)))
    (apply fn args)))


(advice-add #'embark-completing-read-prompter
            :around #'embark-hide-which-key-indicator)


;; Consult users will also want the embark-consult package.
(use-package embark-consult
  :after (embark consult)
  :demand t ; only necessary if you have the hook below
  ;; if you want to have consult previews as you move around an
  ;; auto-updating embark collect buffer
  :hook
  (embark-collect-mode . consult-preview-at-point-mode))

(use-package avy
  :demand
  :bind (("C-;" . avy-goto-char-timer)
         ("C-:" . avy-isearch)
         ("C-'" . avy-goto-char-2)))

(defun avy-action-embark (pt)
  (unwind-protect
      (save-excursion
        (goto-char pt)
        (embark-act))
    (select-window
     (cdr (ring-ref avy-ring 0))))
  t)
(defun avy-action-helpful (pt)
  (save-excursion
    (goto-char pt)
    (helpful-at-point))
  (select-window
   (cdr (ring-ref avy-ring 0)))
  t)
(defun avy-action-mark-to-char (pt)
  (activate-mark)
  (goto-char pt))

(defun avy-action-copy-whole-line (pt)
  (save-excursion
    (goto-char pt)
    (cl-destructuring-bind (start . end)
        (bounds-of-thing-at-point 'line)
      (copy-region-as-kill start end)))
  (select-window
   (cdr
    (ring-ref avy-ring 0)))
  t)

(defun avy-action-yank-whole-line (pt)
  (avy-action-copy-whole-line pt)
  (save-excursion (yank))
  t)

(defun avy-action-kill-whole-line (pt)
  (save-excursion
    (goto-char pt)
    (kill-whole-line))
  (select-window
   (cdr
    (ring-ref avy-ring 0)))
  t)
(defun avy-action-teleport-whole-line (pt)
  (avy-action-kill-whole-line pt)
  (save-excursion (yank)) t)

(setf (alist-get ?t avy-dispatch-alist) 'avy-action-teleport
      (alist-get ?T avy-dispatch-alist) 'avy-action-teleport-whole-line)
(setf (alist-get ?k avy-dispatch-alist) 'avy-action-kill-stay
      (alist-get ?K avy-dispatch-alist) 'avy-action-kill-whole-line)
(setf (alist-get ?y avy-dispatch-alist) 'avy-action-yank
      (alist-get ?w avy-dispatch-alist) 'avy-action-copy
      (alist-get ?W avy-dispatch-alist) 'avy-action-copy-whole-line
      (alist-get ?Y avy-dispatch-alist) 'avy-action-yank-whole-line)
(setf (alist-get ?  avy-dispatch-alist) 'avy-action-mark-to-char)
(setf (alist-get ?H avy-dispatch-alist) 'avy-action-helpful)
(setf (alist-get ?o avy-dispatch-alist) 'avy-action-embark)

Org

The more I use it the more I wonder why I haven’t used it before.

UI Setup

(defun phl-org-mode-setup ()
  (org-indent-mode)
  (auto-fill-mode 1)
  (visual-line-mode 1))

Grab org and its modules

(use-package org
  :hook (org-mode . phl-org-mode-setup)
  :config
  (setq org-agenda-start-with-log-mode t)
  (setq org-agenda-window-setup 'current-window)
  (setq org-agenda-tags-column org-tags-column)
  (setq org-agenda-sticky t)
  (setq org-agenda-inhibit-startup nil)
  (setq org-agenda-dim-blocked-tasks nil)
  (setq org-agenda-compact-blocks nil)
  (setq org-agenda-time-grid
        (quote
         ((daily today remove-match)
          (800 1200 1600 2000)
          "......"
          "----------------")))

  (setq org-log-done 'time)
  (setq org-log-into-drawer t)
  (setq org-ellipsis ""
        org-hide-emphasis-markers t)
  (setq org-todo-keywords
        '((sequence "BACKLOG(b)" "TODO(t)" "NEXT(n)" "|" "DONE(d!)")
          (sequence "HABIT(h)" "|" "CHECKED(c)")))

  (setq org-refile-targets
        '(("Archive.org" :maxlevel . 1)
          ("Tasks.org" :maxlevel . 1)))
  (require 'org-habit)
  (add-to-list 'org-modules 'org-habit)
  (setq org-habit-graph-column 60)
  ;; Save Org buffers after refiling!
  (advice-add 'org-refile :after 'org-save-all-org-buffers)
  :bind ("C-c a" . org-agenda))

(use-package org-download)
(add-hook 'dired-mode-hook 'org-download-enable)

org bullets + center

(use-package org-superstar
  :after org
  :hook (org-mode . org-superstar-mode)
  :config
  (setq org-superstar-headline-bullets-list '("")))

(defun phl-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 . phl-org-mode-visual-fill))

org-roam

Makes writing easy compared to everything else I’ve tried.

(use-package org-roam
  :after consult
  :straight t
  :demand
  :init
  (setq org-roam-v2-ack t)
  :custom
  (org-roam-directory "~/Documents/notes")
  (org-roam-completion-everywhere t)

  (org-roam-dailies-capture-templates
   '(("d" "default" entry "* %<%I:%M %p>: %?"
      :if-new (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n"))))

  (org-roam-capture-templates
   `(("d" "default" plain
      "%?"
      :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
      :unnarrowed t)
     ("b" "book notes" plain (file ,(concat org-roam-directory "/Templates/BookTemplate.org"))
      :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
      :unnarrowed t)
     ("a" "design notes" plain
      (file ,(concat org-roam-directory "/Templates/DesignAnalysisTemplate.org"))
      :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
      :unnarrowed t)
     )
   )

  :bind (("C-c n l" . org-roam-buffer-toggle)
         ("C-c n f" . org-roam-node-find)
         ("C-c n i" . org-roam-node-insert)
         ("C-c n r" . phl-org-roam-rg)
         :map org-mode-map
         ("C-M-i" . completion-at-point)
         :map org-roam-dailies-map
         ("Y" . org-roam-dailies-capture-yesterday)
         ("T" . org-roam-dailies-capture-tomorrow))
  :bind-keymap
  ("C-c n d" . org-roam-dailies-map)
  :config
  
  (defun phl-org-roam-rg ()
    "Search across the content of the root org dir."
    (interactive)
    (consult-ripgrep org-roam-directory))

  (require 'org-roam-dailies) ;; Ensure the keymap is available
  (org-roam-db-autosync-mode)
  (org-roam-setup))

org-toc

(use-package org-make-toc)

Easily insert nodes quicker

(defun org-roam-node-insert-immediate (arg &rest args)
  (interactive "P")
  (let ((args (cons arg args))
        (org-roam-capture-templates (list (append (car org-roam-capture-templates)
                                                  '(:immediate-finish t)))))
    (apply #'org-roam-node-insert args)))
(global-set-key (kbd "C-c n I") #'org-roam-node-insert-immediate)

org tangle

This is how one generates the configuration. And also edit this configuration. We can just autogenerate it with this snippet.

(org-babel-do-load-languages
'org-babel-load-languagesp
'((emacs-lisp . t)
  (python . t)
  (lisp . t)))
(setq org-babel-lisp-eval-fn "sly-eval")

(setq org-src-tab-acts-natively nil)
(setq org-src-window-setup 'current-window)
(push '("conf-unix" . conf-unix) org-src-lang-modes)

(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 '("cl" . "src lisp"))

;; Automatically tangle our .org config file when we save it
(defun phl-org-babel-tangle-config ()
  (when (string-equal (buffer-file-name)
                      (expand-file-name "~/.emacs.d/README.org"))
    ;; Dynamic scoping to the rescue
    (let ((org-confirm-babel-evaluate nil))
      (org-babel-tangle))))

(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'phl-org-babel-tangle-config)))

org templates & tags

To make it easier to write up notes around certain domains, as well as having a project note to show up in agenda.

(defun phl-org-roam-filter-by-tag (tag-name)
    (lambda (node)
      (member tag-name (org-roam-node-tags node))))

(defun phl-org-roam-list-notes-by-tag (tag-name)
  (mapcar #'org-roam-node-file
          (seq-filter
           (phl-org-roam-filter-by-tag tag-name)
           (org-roam-node-list))))

(defun phl-org-roam-refresh-agenda-list ()
  (interactive)
  (setq org-agenda-files
        (append
         (phl-org-roam-list-notes-by-tag "Project")
         '("~/Documents/notes/agenda/Tasks.org"
           "~/Documents/notes/agenda/Habits.org"))))

;; Build the agenda list the first time for the session
(phl-org-roam-refresh-agenda-list)

(defun phl-org-roam-project-finalize-hook ()
  "Adds the captured project file to `org-agenda-files' if the
               capture was not aborted."
  ;; Remove the hook since it was added temporarily
  (remove-hook 'org-capture-after-finalize-hook #'phl-org-roam-project-finalize-hook)

  ;; Add project file to the agenda list if the capture was confirmed
  (unless org-note-abort
    (with-current-buffer (org-capture-get :buffer)
      (add-to-list 'org-agenda-files (buffer-file-name)))))


(defun phl-org-roam-find-project ()
  (interactive)
  ;; Add the project file to the agenda after capture is finished
  (add-hook 'org-capture-after-finalize-hook #'phl-org-roam-project-finalize-hook)

  ;; Select a project file to open, creating it if necessary

  (org-roam-node-find nil nil
   (phl-org-roam-filter-by-tag "Project")
   :templates
   '(("p" "project" plain
      "* Goals\n\n%?\n\n* Tasks\n\n** TODO Add initial tasks\n\n* Dates\n\n"
      :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org"
                         "#+title: ${title}\n#+category: ${title}\n#+filetags: Project")
      :unnarrowed t))))

(defun phl-org-roam-capture-inbox ()
  (interactive)
  (org-roam-capture- :node (org-roam-node-create)
                     :templates '(("i" "inbox" plain "* %?"
                                   :if-new (file+head "Inbox.org" "#+title: Inbox\n")))))


(defun phl-org-roam-capture-project-task ()
  (interactive)
  ;; Add the project file to the agenda after capture is finished
  (add-hook 'org-capture-after-finalize-hook #'phl-org-roam-project-finalize-hook)

  ;; Capture the new task, creating the project file if necessary
  (org-roam-capture- :node (org-roam-node-read nil (phl-org-roam-filter-by-tag "Project"))
                     :templates '(("p" "project" plain "** TODO %?"
                                   :if-new (file+head+olp "%<%Y%m%d%H%M%S>-${slug}.org"
                                                          "#+title: ${title}\n#+category: ${title}\n#+filetags: Project"
                                                          ("Tasks"))))))

(defun phl-org-roam-copy-todo-to-today ()
  (interactive)
  (let ((org-refile-keep t)
        (org-roam-dailies-capture-templates
         '(("t" "tasks" entry "%?"
            :if-new (file+head+olp "%<%Y-%m-%d>.org"
                                   "#+title: %<%Y-%m-%d>\n"
                                   ("Tasks")))))
        (org-after-refile-insert-hook #'save-buffer) today-file pos)
    (save-window-excursion
      (org-roam-dailies--capture
       (current-time) t)
      (setq today-file (buffer-file-name))
      (setq pos (point)))
    (unless (equal (file-truename today-file)
                   (file-truename
                    (buffer-file-name)))
      (org-refile nil nil (list "Tasks" today-file nil pos)))))

(add-to-list 'org-after-todo-state-change-hook
             (lambda ()
               (when (equal org-state "DONE")
                 (phl-org-roam-copy-todo-to-today))))


(global-set-key (kbd "C-c n t") #'phl-org-roam-capture-project-task)
(global-set-key (kbd "C-c n n") #'phl-org-roam-capture-inbox)
(global-set-key (kbd "C-c n p") #'phl-org-roam-find-project)

Programming

Eshell

It just works.

(defun phl-start-new-eshell ()
  "Spawn a new eshell always."
  (interactive)
  (eshell)
  (rename-uniquely))

(global-set-key (kbd "C-c e") #'phl-start-new-eshell)

(defun phl-configure-eshell ()
  ;; Save command history when commands are entered
  (add-hook 'eshell-pre-command-hook 'eshell-save-some-history)

  ;; Truncate buffer for performance
  (add-to-list 'eshell-output-filter-functions 'eshell-truncate-buffer)

  (setq eshell-history-size         10000
        eshell-buffer-maximum-lines 10000
        eshell-hist-ignoredups t
        eshell-scroll-to-bottom-on-input t))

(use-package eshell
  :hook (eshell-first-time-mode . phl-configure-eshell))

Term

It just works more

(require 'term)

(defun phl-start-new-term ()
      "Spawn a new term always."
      (interactive)
      (pop-to-buffer-same-window
       (set-buffer (make-term "terminal" "/bin/zsh")))
      (term-line-mode)
      (rename-uniquely))


(defun phl-term-toggle-mode ()
  "Toggles term between line mode and char mode"
  (interactive)
  (if (term-in-line-mode)
      (term-char-mode)
    (term-line-mode)))

(define-key term-mode-map (kbd "C-c C-j") #'phl-term-toggle-mode)
(define-key term-mode-map (kbd "C-c C-k") #'phl-term-toggle-mode)

(define-key term-raw-map (kbd "C-c C-j") #'phl-term-toggle-mode)
(define-key term-raw-map (kbd "C-c C-k") #'phl-term-toggle-mode)
(global-set-key (kbd "C-c t") #'phl-start-new-term)

Language Server (lsp-mode)

Using lsp-mode because it just works

(use-package lsp-mode
  :commands (lsp lsp-deffered)
  :init
  (setq lsp-keymap-prefix "C-c l")

  :config
  (lsp-enable-which-key-integration t))

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

Dart/Flutter

Surprised how well this is integrated. You just need more packages

flutter.el

(use-package flutter
  :after dart-mode
  :bind (:map dart-mode-map
        ("C-M-x" . #'flutter-run-or-hot-reload))
  :custom
  (setq flutter-sdk-path "/Users/100phlecs/packages/flutter/"))

dart-mode

(use-package dart-mode
  :hook (dart-mode . lsp))

;; UI and such, sine they're dependences of lsp-dart
(use-package flycheck)
(use-package treemacs)
(use-package lsp-treemacs)
(use-package lsp-dart
  :init
  (setq lsp-dart-sdk-dir "/Users/100phlecs/packages/flutter/bin/cache/dart-sdk")
  (setq lsp-dart-flutter-sdk-dir "/Users/100phlecs/packages/flutter")
  (setq lsp-dart-enable-sdk-formatter t))

Common Lisp

alien technology

(use-package sly)
(setq inferior-lisp-program "/opt/homebrew/bin/sbcl")
(use-package rainbow-blocks)
(use-package lispy)

(add-hook
 'emacs-lisp-mode-hook
 (lambda () (lispy-mode 1)
       (company-mode)
       (rainbow-blocks-mode)))

(add-hook
 'lisp-mode-hook
 (lambda () (lispy-mode 1)
       (company-mode)
       (rainbow-blocks-mode)))

(add-hook 'sly-mode-hook (lambda ()
                           (electric-pair-mode)
                           (company-mode)
                           (rainbow-blocks-mode)))

Rust

(use-package rustic
  :bind (:map rustic-mode-map
              ("M-j" . lsp-ui-imenu)
              ("M-?" . lsp-find-references)
              ("C-c C-c l" . flycheck-list-errors)
              ("C-c C-c a" . lsp-execute-code-action)
              ("C-c C-c r" . lsp-rename)
              ("C-c C-c q" . lsp-workspace-restart)
              ("C-c C-c Q" . lsp-workspace-shutdown)
              ("C-c C-c s" . lsp-rust-analyzer-status)
              ("C-c r" . rustic-compile))
  :config
  (progn
  ;; (setq rustic-lsp-setup-p nil)
    (setq rustic-lsp-server 'rust-analyzer)
    (setq rustic-format-on-save nil)
    (setq rustic-indent-offset 2)
    (electric-pair-mode 1)))

Svelte

(use-package web-mode
  :config
  (add-to-list 'auto-mode-alist '("\\.html\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.svelte\\'" . web-mode))
  (setq web-mode-engines-alist
      '(("svelte" "\\.svelte\\'"))))

(add-hook 'web-mode-hook (lambda ()
                            (setq web-mode-code-indent-offset 2)
                            (setq web-mode-markup-indent-offset 2)
                            (setq web-mode-css-indent-offset 2)))

Misc

multiple-cursors

I rarely use this. might remove

(use-package multiple-cursors)

command log

(use-package command-log-mode
:straight (command-log-mode :type git :host github :repo "pierre-rouleau/command-log-mode" :files ("*.el" "*")))

doc-view

Doc view works just fine! but I just prefer to have the pdf in a separate window.

(use-package doc-view
  :config
  (setq doc-view-resolution 400))

About

pocket flint

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors