summaryrefslogtreecommitdiff
path: root/config.org
diff options
context:
space:
mode:
Diffstat (limited to 'config.org')
-rw-r--r--config.org420
1 files changed, 148 insertions, 272 deletions
diff --git a/config.org b/config.org
index 02548ca..054b59e 100644
--- a/config.org
+++ b/config.org
@@ -10,18 +10,18 @@ These settings have to exist before the first GUI frame is created, so they
tangle into =early-init.el=.
#+begin_src emacs-lisp :tangle early-init.el
-;;; early-init.el --- generated from config.org -*- lexical-binding: t; -*-
+ ;;; early-init.el --- generated from config.org -*- lexical-binding: t; -*-
-;;; Commentary:
+ ;;; Commentary:
-;; This file is generated from config.org. Do not edit it directly.
+ ;; This file is generated from config.org. Do not edit it directly.
-;;; Code:
+ ;;; Code:
-(dolist (parameter '((width . 140)
- (height . 42)))
- (add-to-list 'default-frame-alist parameter)
- (add-to-list 'initial-frame-alist parameter))
+ (dolist (parameter '((width . 140)
+ (height . 42)))
+ (add-to-list 'default-frame-alist parameter)
+ (add-to-list 'initial-frame-alist parameter))
#+end_src
* Bootstrapping
@@ -29,22 +29,22 @@ tangle into =early-init.el=.
This is the start of the main runtime entry point, which tangles into =init.el=.
#+begin_src emacs-lisp
-;;; init.el --- generated from config.org -*- lexical-binding: t; -*-
+ ;;; init.el --- generated from config.org -*- lexical-binding: t; -*-
-;;; Commentary:
+ ;;; Commentary:
-;; This file is generated from config.org. Do not edit it directly.
+ ;; This file is generated from config.org. Do not edit it directly.
-;;; Code:
+ ;;; Code:
-(let ((minver "27.1"))
- (when (version< emacs-version minver)
- (error "Your Emacs is too old -- this config requires v%s or higher" minver)))
-(when (version< emacs-version "28.1")
- (message
- (concat
- "Your Emacs is old, and some functionality in this config will be "
- "disabled. Please upgrade if possible.")))
+ (let ((minver "27.1"))
+ (when (version< emacs-version minver)
+ (error "Your Emacs is too old -- this config requires v%s or higher" minver)))
+ (when (version< emacs-version "28.1")
+ (message
+ (concat
+ "Your Emacs is old, and some functionality in this config will be "
+ "disabled. Please upgrade if possible.")))
#+end_src
* Shared paths and system identity
@@ -58,22 +58,10 @@ configuration, including the Org directory under =~/org/=.
(defconst *is-a-linux* (eq system-type 'gnu/linux))
(defconst *is-a-mac* (eq system-type 'darwin))
- (defun ss/home-path (path)
- "Expand PATH relative to the user's home directory."
- (expand-file-name path "~"))
-
- (defun ss/config-path (path)
- "Expand PATH relative to `user-emacs-directory'."
- (expand-file-name path user-emacs-directory))
-
- (defun ss/org-path (path)
- "Expand PATH relative to the Org directory."
- (expand-file-name path (ss/home-path "org/")))
-
(provide 'init-paths)
;; Keep custom-set-variables out of the main config.
- (setq custom-file (ss/config-path "custom.el"))
+ (setq custom-file (expand-file-name "custom.el" user-emacs-directory))
#+end_src
* Package setup
@@ -82,20 +70,19 @@ This section bootstraps packages and defines the archives the rest of the
configuration relies on.
#+begin_src emacs-lisp
- (eval-and-compile
- (require 'package)
-
- (setq package-archives
- (append '(("melpa" . "https://melpa.org/packages/"))
- package-archives)
- package-archive-priorities '(("gnu" . 10)
- ("nongnu" . 8)
- ("melpa" . 5))
- package-install-upgrade-built-in t
- use-package-always-ensure nil)
-
- (package-initialize)
- (require 'use-package))
+ (require 'package)
+
+ (setq package-archives
+ (append '(("melpa" . "https://melpa.org/packages/"))
+ package-archives)
+ package-archive-priorities '(("gnu" . 10)
+ ("nongnu" . 8)
+ ("melpa" . 5))
+ package-install-upgrade-built-in t
+ use-package-always-ensure nil)
+
+ (package-initialize)
+ (require 'use-package)
#+end_src
* Interface defaults
@@ -103,75 +90,34 @@ configuration relies on.
This section sets the visual defaults: theme, fonts, and frame behavior.
#+begin_src emacs-lisp
- (defconst ss/font-family "JetBrains Mono"
- "Preferred font family for GUI Emacs.")
-
- (defconst ss/font-height 140
- "Preferred default font height for GUI Emacs.")
-
- (defconst ss/font-weight 'medium
- "Preferred default font weight for GUI Emacs.")
-
- (defconst ss/frame-width 140
- "Preferred width for graphical Emacs frames, in columns.")
-
- (defconst ss/frame-height 42
- "Preferred height for graphical Emacs frames, in lines.")
-
- (defun ss/apply-frame-size (&optional frame)
- "Apply the preferred size to FRAME when it is graphical.
- If FRAME is nil, use the selected frame."
- (let ((target-frame (or frame (selected-frame))))
- (when (display-graphic-p target-frame)
- (set-frame-size target-frame ss/frame-width ss/frame-height))))
-
- (defun ss/apply-font-faces ()
- "Apply the original JetBrains-based face setup."
- (set-face-attribute
- 'default nil
- :family ss/font-family :height ss/font-height :weight ss/font-weight)
- (set-face-attribute
- 'fixed-pitch nil
- :family ss/font-family :weight ss/font-weight)
- (set-face-attribute
- 'fixed-pitch-serif nil
- :family ss/font-family :weight ss/font-weight))
-
- (defun ss/apply-gui-defaults (&optional frame)
- "Apply GUI defaults to FRAME.
-If FRAME is nil, use the selected frame."
- (let ((target-frame (or frame (selected-frame))))
- (when (display-graphic-p target-frame)
- (with-selected-frame target-frame
- (ss/apply-frame-size target-frame)
- (ss/disable-menu-bar)
- (tool-bar-mode -1)
- (scroll-bar-mode -1)
- (tooltip-mode -1)
- (when (find-font (font-spec :name ss/font-family))
- (ss/apply-font-faces))))))
-
- (defun ss/disable-menu-bar ()
- "Disable the menu bar for the current frame/session."
- (menu-bar-mode -1))
-
- (add-hook 'after-make-frame-functions #'ss/apply-gui-defaults)
-
(when (display-graphic-p)
- (ss/apply-gui-defaults))
+ (set-frame-size (selected-frame) 140 42)
+ (menu-bar-mode -1)
+ (tool-bar-mode -1)
+ (scroll-bar-mode -1)
+ (tooltip-mode -1)
+ (set-face-attribute
+ 'default nil
+ :family "JetBrains Mono" :height 140 :weight 'medium)
+ (set-face-attribute
+ 'fixed-pitch nil
+ :family "JetBrains Mono" :weight 'medium)
+ (set-face-attribute
+ 'fixed-pitch-serif nil
+ :family "JetBrains Mono" :weight 'medium))
(unless (display-graphic-p)
- (add-hook 'emacs-startup-hook #'ss/disable-menu-bar))
+ (add-hook 'emacs-startup-hook (lambda () (menu-bar-mode -1))))
(setq inhibit-startup-message t
- inhibit-startup-screen t
- ring-bell-function 'ignore)
+ inhibit-startup-screen t
+ ring-bell-function 'ignore)
- (use-package modus-themes
- :ensure nil
- :no-require t
- :config
- (load-theme 'modus-vivendi t))
+ (use-package modus-themes
+ :ensure nil
+ :no-require t
+ :config
+ (load-theme 'modus-vivendi t))
(line-number-mode 1)
(column-number-mode 1)
@@ -196,39 +142,35 @@ If FRAME is nil, use the selected frame."
display-time-default-load-average nil)
(display-time-mode 1))
- (defun ss/mode-line-right-align ()
- "Return a spacer that right-aligns `mode-line-misc-info'."
- (propertize
- " "
- 'display
- `((space :align-to
- (- right
- ,(+ 2 (string-width (format-mode-line mode-line-misc-info))))))))
-
;; Keep the theme's faces, but make the right edge alignment dynamic.
(setq-default mode-line-format
(list
- ;; Left padding
- " "
- "%e"
- mode-line-front-space
- mode-line-mule-info
- mode-line-client
- mode-line-modified
- mode-line-remote
- mode-line-frame-identification
- mode-line-buffer-identification
- " "
- mode-line-position
- '(vc-mode vc-mode)
- " "
- mode-line-modes
- ;; Right-align from here
- '(:eval (ss/mode-line-right-align))
- mode-line-misc-info
- ;; Right padding
- " "
- mode-line-end-spaces))
+ ;; Left padding
+ " "
+ "%e"
+ mode-line-front-space
+ mode-line-mule-info
+ mode-line-client
+ mode-line-modified
+ mode-line-remote
+ mode-line-frame-identification
+ mode-line-buffer-identification
+ " "
+ mode-line-position
+ '(vc-mode vc-mode)
+ " "
+ mode-line-modes
+ ;; Right-align from here
+ '(:eval (propertize
+ " "
+ 'display
+ `((space :align-to
+ (- right
+ ,(+ 2 (string-width (format-mode-line mode-line-misc-info))))))))
+ mode-line-misc-info
+ ;; Right padding
+ " "
+ mode-line-end-spaces))
#+end_src
@@ -243,28 +185,28 @@ choices.
(prefer-coding-system 'utf-8)
(setq auto-save-default nil
- backup-inhibited t
- echo-keystrokes 0.1
- compilation-ask-about-save nil
- mouse-wheel-scroll-amount '(1 ((shift) . 1))
- mouse-wheel-progressive-speed nil
- mouse-wheel-follow-mouse t
- scroll-step 1
- scroll-conservatively 101
- enable-recursive-minibuffers t
- gc-cons-threshold (* 128 1024 1024)
- read-process-output-max (* 4 1024 1024)
- process-adaptive-read-buffering nil)
+ backup-inhibited t
+ echo-keystrokes 0.1
+ compilation-ask-about-save nil
+ mouse-wheel-scroll-amount '(1 ((shift) . 1))
+ mouse-wheel-progressive-speed nil
+ mouse-wheel-follow-mouse t
+ scroll-step 1
+ scroll-conservatively 101
+ enable-recursive-minibuffers t
+ gc-cons-threshold (* 128 1024 1024)
+ read-process-output-max (* 4 1024 1024)
+ process-adaptive-read-buffering nil)
(fset 'yes-or-no-p 'y-or-n-p)
(global-auto-revert-mode 1)
(delete-selection-mode 1)
(setq-default indent-tabs-mode nil
- fill-column 80
- tab-width 2
- indicate-empty-lines t
- sentence-end-double-space nil)
+ fill-column 80
+ tab-width 2
+ indicate-empty-lines t
+ sentence-end-double-space nil)
#+end_src
@@ -326,7 +268,8 @@ PARA notes, so project, area, and resource files can surface TODOs without
pulling in daily or archived notes. A small directory helper keeps PARA
subdirectories easy to create from the minibuffer before capturing into them.
A curated =moc.org= in the Org root acts as the startup landing page and quick
-navigation surface without becoming a global fallback buffer.
+navigation surface. The config assumes that file already exists and opens it
+directly during startup rather than creating it on demand.
#+begin_src emacs-lisp
(use-package org
@@ -355,6 +298,9 @@ navigation surface without becoming a global fallback buffer.
(defconst ss/org-archives-directory (expand-file-name "archives/" ss/org-directory)
"Directory for archived notes.")
+ (defconst ss/moc-file (expand-file-name "moc.org" ss/org-directory)
+ "Central MOC note.")
+
(defconst ss/org-note-directories
(list ss/org-directory
ss/org-daily-directory
@@ -367,7 +313,7 @@ navigation surface without becoming a global fallback buffer.
(defconst ss/org-agenda-directories
(list ss/org-projects-directory
- ss/org-areas-directory)
+ ss/org-areas-directory)
"Directories whose Org files feed the agenda.")
(defconst ss/org-subdirectory-roots
@@ -379,7 +325,7 @@ navigation surface without becoming a global fallback buffer.
(defun ss/denote-capture-in-directory (directory &optional keywords &rest prompts)
"Start a Denote Org capture in DIRECTORY with KEYWORDS and PROMPTS.
-If PROMPTS is empty, rely on `denote-prompts'."
+ If PROMPTS is empty, rely on `denote-prompts'."
(let* ((prompt-for-keywords (memq :keywords prompts))
(denote-directory directory)
(denote-use-directory (unless (memq :subdirectory prompts) directory))
@@ -396,17 +342,6 @@ If PROMPTS is empty, rely on `denote-prompts'."
(memq :template prompts))
(denote-org-capture))))
- (defun ss/note-subdirectory-candidates (root)
- "Return existing subdirectories under ROOT as relative paths."
- (sort
- (delete-dups
- (mapcar (lambda (path)
- (directory-file-name (file-relative-name path root)))
- (seq-filter
- #'file-directory-p
- (directory-files-recursively root directory-files-no-dot-files-regexp t t))))
- #'string<))
-
(defun ss/create-note-subdirectory ()
"Create a PARA subdirectory using minibuffer completion."
(interactive)
@@ -416,105 +351,52 @@ If PROMPTS is empty, rely on `denote-prompts'."
nil t))
(root (alist-get root-name ss/org-subdirectory-roots nil nil #'string=))
(completion-extra-properties '(:category file))
+ (candidates
+ (sort
+ (delete-dups
+ (mapcar (lambda (path)
+ (directory-file-name (file-relative-name path root)))
+ (seq-filter
+ #'file-directory-p
+ (directory-files-recursively root directory-files-no-dot-files-regexp t t))))
+ #'string<))
(subdirectory (completing-read
(format "Subdirectory in %s: " root-name)
- (ss/note-subdirectory-candidates root)
+ candidates
nil nil))
(target (expand-file-name subdirectory root))
(existing (file-directory-p target)))
(make-directory target t)
- (ss/refresh-org-agenda-files)
+ (ss/refresh-org-agenda-files)
(message "%s note directory: %s"
(if existing "Using existing" "Created")
target)))
- (defun ss/ensure-org-note-directories ()
- "Create the Org directories used by the notes workflow."
- (mapc (lambda (directory)
- (make-directory directory t))
- ss/org-note-directories))
-
- (defun ss/ensure-org-agenda-loaded ()
- "Load Org agenda support before using agenda-specific helpers.
-This ensures `org-agenda-file-regexp' and `org-agenda' are available."
- (require 'org-agenda))
-
- (defun ss/org-agenda-files ()
- "Return the Org files that should be scanned by the agenda."
- (ss/ensure-org-agenda-loaded)
- (delete-dups
- (apply #'append
- (mapcar (lambda (directory)
- (if (file-directory-p directory)
- (directory-files-recursively directory org-agenda-file-regexp)
- nil))
- ss/org-agenda-directories))))
-
(defun ss/refresh-org-agenda-files (&rest _)
"Refresh `org-agenda-files' from the current PARA directories.
-Ignore any arguments passed by advice wrappers."
- (setq org-agenda-files (ss/org-agenda-files)))
-
- (defun ss/daily-note-path (&optional time)
- "Return the file name for the daily note at TIME.
-If TIME is nil, use the current date."
- (expand-file-name
- (format-time-string "%Y-%m-%d.org" time)
- ss/org-daily-directory))
-
- (defun ss/moc-path ()
- "Return the file name for the central MOC note."
- (expand-file-name "moc.org" ss/org-directory))
-
- (defun ss/moc-template ()
- "Return the initial contents for the central MOC note."
- (concat
- "#+title: MOC\n\n"
- "* Quick Access\n"
- "- [[elisp:(ss/open-agenda)][Open agenda]]\n"
- "- [[elisp:(ss/open-todays-note)][Today's note]]\n"
- "- [[elisp:(org-capture nil)][Capture]]\n"
- "- [[elisp:(denote-open-or-create)][New note]]\n\n"
- "* Projects (active)\n"
- "- Backend Chapter Uplift\n"
- "- API Strategy\n"
- "- Maturity Matrix\n"
- "- DPT Ways of Working\n\n"
- "* Areas\n"
- "- My Role\n"
- "- People and Performance\n"
- "- SE Practice\n"
- "- Stakeholder Alignment\n"
- "- Engineering Department\n\n"
- "* Resources (high leverage)\n"
- "- API Strategy Reference\n"
- "- Triage System\n"
- "- Weekly Focus\n"))
-
- (defun ss/ensure-moc ()
- "Create the central MOC note when it does not exist.
-Return the path to the note."
- (let ((file (ss/moc-path)))
- (unless (file-exists-p file)
- (make-directory (file-name-directory file) t)
- (with-temp-file file
- (insert (ss/moc-template))))
- file))
-
- (defun ss/daily-note-template (&optional time)
- "Return the initial contents for the daily note at TIME."
- (format "#+title: %s\n\n* Tasks\n\n* Notes\n\n* Open Loops\n"
- (format-time-string "%Y-%m-%d" (or time (current-time)))))
+ Ignore any arguments passed by advice wrappers."
+ (require 'org-agenda)
+ (setq org-agenda-files
+ (delete-dups
+ (apply #'append
+ (mapcar (lambda (directory)
+ (if (file-directory-p directory)
+ (directory-files-recursively directory org-agenda-file-regexp)
+ nil))
+ ss/org-agenda-directories)))))
(defun ss/ensure-daily-note (&optional time)
"Create the daily note for TIME when it does not exist.
-Return the path to the note."
+ Return the path to the note."
(let* ((date (or time (current-time)))
- (file (ss/daily-note-path date)))
+ (file (expand-file-name
+ (format-time-string "%Y-%m-%d.org" date)
+ ss/org-daily-directory)))
(unless (file-exists-p file)
(make-directory (file-name-directory file) t)
(with-temp-file file
- (insert (ss/daily-note-template date))))
+ (insert (format "#+title: %s\n\n* Tasks\n\n* Notes\n\n* Open Loops\n"
+ (format-time-string "%Y-%m-%d" date)))))
file))
(defun ss/open-todays-note ()
@@ -525,22 +407,14 @@ Return the path to the note."
(defun ss/open-moc ()
"Open the central MOC note."
(interactive)
- (find-file (ss/ensure-moc)))
-
- (defun ss/open-moc-on-startup ()
- "Open the central MOC note during normal startup."
- (when (and (equal (buffer-name (current-buffer)) "*scratch*")
- (not buffer-file-name))
- (ss/open-moc)))
+ (find-file ss/moc-file))
(defun ss/open-agenda ()
"Refresh agenda files and invoke `org-agenda'."
(interactive)
- (ss/ensure-org-agenda-loaded)
(call-interactively #'org-agenda))
:init
- (add-hook 'emacs-startup-hook #'ss/open-moc-on-startup)
- (ss/ensure-moc)
+ (add-hook 'emacs-startup-hook (lambda () (find-file ss/moc-file)))
:bind (("C-c a" . ss/open-agenda)
("C-c c" . org-capture)
("C-c n M" . ss/open-moc)
@@ -548,7 +422,7 @@ Return the path to the note."
("C-c n d" . ss/open-todays-note))
:config
(setq org-directory ss/org-directory
- org-hide-emphasis-markers t)
+ org-hide-emphasis-markers t)
(add-hook 'org-mode-hook
(lambda ()
(setq-local org-hide-emphasis-markers t)
@@ -556,7 +430,9 @@ Return the path to the note."
(font-lock-ensure)))
(ss/refresh-org-agenda-files)
(advice-add 'org-agenda :before #'ss/refresh-org-agenda-files)
- (ss/ensure-org-note-directories))
+ (mapc (lambda (directory)
+ (make-directory directory t))
+ ss/org-note-directories))
#+end_src
** Capture entry points
@@ -684,14 +560,14 @@ plumbing in this file.
#+begin_src emacs-lisp
(use-package gptel
:ensure t
- :init
+ :init
(setq gptel-default-mode 'org-mode
- gptel-model 'gpt-4o
- gptel-backend (gptel-make-gh-copilot "Copilot"))
+ gptel-model 'gpt-4o
+ gptel-backend (gptel-make-gh-copilot "Copilot"))
:bind (("C-c n g" . gptel)
- ("C-c n s" . gptel-send)
- ("C-c n r" . gptel-rewrite)
- ("C-c n a" . gptel-add)))
+ ("C-c n s" . gptel-send)
+ ("C-c n r" . gptel-rewrite)
+ ("C-c n a" . gptel-add)))
#+end_src
* Generated file footers
@@ -700,13 +576,13 @@ The closing blocks just finish the generated startup files cleanly.
#+begin_src emacs-lisp
-(when (file-exists-p custom-file)
- (load custom-file nil 'nomessage))
+ (when (file-exists-p custom-file)
+ (load custom-file nil 'nomessage))
-;;; init.el ends here
+ ;;; init.el ends here
#+end_src
#+begin_src emacs-lisp :tangle early-init.el
-;;; early-init.el ends here
+ ;;; early-init.el ends here
#+end_src