This is my personal config for Emacs. It is constructed in literate programming using Org-mode for a documented configuration.
If you’re viewing the Org file, you can open source code blocks (those are the ones in begin_src) in a separate buffer by moving your point inside them and typing ` C-c ’ ` (org-edit-special). This opens another buffer in emacs-lisp-mode, so you can use M-x eval-buffer to load the changes. If you want to explore how functions work, use M-x edebug-defun to set up debugging for that function, and then call it.
I use `use-package` and Straight so that all packages are automatically installed if cloning this repo for another machine.
My current configuration uses doom-theme, specifically doom-dracula (everywhere!) and some default settings.
(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
;; Enable flashing mode-line on errors
(doom-themes-visual-bell-config)
;; Corrects (and improves) org-mode's native fontification.
(doom-themes-org-config)
(load-theme 'doom-dracula t))
(use-package doom-modeline
:ensure t
:init (doom-modeline-mode 1)
:config
(setq doom-modeline-battery t)
;; Whether display the time. It respects `display-time-mode'.
(display-time-mode 1)
(setq doom-modeline-time t)
;; Whether to use an analogue clock svg as the live time icon.
;; It respects options `doom-modeline-icon', `doom-modeline-time-icon', and `doom-modeline-time-live-icon'.
(setq doom-modeline-time-analogue-clock t)
;; The scaling factor used when drawing the analogue clock.
(setq doom-modeline-time-clock-size 0.7))
Hide things when emacs starts up, namely the tooltips, toolbar and scrollbar. Also set `C-z` and `C-x C-z` to nil. `C-z` minimizes/hides emacs and it’s enfuriating when I accidently hit that key combo.
(use-package emacs
:init
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(tooltip-mode -1)
:config
(setq inhibit-splash-screen t)
:bind (("C-z" . nil)
("C-x C-z" . nil)))
(set-face-attribute 'default nil :font "JetBrains Mono" :weight 'light :height 120)
(set-face-attribute 'fixed-pitch nil :font "JetBrains Mono" :weight 'light :height 120)
(set-face-attribute 'variable-pitch nil :font "JetBrains Mono" :weight 'light :height 1.0)
Small settings and packages that really don’t have a place anywhere else in this document that warrants it’s own section heading for each one. These are important in how I like my emacs to perform.
(fset 'yes-or-no-p 'y-or-n-p)
(set-frame-font "JetBrains Mono 12")
(setq user-full-name "Greg Newman"
user-mail-address "greg@gregnewman.org")
(setq-default indent-tabs-mode nil)
(setq ring-bell-function (lambda ()))
(setq confirm-kill-emacs 'yes-or-no-p)
(setq require-final-newline t)
(setq-default line-spacing 0.15)
(setq explicit-shell-file-name "/bin/zsh")
(setq backup-directory-alist `(("." . "~/.saves")))
(setq backup-by-copying t)
(setq delete-old-versions t)
(setq kept-new-versions 10)
(setq kept-old-versions 10)
(setq version-control t)
(global-display-line-numbers-mode)
(setq-default display-fill-column-indicator-column 88)
;; always show paren highlights
(show-paren-mode 1)
; highlight current line
(global-hl-line-mode 1)
(set-face-background 'hl-line "#1C1B1A")
;; javascript indents. This can probably be removed once I settle on a "good" js config
(setq js-indent-level 2)
; Desktop setup.
(desktop-save-mode 1)
(setq desktop-dirname "~/.emacs.d/desktops/")
(setq desktop-base-file-name (concat ".desktop." (system-name)))
(setq desktop-path (list desktop-dirname))
(setq desktop-base-lock-name "lock")
(setq desktop-load-locked-desktop t)
; Very useful if dealing with git repos and also files that can change from Dropbox
(global-auto-revert-mode 1)
(setq auto-revert-use-notify nil)
(setq auto-revert-interval 5)
;; Configure where TAGS are stored
(setq tags-table-list (list "~/.emacs.d/TAGS"))
;; isearch improvements
(setq isearch-lazy-count t)
(setq lazy-count-prefix-format nil)
(setq lazy-count-suffix-format " (%s/%s)")
;; some useful settings found in http://yummymelon.com/devnull/surprise-and-emacs-defaults.html
(setq sentence-end-double-space nil)
(setq delete-selection-mode t)
(setq dired-auto-revert-buffer t)
;; associate some of these files with modes
(add-to-list 'auto-mode-alist '("\\.astro\\'" . js-ts-mode))
;; (add-to-list 'auto-mode-alist '("\\.mdx\\'" . markdown-ts-mode))
(setq calendar-latitude 35.064905)
(setq calendar-longitude -80.769724)
(setq calendar-location-name "Charlotte, NC")
;; set default to 95% opaque
(set-frame-parameter (selected-frame) 'alpha '(100 100))
(add-to-list 'default-frame-alist '(alpha 100 100))
;; convenience function to toggle transparency given a value
(defun gn/transparency (value)
"Sets the transparency of the frame window. 0=transparent/100=opaque"
(interactive "nTransparency Value 0 - 100 opaque:")
(set-frame-parameter (selected-frame) 'alpha value))
(global-set-key (kbd "C-c t") 'gn/transparency)
(use-package markdown-mode
:ensure t
:config
(add-to-list 'auto-mode-alist
'("\\.\\(?:md\\|markdown\\|mkd\\|mdown\\|mkdn\\|mdwn\\)\\'" . markdown-mode))
)
;; icons
(use-package all-the-icons)
;; ;; Git Gutter
(use-package git-gutter
:diminish git-gutter-mode
:config (global-git-gutter-mode)
:init
(progn
(setq git-gutter:separator-sign " "
git-gutter:lighter " GG"))
:config
(progn
(set-face-foreground 'git-gutter:deleted "#990A1B")
(set-face-foreground 'git-gutter:modified "#00736F")
(set-face-foreground 'git-gutter:added "#546E00"))
:bind (("C-x p" . git-gutter:previous-hunk)
("C-x n" . git-gutter:next-hunk)
("C-x v =" . git-gutter:popup-hunk)
("C-x v r" . git-gutter:revert-hunk)))
;; Recent files
(setq recentf-save-file (concat user-emacs-directory "recentf")
recentf-max-saved-items 200
recentf-max-menu-items 15)
(recentf-mode t)
Remember my place in files across sessions
(save-place-mode +1)
(setq-default save-place t)
Copied from http://emacsredux.com/blog/2013/05/22/smarter-navigation-to-the-beginning-of-a-line/
(defun my/smarter-move-beginning-of-line (arg)
"Move point back to indentation of beginning of line.
Move point to the first non-whitespace character on this line.
If point is already there, move to the beginning of the line.
Effectively toggle between the first non-whitespace character and
the beginning of the line.
If ARG is not nil or 1, move forward ARG - 1 lines first. If
point reaches the beginning or end of the buffer, stop there."
(interactive "^p")
(setq arg (or arg 1))
;; Move lines first
(when (/= arg 1)
(let ((line-move-visual nil))
(forward-line (1- arg))))
(let ((orig-point (point)))
(back-to-indentation)
(when (= orig-point (point))
(move-beginning-of-line 1))))
;; remap C-a to `smarter-move-beginning-of-line'
(global-set-key [remap move-beginning-of-line]
'my/smarter-move-beginning-of-line)
I forget bindings for modes I don’t use regularly. Which-key provides nice reminders.
(use-package which-key
:init
(which-key-mode)
:config
(which-key-setup-side-window-right-bottom)
(setq which-key-sort-order 'which-key-key-order-alpha
which-key-side-window-max-width 0.33
which-key-idle-delay 0.5)
:diminish which-key-mode)
(provide 'init-which-key)
I use ibuffer a lot for switching between buffers from a list of available open buffers. These settings help to organize that list.
(global-set-key (kbd "C-x C-b") 'ibuffer)
(autoload 'ibuffer "ibuffer" "List buffers." t)
(setq ibuffer-saved-filter-groups
(quote (("default"
("Python"
(mode . python-ts-mode))
("HTML"
(mode . mhtml-mode))
("JS"
(or (mode . js-ts-mode)
(filename . ".js")))
("TXT"
(mode . text-mode))
("YAML"
(filename . "yaml"))
("Org" ;; all org-related buffers
(mode . org-mode))
("Lisp"
(mode . emacs-lisp-mode))))))
;; don't show empty groups
(setq ibuffer-show-empty-filter-groups nil)
(add-hook 'ibuffer-mode-hook
(lambda ()
(ibuffer-switch-to-saved-filter-groups "default")))
;; Add full path to buffer title
(setq frame-title-format
(list (format "%s %%S: %%j " (system-name))
'(buffer-file-name "%f" (dired-directory dired-directory "%b"))))
(use-package hydra)
(defhydra hydra-zoom (global-map "<f2>")
"zoom"
("g" text-scale-increase "in")
("l" text-scale-decrease "out"))
The :ensure-system-package keyword allows you to ensure system binaries exist alongside your package declarations.
(use-package use-package-ensure-system-package
:ensure t)
(use-package just-mode
:ensure t)
(use-package copilot
:straight (:host github :repo "zerolfx/copilot.el" :files ("dist" "*.el"))
:ensure t
:diminish
:config
(setq copilot-node-executable "/opt/homebrew/bin/node")
(add-hook 'prog-mode-hook 'copilot-mode)
(setq copilot-max-char -1)
)
(define-key copilot-completion-map (kbd "<tab>") 'copilot-accept-completion)
(define-key copilot-completion-map (kbd "TAB") 'copilot-accept-completion)
(use-package racket-mode)
(use-package ob-racket
:straight (:type git :host github :repo "hasu/emacs-ob-racket"))
Getting Things Done (GTD), is a grouping of productivity processes following five basic principles.
- Capture - Everything in your mind needs to be captured because your mind is “a horrible office”. This is typically the inbox.org file in my setup but is also done in analog notebooks, email and voice memos.
- Clarify - Every task that doesn’t take two minutes to do should be broken down into actionable tasks that simplify the larger scope of the project.
- Organize - All projects and next actions are organized into areas, assigned due dates if needed, prioritized and effort estimates added to them. If the tasks/projects are not something to do right now they are still organized for later consumption. Anything that needs to be on the calendar should be added but keep the calendar sacred. Calendars should only be for appointments or hard-carved blocks of time.
- Reviews - Reviews should be handled on a regular basis. I do a daily review of what should be the priorities for the day but I also do weekly and monthly reviews to keep my systems from getting stale and/or stuck.
- Engage - Choose the next action and get to work.
I have gitwatch running on my machine which watches my org directory and commits changes as they come in.
gitwatch -r origin -b main . &
Use C-u C-x = (which runs the command what-cursor-position with a prefix argument) to show information about the character under the cursor, including the face which is being used for it.
;; Load org-faces to make sure we can set appropriate faces
(require 'org-faces)
;; Hide emphasis markers on formatted text
(setq org-hide-emphasis-markers t)
;; When Visual Line mode is enabled, `word-wrap' is turned on in this buffer, and simple editing commands are redefined to act on visual lines, not logical lines.
(add-hook 'org-mode-hook 'visual-line-mode)
(add-hook 'org-mode-hook 'variable-pitch-mode)
;; Resize Org headings
(dolist (face '((org-level-1 . 1.0)
(org-level-2 . 1.0)
(org-level-3 . 1.0)
(org-level-4 . 1.0)
(org-level-5 . 1.0)
(org-level-6 . 1.0)
(org-level-7 . 1.0)
(org-level-8 . 1.0)))
(set-face-attribute (car face) nil :font "Monaspace Neon" :weight 'medium :height (cdr face)))
;; Make the document title a bit bigger
(set-face-attribute 'org-document-title nil :font "Monaspace Neon" :weight 'bold :height 1.1)
;; Make sure certain org faces use the fixed-pitch face when variable-pitch-mode is on
(custom-theme-set-faces
'user
'(variable-pitch ((t (:family "Monaspace Neon" :height 120 :weight thin))))
'(fixed-pitch ((t ( :family "Fira Code" :height 115))))
'(org-block ((t (:inherit fixed-pitch))))
'(org-code ((t (:inherit (shadow fixed-pitch)))))
'(org-formula ((t (:inherit fixed-pitch))))
'(org-checkbox ((t (:inherit fixed-pitch))))
'(org-document-info ((t (:foreground "dark orange"))))
'(org-document-info-keyword ((t (:inherit (shadow fixed-pitch)))))
'(org-indent ((t (:inherit (org-hide fixed-pitch)))))
'(org-link ((t (:foreground "cyan" :underline t :weight light))))
'(org-meta-line ((t (:inherit (font-lock-comment-face fixed-pitch)))))
'(org-property-value ((t (:inherit fixed-pitch))) t)
'(org-special-keyword ((t (:inherit (font-lock-comment-face fixed-pitch)))))
'(org-table ((t (:inherit fixed-pitch :foreground "#83a598"))))
'(org-tag ((t (:inherit (shadow fixed-pitch) :weight bold :height 0.9))))
'(org-verbatim ((t (:inherit (shadow fixed-pitch))))))
This will be a expanding collection of org customization. I live in text files throughout my days and orgmode gives me a nice interface for collecting notes. I use org from the git repo to stay up to date with fixes and new features. I can probably move this to be installed via Straight but for now this works fine.
(setq org-modules '(org-protocol))
(eval-after-load 'org
'(org-load-modules-maybe t))
;; respects splits
(setq org-agenda-window-setup 'current-window)
;; agenda files
(setq org-agenda-files (directory-files-recursively "~/Dropbox/Org/" "\\.org$"))
;; Start the weekly agenda on Monday
(setq org-agenda-start-on-weekday 1)
;; Display tags farther right
(setq org-agenda-tags-column -102)
(setq org-agenda-span 7)
(setq org-tags-column 88)
(setq org-agenda-sticky nil)
(setq org-agenda-inhibit-startup t)
(setq org-agenda-use-tag-inheritance t)
(setq org-agenda-show-log t)
(setq org-agenda-skip-scheduled-if-done t)
(setq org-agenda-skip-deadline-if-done t)
(setq org-use-speed-commands t)
(setq org-agenda-skip-deadline-prewarning-if-scheduled 'pre-scheduled)
(setq org-columns-default-format "%14SCHEDULED %Effort{:} %CLOCKSUM_T{:} %1PRIORITY %TODO %50ITEM %TAGS")
;; The following lines are always needed. Choose your own keys.
(global-set-key "\C-cl" 'org-store-link)
(global-set-key "\C-ca" 'org-agenda)
;; enable line breaks
(add-hook 'org-mode-hook (lambda () (setq truncate-lines nil)))
;; Don't allow parent to be marked done unless children are done
(setq org-enforce-todo-dependencies t)
(setq org-enforce-todo-checkbox-dependencies t)
(setq org-fontify-done-headline t)
(setq org-startup-folded t)
(setq org-src-fontify-natively nil)
;; Refiling
(setq org-refile-targets '((org-agenda-files :maxlevel . 5)))
(setq org-refile-allow-creating-parent-nodes 'confirm)
;; Visual Line Mode
(add-hook 'org-mode-hook 'visual-line-mode)
;; Org indent mode
(add-hook 'org-mode-hook 'org-indent-mode)
;; Line numbers
(defun gn/orgmode-ignore-line-numbers-mode ()
(interactive)
"turns off line numbers mode in org buffers"
(display-line-numbers-mode -1))
(add-hook 'org-mode-hook #'gn/orgmode-ignore-line-numbers-mode)
(defun gn/orgmode-ignore-whitespace-mode ()
(interactive)
"turns off whitespace mode in org buffers"
(whitespace-mode -1))
;; Turn off whitespace-mode since my linters will handle them anyway and it's annoying
(whitespace-mode -1)
(use-package org-alert
:straight t
:ensure t
:config
(setq org-alert-interval 60
org-alert-notify-cutoff 5
org-alert-notify-after-event-cutoff 2)
(org-alert-enable))
(use-package alert
:straight t
:config
(setq alert-default-style 'osx-notifier
alert-fade-time 120))
Setting up my todo keywords which are global and their relative colors.
;; Keywords
(setq org-todo-keywords
(quote ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)" "PROJECTDONE(e)")
(sequence "WAITING(w@/!)" "SOMEDAY(s@/!)" "|" "CANCELLED(c@/!)"))))
;; Anytime a task is marked done the line states `CLOSED: [timestamp]
(setq org-log-done 'time)
(setq org-todo-keyword-faces
(quote (("TODO" :foreground "lime green" :weight bold)
("NEXT" :foreground "cyan" :weight bold)
("DONE" :foreground "dim gray" :weight bold)
("PROJECTDONE" :foreground "dim gray" :weight bold)
("WAITING" :foreground "tomato" :weight bold)
("SOMEDAY" :foreground "magenta" :weight bold)
("CANCELLED" :foreground "dim gray" :weight bold))))
I use C-c c to start capture mode
(global-set-key (kbd "C-c c") 'org-capture)
Capture template are critical for keeping focused on the current work and not getting sent down the proverbial rabbit hole. It’s also handy for knowledge investements while working. For instance, a method in a python library I need to understand more deeply, I can trigger the capture template for Knowledge Investments with `C=c c k`, add some context and with `C=c C=c` close and save the capture without leaving my position in the file. The link to where I found the method is captured in the template and I can visit that later in the day when I have time to dive deep.
For my reference the syntax is as follows
("t" "Todo" entry (file "~/Dropbox/Org/inbox.org") "* TODO %?\n%U\n%a\n" :clock-keep t)
`t` is the trigger key for Todo. Todo entry is layman’s term for the capture followed by what file to store it in. The instruction regex starts with the tag or keyword then template expansions.
- %? Position the cursor where I was
- %u, %U Inactive timestamp
- %a annotation, normally the link created with org-store-link
- :clock-keep keeps the clock running if I’m clocking a task
;; Capture templates
(setq org-indent-indentation-per-level 2)
(setq org-capture-templates
(quote (("t" "Todo" entry (file "~/Dropbox/Org/inbox.org")
"* TODO %?\n%U\n%a\n" :clock-keep t)
("k" "Knowledge Investment" entry (file "~/Dropbox/Org/inbox.org")
"* %? :KI:\n%U\n%a\n" :clock-keep t)
("n" "Note" entry (file "~/Dropbox/Org/inbox.org")
"* %? :NOTE:\n%U\n%a\n" :clock-keep t)
("d" "Daybook" entry (file+olp+datetree "~/Dropbox/Org/daybook.org")
"* %?" :clock-keep t)
("o" "OBTF" entry (file+olp+datetree "~/Dropbox/Org/OBTF.org")
"* %<%H:%M> %?" :jump-to-captured t)
("m" "Meeting" entry (file "~/Dropbox/Org/inbox.org")
"* Meeting with %? :MEETING:\n%U" :clock-keep t)
("p" "Phone call" entry (file "~/Dropbox/Org/inbox.org")
"* PHONE %? :PHONE:\n%U" :clock-keep t))))
(org-babel-do-load-languages
'org-babel-load-languages
'(
(python . t)
(js . t)
(emacs-lisp . t)
(org . t)
(sql . t)
(ditaa . t)
(racket . t)
))
;; Syntax highlight in #+BEGIN_SRC blocks
(setq org-src-fontify-natively t)
;; Don't prompt before running code in org
(setq org-confirm-babel-evaluate nil)
Pulled some ideas from https://blog.aaronbieber.com/2016/09/24/an-agenda-for-life-with-org-mode.html Some of these have been yanked from bnb-emacs
(defun gn/org-skip-subtree-if-priority (priority)
"Skip an agenda subtree if it has a priority of PRIORITY.
PRIORITY may be one of the characters ?A, ?B, or ?C."
(let ((subtree-end (save-excursion (org-end-of-subtree t)))
(pri-value (* 1000 (- org-lowest-priority priority)))
(pri-current (org-get-priority (thing-at-point 'line t))))
(if (= pri-value pri-current)
subtree-end
nil)))
(defun gn/org-agenda-with-tip (arg)
(org-agenda-list arg)
(let ((inhibit-read-only t)
(pos (point)))
(goto-char (point-max))
(goto-char pos)))
;; Reset everything to nil
(setq org-agenda-custom-commands nil)
(add-to-list 'org-agenda-custom-commands
'("b" "Agenda" gn/org-agenda-with-tip))
(add-to-list 'org-agenda-custom-commands
'("N" "Notes" tags "NOTE"
((org-agenda-overriding-header "Notes")
(org-tags-match-list-sublevels t))))
(add-to-list 'org-agenda-custom-commands
'("k" "Knowledge Investments" tags "KI"
((org-agenda-overriding-header "Knowledge Investments")
(org-tags-match-list-sublevels t))))
;; Taken from doc.norang.ca/org-mode.html
(add-to-list 'org-agenda-custom-commands
'("c" "Simple agenda view"
((agenda "")
(tags "PRIORITY=\"A\""
((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
(org-agenda-overriding-header "HIGH PRIORITY ITEMS")))
(alltodo ""
((org-agenda-skip-function
'(or (gn/org-skip-subtree-if-priority ?A)
(org-agenda-skip-if nil '(scheduled deadline)))))))))
(add-to-list 'org-agenda-custom-commands
'("f" . "FOCUS...") t)
(add-to-list 'org-agenda-custom-commands
'("d" "All Tasks (grouped by Due Date)"
((tags-todo "DEADLINE<\"<+0d>\""
((org-agenda-overriding-header "OVERDUE")
(org-agenda-skip-function
'(org-agenda-skip-entry-if 'notdeadline))))
(tags-todo "DEADLINE=\"<+0d>\""
((org-agenda-overriding-header "DUE TODAY")
(org-agenda-skip-function
'(org-agenda-skip-entry-if 'notdeadline))))
(tags-todo "DEADLINE=\"<+1d>\""
((org-agenda-overriding-header "DUE TOMORROW")
(org-agenda-skip-function
'(org-agenda-skip-entry-if 'notdeadline))))
(tags-todo "DEADLINE>\"<+1d>\"+DEADLINE<=\"<+7d>\""
((org-agenda-overriding-header "DUE WITHIN A WEEK")
(org-agenda-skip-function
'(org-agenda-skip-entry-if 'notdeadline))))
(tags-todo "DEADLINE>\"<+7d>\"+DEADLINE<=\"<+28d>\""
((org-agenda-overriding-header "DUE WITHIN A MONTH")
(org-agenda-skip-function
'(org-agenda-skip-entry-if 'notdeadline))))
(tags-todo "DEADLINE>\"<+28d>\""
((org-agenda-overriding-header "DUE LATER")
(org-agenda-skip-function
'(org-agenda-skip-entry-if 'notdeadline))))
(tags-todo "TODO={WAIT}"
((org-agenda-overriding-header "WAITING FOR")
(org-agenda-skip-function
'(org-agenda-skip-entry-if 'deadline))))
(todo ""
((org-agenda-overriding-header "UNSCHEDULED")
(org-agenda-skip-function
'(org-agenda-skip-entry-if 'deadline)))))
((org-agenda-sorting-strategy '(priority-down))
(org-agenda-write-buffer-name "All Tasks (grouped by Due Date)"))
"~/Dropbox/Org/all-tasks-by-due-date.pdf") t)
(add-to-list 'org-agenda-custom-commands
`("f." "Today"
((agenda ""
((org-agenda-entry-types '(:timestamp :sexp))
(org-agenda-overriding-header
(concat "CALENDAR Today: "
(format-time-string "%a %d" (current-time))))
(org-agenda-span 'day)))
(tags-todo "DEADLINE=\"<+0d>\""
((org-agenda-overriding-header "DUE TODAY")
(org-agenda-skip-function
'(org-agenda-skip-entry-if 'notedeadline))
(org-agenda-sorting-strategy '(priority-down))))
(tags-todo "DEADLINE<\"<+0d>\""
((org-agenda-overriding-header "OVERDUE")
(org-qagenda-skip-function
'(org-agenda-skip-entry-if 'notedeadline))
(org-agenda-sorting-strategy '(priority-down))))
(agenda ""
((org-agenda-entry-types '(:scheduled))
(org-agenda-overriding-header "SCHEDULED")
(org-agenda-skip-function
'(org-agenda-skip-entry-if 'todo 'done))
(org-agenda-sorting-strategy
'(priority-down time-down))
(org-agenda-span 'day)
(org-agenda-start-on-weekday nil)
(org-agenda-time-grid nil)))
(todo "DONE"
((org-agenda-overriding-header "COMPLETED"))))
((org-agenda-format-date "")
(org-agenda-start-with-clockreport-mode nil))) t)
(add-to-list 'org-agenda-custom-commands
'("fh" "Hotlist"
((tags-todo "DEADLINE<\"<+0d>\""
((org-agenda-overriding-header "OVERDUE")))
(tags-todo "DEADLINE>=\"<+0d>\"+DEADLINE<=\"<+1w>\""
((org-agenda-overriding-header "DUE IN NEXT 7 DAYS")))
(tags-todo "DEADLINE=\"\"+FLAGGED|DEADLINE>\"<+1w>\"+FLAGGED"
((org-agenda-overriding-header "FLAGGED"))))
((org-agenda-todo-ignore-scheduled 'future))) t)
(add-to-list 'org-agenda-custom-commands
'("r" . "REVIEW...") t)
(add-to-list 'org-agenda-custom-commands
'("ra" . "All Tasks...") t)
(add-to-list 'org-agenda-custom-commands
'("rt" . "Timesheet...") t)
;; Show what happened today.
(add-to-list 'org-agenda-custom-commands
'("rtd" "Daily Timesheet"
((agenda ""))
((org-agenda-log-mode-items '(clock closed))
(org-agenda-overriding-header "DAILY TIMESHEET")
(org-agenda-show-log 'clockcheck)
(org-agenda-span 'day)
(org-agenda-start-with-clockreport-mode t)
(org-agenda-time-grid nil))) t)
;; Show what happened this week.
(add-to-list 'org-agenda-custom-commands
'("rtw" "Weekly Timesheet"
((agenda ""))
(
;; (org-agenda-format-date "")
(org-agenda-overriding-header "WEEKLY TIMESHEET")
(org-agenda-skip-function '(org-agenda-skip-entry-if 'timestamp))
(org-agenda-span 'week)
(org-agenda-start-on-weekday 1)
(org-agenda-start-with-clockreport-mode t)
(org-agenda-time-grid nil))) t)
(add-to-list 'org-agenda-custom-commands
'("rw" "Weekly review"
((tags "CATEGORY={@REFILE}&LEVEL<=2"
((org-agenda-overriding-header "NEW TASKS")))
(agenda ""
((org-agenda-clockreport-mode t)
(org-agenda-format-date
(concat "\n"
"%Y-%m-%d" " %a "
(make-string (window-width) ?_)))
(org-agenda-overriding-header "PAST WEEK")
(org-agenda-prefix-format " %?-11t %i %-12:c% s")
(org-agenda-show-log 'clockcheck)
(org-agenda-span 7)
(org-agenda-start-day "-1w")
(org-deadline-warning-days 0)))
(agenda ""
((org-agenda-overriding-header "NEXT 30 DAYS")
(org-agenda-span 'month)
(org-agenda-start-day "+0d")
(org-deadline-warning-days 0)))
(tags "PROJECT"
((org-agenda-overriding-header "PROJECT LIST")))
(todo "DONE|PROJECTDONE"
((org-agenda-overriding-header
"Candidates to be archived"))))))
Org-Super-Agenda commands
(use-package org-super-agenda
:straight
(org-super-agenda
:type git
:host github
:repo "alphapapa/org-super-agenda")
:config
(org-super-agenda-mode t)
(add-to-list 'org-agenda-custom-commands
'("gt" "All Tasks - Grouped"
((todo "" ((org-super-agenda-groups
'((:name "All Tasks" :auto-category t)))))))))
Using org buillets and hiding leading stars. I’m also fontifying headings, quotes and done headlines.
(use-package org-bullets
:commands org-bullets-mode
:init
(add-hook 'org-mode-hook 'org-bullets-mode))
(progn
(require 'org-indent)
(org-indent-mode t))
(setq org-hide-leading-stars t)
(setq org-fontify-whole-heading-line t)
(setq org-fontify-quote-and-verse-blocks t)
(setq org-fontify-done-headline t)
(use-package org-download)
(setq-default org-download-image-dir "~/Dropbox/Org/img")
(use-package org-fancy-priorities
:ensure t
:hook
(org-mode . org-fancy-priorities-mode)
:config
(setq org-fancy-priorities-list '("🅰️" "🅱️" "1️⃣" "☕")))
(use-package org-roam ;; :straight t (org-roam :type git :host github :repo “org-roam/org-roam”) :straight t :init (setq org-roam-directory (file-truename “~/Dropbox/Org/”)) (setq org-roam-file-extensions ‘(“org” “md”)) (setq org-roam-dailies-directory “dailies”) (setq find-file-visit-truename t) (setq org-roam-mode-sections (list #’org-roam-backlinks-section #’org-roam-reflinks-section #’org-roam-unlinked-references-section )) :custom (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-database-connector ‘sqlite-builtin)
:bind ((“C-c n l” . org-roam-buffer-toggle) (“C-c n t” . org-roam-dailies-goto-today) (“C-c n f” . org-roam-node-find) (“C-c n i” . org-roam-node-insert)) :config (org-roam-setup) )
;; Documenation: https://github.com/nobiot/md-roam (use-package md-roam :straight (:host github :repo “nobiot/md-roam”) :after org-roam ) (md-roam-mode 1) (setq md-roam-file-extension “md”)
(org-roam-db-autosync-mode)
Denote for taking notes and consult-notes for quickly searching
(use-package denote
:custom
((denote-directory "~/Dropbox/Org/denote/")
(denote-prompts '(title keywords))
;; Use orgmode format by default
(denote-file-type 'org)
(denote-date-prompt-use-org-read-date t))
:hook
(dired-mode . denote-dired-mode))
(use-package consult-notes
:commands (consult-notes
consult-notes-search-in-all-notes
;; if using org-roam
consult-notes-org-roam-find-node
consult-notes-org-roam-find-node-relation)
:config
(setq consult-notes-file-dir-sources '(("Org" ?o "~/Dropbox/Org/")
("Denote" ?d "~/Dropbox/Org/denote/")))
(consult-notes-org-headings-mode)
(consult-notes-denote-mode)
;; search only for text files in denote dir
(setq consult-notes-denote-files-function (function denote-directory-text-only-files)))
When starting emacs gui on Mac OS, the paths are not read from .zshrc Using `exec-path-from-shell` fixes this.
(use-package exec-path-from-shell
:config
(when (memq window-system '(mac ns x))
(exec-path-from-shell-initialize)))
(use-package pyenv-mode-auto)
(defun pyenv-activate-current-project ()
"Automatically activates pyenv version if .python-version file exists."
(interactive)
(let ((python-version-directory (locate-dominating-file (buffer-file-name) ".python-version")))
(if python-version-directory
(let* ((pyenv-version-path (f-expand ".python-version" python-version-directory))
(pyenv-current-version (s-trim (f-read-text pyenv-version-path 'utf-8))))
(pyenv-mode-set pyenv-current-version)
(message (concat "Setting virtualenv to " pyenv-current-version))))))
(defvar pyenv-current-version nil nil)
(defun pyenv-init()
"Initialize pyenv's current version to the global one."
(let ((global-pyenv (replace-regexp-in-string "\n" "" (shell-command-to-string "pyenv global"))))
(message (concat "Setting pyenv version to " global-pyenv))
(pyenv-mode-set global-pyenv)
(setq pyenv-current-version global-pyenv)))
(add-hook 'after-init-hook 'pyenv-init)
(use-package pyenv-mode)
;; Fixes an issue where pyenv conflicts with org-mode
(eval-after-load 'pyenv-mode
'(progn
(define-key pyenv-mode-map (kbd "C-c C-s") nil)))
(add-hook 'python-ts-mode-hook #'display-fill-column-indicator-mode)
(use-package project :ensure t)
Automatically install and use tree-sitter major modes in Emacs 29+. If the tree-sitter version can’t be used, fall back to the original major mode.
(setq major-mode-remap-alist
'((yaml-mode . yaml-ts-mode)
(bash-mode . bash-ts-mode)
(js-mode . js-ts-mode)
(js2-mode . js-ts-mode)
(js-base-mode . js-ts-mode)
(typescript-mode . typescript-ts-mode)
(json-mode . json-ts-mode)
(css-mode . css-ts-mode)
(python-mode . python-ts-mode)))
;; Eglot
;; (use-package eglot
;; ;; :ensure t
;; ;; :defer t
;; :bind (:map eglot-mode-map
;; ("C-c l a" . eglot-code-actions)
;; ("C-c l qr" . eglot-rename)
;; ("C-c l f" . eglot-format)
;; ("C-c l d" . eldoc))
;; :hook ((python-ts-mode . eglot-ensure)
;; (js-ts-mode . eglot-ensure)
;; (typescript-ts-mode . eglot-ensure)
;; (python-ts-mode . superword-mode)
;; (python-ts-mode . hs-minor-mode)
;; (python-ts-mode . (lambda () (set-fill-column 88)))))
;; ;; :config
;; ;; (setq-default eglot-workspace-configuration
;; '((:pylsp . (:configurationSources ["flake8"]
;; :plugins (
;; :pycodestyle (:enabled :json-false)
;; :mccabe (:enabled :json-false)
;; :pyflakes (:enabled :json-false)
;; :flake8 (:enabled :json-false
;; :maxLineLength 88)
;; :ruff (:enabled t
;; :lineLength 88)
;; :pydocstyle (:enabled t
;; :convention "numpy")
;; :yapf (:enabled :json-false)
;; :autopep8 (:enabled :json-false)
;; :black (:enabled t
;; :line_length 88
;; :cache_config t)))))))
;; (with-eval-after-load 'eglot
;; (add-to-list 'eglot-server-programs
;; '(js-ts-mode . ("typescript-language-server" "--stdio"))))
;; ;;
;; (add-to-list 'eglot-server-programs '(js-ts-mode . ("typescript-language-server" "--stdio")))
;; Tree-sitter
(use-package treesit-auto
:straight (:host github :repo "renzmann/treesit-auto")
:config
(setq treesit-auto-install 'prompt)
(treesit-auto-add-to-auto-mode-alist 'all)
(global-treesit-auto-mode)
(add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode))
;; Eldoc
(use-package eldoc
:init
(global-eldoc-mode))
;; Enable vertico
(use-package vertico
:custom
(vertico-count 13) ; Number of candidates to display
(vertico-resize t)
(vertico-cycle nil) ; Go from last to first candidate and first to last (cycle)?
:init
(vertico-mode))
(use-package savehist
:init
(savehist-mode))
;; Optionally use the `orderless' completion style.
(use-package orderless
:init
;; Configure a custom style dispatcher (see the Consult wiki)
;; (setq orderless-style-dispatchers '(+orderless-dispatch)
;; orderless-component-separator #'orderless-escapable-split-on-space)
(setq completion-styles '(orderless basic)
completion-category-defaults nil
completion-category-overrides '((file (styles partial-completion)))))
;; Enable rich annotations using the Marginalia package
(use-package marginalia
;; Either bind `marginalia-cycle' globally or only in the minibuffer
:bind (("M-A" . marginalia-cycle)
:map minibuffer-local-map
("M-A" . marginalia-cycle))
:custom
(marginalia-max-relative-age 0)
(marginalia-align 'right)
:init
(marginalia-mode))
;; borrowed from Jeremy https://github.com/jeremyf/dotemacs/blob/4bdb58ea43e5dfcdd2025d54193598be0a9dd5b9/emacs.d/jf-completing.el#L219-L227
(require 'consult-imenu)
(dolist (python '(python-mode python-ts-mode))
(add-to-list 'consult-imenu-config
`(,python
:toplevel "Method"
:types ((?f "Field" font-lock-variable-name-face)
(?c "Class" font-lock-property-use-face)
(?m "Method" font-lock-function-name-face)
(?M "Module" font-lock-builtin-face)
(?v "Variable" font-lock-variable-name-face)
))))
(use-package consult-projectile
:straight (consult-projectile :type git :host gitlab :repo "OlMon/consult-projectile" :branch "master")
:commands (consult-projectile)
:bind (("C-x 4 p" . consult-projectile-find-file-other-window)))
;;("M-s r" . consult-ripgrep)
;;("M-s f" . projectile-ripgrep)))
(use-package consult-dir
;; This package helps ease traveling across directories by providing directory
;; candidates related to current buffers, bookmarks, and projects. Further,
;; like other ~consult.el~ functions, you can use narrowing keys. See
;; https://github.com/karthink/consult-dir.
:straight t
:after (consult)
:bind (("C-x C-d" . consult-dir)
:map minibuffer-local-completion-map
("C-x C-d" . consult-dir)
("C-x C-j" . consult-dir-jump-file)))
;; Embark - this config is taken directly from https://github.com/oantolin/embark
(use-package embark
:ensure t
:bind
(("C-." . embark-act) ;; pick some comfortable binding
("C-;" . embark-dwim) ;; good alternative: M-.
("C-h B" . embark-bindings)) ;; alternative for `describe-bindings'
:init
;; Optionally replace the key help with a completing-read interface
(setq prefix-help-command #'embark-prefix-help-command)
;; Show the Embark target at point via Eldoc. You may adjust the
;; Eldoc strategy, if you want to see the documentation from
;; multiple providers. Beware that using this can be a little
;; jarring since the message shown in the minibuffer can be more
;; than one line, causing the modeline to move up and down:
;; (add-hook 'eldoc-documentation-functions #'embark-eldoc-first-target)
;; (setq eldoc-documentation-strategy #'eldoc-documentation-compose-eagerly)
:config
;; 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)))))
;; Consult users will also want the embark-consult package.
(use-package embark-consult
:ensure t ; only need to install it, embark loads it after consult if found
:hook
(embark-collect-mode . consult-preview-at-point-mode))
(use-package all-the-icons-completion
:after (marginalia all-the-icons)
:hook (marginalia-mode . all-the-icons-completion-marginalia-setup)
:init
(all-the-icons-completion-mode))
(use-package cape
;; Completion at point functions, with the amazing `cape-capf-super' for
;; granular configuration of specific mode completion behavior.
:straight t
:init
(add-to-list 'completion-at-point-functions #'cape-dabbrev)
(add-to-list 'completion-at-point-functions #'cape-file)
(add-to-list 'completion-at-point-functions #'cape-keyword)
:bind (("C-c h d" . cape-dabbrev)
("C-c h e" . cape-elisp-block)
("C-c h f" . cape-file)
("C-c h h" . cape-history)
;; ("C-c h s" . cape-symbol)
("C-c h w" . cape-dict)))
(use-package corfu
;; Optional customizations
;; :custom
;; (corfu-cycle t) ;; Enable cycling for `corfu-next/previous'
;; (corfu-auto t) ;; Enable auto completion
;; (corfu-separator ?\s) ;; Orderless field separator
;; (corfu-quit-at-boundary nil) ;; Never quit at completion boundary
;; (corfu-quit-no-match nil) ;; Never quit, even if there is no match
;; (corfu-preview-current nil) ;; Disable current candidate preview
;; (corfu-preselect 'prompt) ;; Preselect the prompt
;; (corfu-on-exact-match nil) ;; Configure handling of exact matches
;; (corfu-scroll-margin 5) ;; Use scroll margin
;; Enable Corfu only for certain modes.
;; :hook ((prog-mode . corfu-mode)
;; (shell-mode . corfu-mode)
;; (eshell-mode . corfu-mode))
;; Recommended: Enable Corfu globally. This is recommended since Dabbrev can
;; be used globally (M-/). See also the customization variable
;; `global-corfu-modes' to exclude certain modes.
:init
(global-corfu-mode))
;; A few more useful configurations...
(use-package emacs
:init
;; TAB cycle if there are only few candidates
;; (setq completion-cycle-threshold 3)
;; Enable indentation+completion using the TAB key.
;; `completion-at-point' is often bound to M-TAB.
(setq tab-always-indent 'complete)
;; Emacs 30 and newer: Disable Ispell completion function. As an alternative,
;; try `cape-dict'.
(setq text-mode-ispell-word-completion nil)
;; Emacs 28 and newer: Hide commands in M-x which do not apply to the current
;; mode. Corfu commands are hidden, since they are not used via M-x. This
;; setting is useful beyond Corfu.
(setq read-extended-command-predicate #'command-completion-default-include-p))
It looks like rg.el has more options for regex when searching
(use-package projectile
:bind-keymap
("C-c p" . projectile-command-map))
(use-package rg
:ensure-system-package rg)
(use-package company
:config
(setq company-minimum-prefix-length 1
company-idle-delay 0
company-tooltip-limit 10
company-transformers nil
company-show-numbers t)
(global-company-mode +1))
; (use-package company-lsp
; :after company
; :config
; (setq company-lsp-enable-snippet nil)
; :init (add-to-list 'company-backends 'company-capf))
(use-package company-box
:hook (company-mode . company-box-mode))
(use-package magit
:bind ("C-x g" . magit-status))
(use-package magit-todos
:after magit
:after hl-todo
:config
(setq magit-todos-depth 2)
(setq magit-todos-exclude-globs '("*.js.map"))
(magit-todos-mode))
(use-package hl-todo
:config
;; Adding a new keyword: TEST.
(add-to-list 'hl-todo-keyword-faces '("TODO" . "gold"))
(add-to-list 'hl-todo-keyword-faces '("Fixme" . "orange"))
:init
(add-hook 'python-ts-mode-hook (lambda () (hl-todo-mode t)))
)
Repo and documentation https://github.com/Silex/docker.el
(use-package docker
:ensure t
:bind ("C-c d" . docker))
(use-package winner
:ensure t
:commands (winner-undo winner-redo)
:custom
(winner-boring-buffers '("*Completions*" "*Help*" "*Apropos*" "*Buffer List*" "*info*" "*Compile-Log*")))
(winner-mode 1)
Avy makes searching and selecting so much easier. `M-s` is my keybinding, type a string and choose the selection in buffer.
(use-package avy
:ensure t
:config
(avy-setup-default)
:bind ("M-s" . avy-goto-char-timer))
(use-package rainbow-mode
:hook (emacs-lisp-mode web-mode python-ts-mode))
(use-package yasnippet)
(use-package yasnippet-snippets)
(yas-global-mode 1)
Trying out some nicer looking indent bars from jdtsmith/indent-bars
(use-package indent-bars
:straight (indent-bars :type git :host github :repo "jdtsmith/indent-bars")
:custom
(indent-bars-treesit-support t)
(indent-bars-no-descend-string t)
(indent-bars-treesit-ignore-blank-lines-types '("module"))
(indent-bars-treesit-wrap '((python argument_list parameters ; for python, as an example
list list_comprehension
dictionary dictionary_comprehension
parenthesized_expression subscript)))
:config
(setq
indent-bars-color '(highlight :face-bg t :blend 0.2)
indent-bars-prefer-character 1
indent-bars-pattern ".*.*.*.*"
indent-bars-width-frac 0.5
indent-bars-pad-frac 0.2
indent-bars-zigzag 0.1
indent-bars-color-by-depth '(:palette ("red" "green" "orange" "cyan") :blend 1)
indent-bars-highlight-current-depth '(:blend 0.5))
:hook
((python-base-mode yaml-mode js-base-mode web-mode) . indent-bars-mode))
;; Org-mac-link is being pulled from Jeremy's fork. I was getting errors with the main repo.
(use-package org-mac-link
;; Similar to `grab-mac-link' but a bit specific to `org-mode'.
:straight (org-mac-link :type git :host github :repo "jeremyf/org-mac-link")
:bind (:map org-mode-map (("C-c g" . org-mac-grab-link))))
(use-package golden-ratio
:ensure t
:diminish golden-ratio-mode
:init
(golden-ratio-mode 0))
(use-package logos
:ensure t
:config
(setq logos-outlines-are-pages t)
)
(use-package olivetti
:ensure t)
(use-package nov
:ensure t
:config
(add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode)))
;; Casual Avy
;; https://github.com/kickingvegas/casual-avy
(use-package casual-avy
:straight
(casual-avy
:type git
:host github
:repo "kickingvegas/casual-avy")
:bind ("M-g" . casual-avy-tmenu))
;; Casual Dired
;; https://github.com/kickingvegas/casual-dired
(use-package casual-dired
:straight
(casual-dired
:type git
:host github
:repo "kickingvegas/casual-dired")
:bind (:map dired-mode-map ("C-o" . 'casual-dired-tmenu)))
(use-package emojify
:hook (after-init . global-emojify-mode))
Activities, this Emacs library allows the user to manage frames/tabs, windows, and buffers according to their purpose. An “activity” comprises a frame or tab, its window configuration, and the buffers displayed in them–its “state”; this state would be related to a certain task the user performs at various times, such as developing a certain software project, reading and writing email, working with one’s Org mode system, etc.
(use-package activities
:init
(activities-mode)
;; (activities-tabs-mode) ;; if you want tabs
;; Prevent `edebug' default bindings from interfering.
(setq edebug-inhibit-emacs-lisp-mode-bindings t)
:bind
(("C-x C-a C-n" . activities-new)
("C-x C-a C-d" . activities-define)
("C-x C-a C-a" . activities-resume)
("C-x C-a C-s" . activities-suspend)
("C-x C-a C-k" . activities-kill)
("C-x C-a RET" . activities-switch)
("C-x C-a b" . activities-switch-buffer)
("C-x C-a g" . activities-revert)
("C-x C-a l" . activities-list)))
http://emacswiki.org/emacs/BookMarks
Keystroke | Action |
---|---|
C-x r m | Set a bookmark |
C-x r b | Jump to a bookmark |
C-x r l | List your bookmarks |
M-x bookmark-delete | Delete bookmark by name |
(setq bookmark-save-flag t
bookmark-set-fringe-mark t
bookmark-menu-confirm-deletion t)
Documentation NANOG — bmag/imenu-list: Emacs plugin to show the current buffer’s imenu entries in a separate buffer
(use-package imenu-list)
(global-set-key (kbd "C-'") #'imenu-list-smart-toggle)
(setq imenu-list-focus-after-activation t)
(use-package lua-mode)