summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/custom-functions.el3
-rw-r--r--modules/dirvish-config.el36
-rw-r--r--modules/eshell-vterm-config.el20
-rw-r--r--modules/flyspell-config.el7
-rw-r--r--modules/org-agenda-config.el425
-rw-r--r--modules/org-capture-config.el42
-rw-r--r--modules/org-config.el144
-rw-r--r--modules/org-roam-config.el174
-rw-r--r--modules/prog-general.el22
-rw-r--r--modules/prog-lisp.el10
-rw-r--r--modules/show-kill-ring.el11
-rw-r--r--modules/system-utils.el5
-rw-r--r--modules/test-code.el5
-rw-r--r--modules/ui-theme.el18
-rw-r--r--modules/vc-config.el9
15 files changed, 518 insertions, 413 deletions
diff --git a/modules/custom-functions.el b/modules/custom-functions.el
index 9f1875a5..a36dfe80 100644
--- a/modules/custom-functions.el
+++ b/modules/custom-functions.el
@@ -438,7 +438,7 @@ Uses `sortable-time-format' for the formatting the date/time."
(interactive)
(insert (format-time-string sortable-time-format (current-time))))
-(defvar sortable-date-format "%Y-%m-%d "
+(defvar sortable-date-format "%Y-%m-%d %a"
"Time format to insert with `insert-current-time' func.
See help of `format-time-string' for possible replacements")
@@ -556,6 +556,7 @@ Uses `sortable-time-format' for the formatting the date/time."
(define-key map "-" #'cj/hyphenate-region)
(define-key map "U" 'upcase-region)
(define-key map "w" 'cj/remove-leading-trailing-whitespace)
+ (define-key map "W" 'fixup-whitespace)
(define-key map "#" 'cj/count-words-buffer-or-region)
(define-key map "1" 'cj/alphabetize-and-replace-region)
(define-key map "C" 'display-fill-column-indicator-mode)
diff --git a/modules/dirvish-config.el b/modules/dirvish-config.el
index f35d2934..12f67519 100644
--- a/modules/dirvish-config.el
+++ b/modules/dirvish-config.el
@@ -31,6 +31,35 @@
;; (add-hook 'dired-mode-hook 'auto-revert-mode) ;; auto revert dired when files change
+;; -------------------------- Dired Copy Path As Kill --------------------------
+;; copies the full path of the file at point to the clipboard
+
+(defun cj/dired-copy-path-as-kill ()
+ "Copy the full path of file at point in dired to the clipboard."
+ (interactive)
+ (let ((filename (dired-get-file-for-visit)))
+ (if (and filename (file-exists-p filename))
+ (progn
+ (kill-new filename)
+ (message "Copied '%s' to clipboard." filename))
+ (message "No file at point."))))
+
+;; ------------------------ Dired Convert Image To Jpeg ------------------------
+;; converts the image at point to a jpeg
+
+(defun cj/dired-convert-image-to-jpeg ()
+ (interactive)
+ (let* ((original-file (dired-get-file-for-visit))
+ (file-extension (file-name-extension original-file))
+ (jpeg-file (concat (file-name-sans-extension original-file) ".jpeg")))
+ (if (member file-extension '("png" "bmp" "gif" "tif" "tiff" "svg" "webp"))
+ (if (string= file-extension "jpeg")
+ (message "File is already in JPEG format.")
+ (start-process "convert-to-jpeg" nil "convert" original-file jpeg-file)
+ (message "Conversion started for %s" original-file))
+ (message (concat "File is not a supported image file type."
+ "Current supported types: "
+ "'png' 'bmp' 'gif' 'tif' 'tiff' 'svg' 'webp'")))))
;; ------------------------ Dired Mark All Visible Files -----------------------
;; convenience function to mark all visible files in dired
@@ -55,7 +84,8 @@
'(("h" "~/" "home")
("rsb" "/sshx:cjennings@wolf.usbx.me:/home/cjennings/" "remote seedbox")
("rcj" "/sshx:cjennings@cjennings.net:~" "remote cjennings.net")
- ("co" "~/code" "code")
+ ("co" "~/code" "code")
+ ("cj" "~/code/cjennings-net" "cjennings.net hugo")
("df" "~/.dotfiles/" "dotfiles")
("dn" "~/downloads/" "downloads")
("dr" "~/sync/org/drill/" "org drill files")
@@ -95,10 +125,12 @@
(shell-command (concat "nitrogen --save --set-zoom-fill "
(dired-file-name-at-point) " >>/dev/null 2>&1" ))))
("Z" . (lambda () (interactive) (cj/open-file-with-command "zathura")))
- ("p" . (lambda () (interactive) (cj/open-file-with-command "gimp")))
+ ("P" . (lambda () (interactive) (cj/open-file-with-command "gimp")))
("<left>" . dired-up-directory)
("<right>" . dired-find-file)
("f" . dirvish-file-info-menu)
+ ("p" . cj/dired-copy-path-as-kill)
+ ("C" . cj/dired-convert-image-to-jpeg)
("y" . dirvish-yank-menu)
("N" . dirvish-narrow)
("M" . cj/dired-mark-all-visible-files)
diff --git a/modules/eshell-vterm-config.el b/modules/eshell-vterm-config.el
index 7d37d9e5..c6e5cc1e 100644
--- a/modules/eshell-vterm-config.el
+++ b/modules/eshell-vterm-config.el
@@ -65,20 +65,26 @@
(add-to-list 'eshell-visual-options '("git" "--help" "--paginate"))
;; aliases
- (eshell/alias "clear" "clear 1") ;; leaves the prompt at the top of the window
- (eshell/alias "e" "find-file $*")
+ (eshell/alias "clear" "clear 1") ;; leaves prompt at the top of the window
+ (eshell/alias "e" "find-file $1")
(eshell/alias "gocj" "cd /sshx:cjennings@cjennings.net:/var/cjennings/")
(eshell/alias "gosb" "cd /sshx:cjennings@wolf.usbx.me:/home/cjennings/")
(eshell/alias "gowolf" "cd /sshx:cjennings@wolf.usbx.me:/home/cjennings/")
(eshell/alias "v" "eshell-exec-visual $*")
- (eshell/alias "ff" "find-file-other-window $*")
- (eshell/alias "f" "cj/eshell-find-using-dired $1")
+ (eshell/alias "ff" "find-file-other-window $1")
+ (eshell/alias "f" "find-using-dired $1")
(eshell/alias "r" "ranger")
- (eshell/alias "em" "find-file $*")
- (eshell/alias "emacs" "find-file $*")
+ (eshell/alias "em" "find-file $1")
+ (eshell/alias "emacs" "find-file $1")
(eshell/alias "ll" "ls -l"))))
-(defun cj/eshell-find-using-dired (file-pattern)
+(defun eshell/find-file-other-window (file)
+ (find-file-other-window (mapconcat 'identity file " ")))
+
+(defun eshell/find-file (file)
+ (find-file-other-window (mapconcat 'identity file " ")))
+
+(defun eshell/find-using-dired (file-pattern)
"Find a file FILE-PATTERN' using 'find-name-dired'."
(let ((escaped-pattern (regexp-quote file-pattern)))
(find-name-dired . escaped-pattern)))
diff --git a/modules/flyspell-config.el b/modules/flyspell-config.el
index 6109eebc..ad0945c4 100644
--- a/modules/flyspell-config.el
+++ b/modules/flyspell-config.el
@@ -180,12 +180,5 @@ handled appropriately."
(global-set-key (kbd "C-c f") 'flyspell-toggle )
-;; -------------------------------- Ispell STFU --------------------------------
-;; tell ispell where to send it's spurious error messages
-
-(advice-add 'ispell-lookup-words :around
- (lambda (orig &rest args)
- (shut-up (apply orig args))))
-
(provide 'flyspell-config)
;;; flyspell-config.el ends here.
diff --git a/modules/org-agenda-config.el b/modules/org-agenda-config.el
index 016fffcc..f15e5503 100644
--- a/modules/org-agenda-config.el
+++ b/modules/org-agenda-config.el
@@ -5,277 +5,216 @@
;; Agenda views are tied to the F8 (fate) key.
-;; f8 - DAILY SCHEDULE containing a events with a scheduled date or deadline of
-;; the current day. This is followed by...
-;; - TASK LIST containing tasks from all agenda sources.
+;; f8 - MAIN AGENDA which organizes all tasks and events into:
+;; - all unfinished priority A tasks
+;; - the weekly schedule, including the habit consistency graph
+;; - all priority B and C tasks
-;; C-f8 - TASK LIST containing all tasks from all agenda sources
+;; C-f8 - TASK LIST containing all tasks from all agenda targets.
-;; M-f8 - TASK LIST containing all tasks from the current org-mode buffer.
+;; M-f8 - TASK LIST containing all tasks from just the current org-mode buffer.
;; NOTE:
;; Files that contain information relevant to the agenda will be found in the
;; following places: the schedule-file, org-roam notes tagged as 'Projects' and
;; project todo.org files found in project-dir and code-dir.
-;; How the agenda is created:
-;; The inbox and schedule files are always included first. However, in order to
-;; stay current, the files containing agenda information are queried before
-;; calling the functions in the section org-agenda functions to display the
-;; data. This way, any newly created events from project todo.org files, or
-;; org-roam Project files will be included.
-
;;; Code:
-(with-eval-after-load 'org-roam
-
- ;; ----------------------------- Org TODO Settings ---------------------------
-
- (setq org-todo-keywords '((sequence "TODO(t)" "PROJECT(p)" "DOING(i)"
- "WAITING(w)" "VERIFY(v)" "STALLED(s)"
- "DELEGATED(x)" "|"
- "FAILED(f)" "DONE(d)" "CANCELLED(c)")))
-
- (setq org-todo-keyword-faces
- '(("TODO" . "green")
- ("PROJECT" . "blue")
- ("DOING" . "yellow")
- ("WAITING" . "white")
- ("VERIFY" . "orange")
- ("STALLED" . "light blue")
- ("DELEGATED" . "green")
- ("FAILED" . "red")
- ("DONE" . "dark grey")
- ("CANCELLED" . "dark grey")))
-
- (setq org-highest-priority ?A)
- (setq org-lowest-priority ?D)
- (setq org-default-priority ?D)
- (setq org-priority-faces '((?A . (:foreground "Cyan" :weight bold))
- (?B . (:foreground "Yellow"))
- (?C . (:foreground "Green"))
- (?D . (:foreground "Grey"))))
-
- (setq org-enforce-todo-dependencies t)
- (setq org-enforce-todo-checkbox-dependencies t)
- (setq org-deadline-warning-days 7) ;; warn me w/in a week of deadlines
- (setq org-log-done nil) ;; don't log when tasks was done
-
- ;; inherit parents properties (no schedules or deadlines)
- (setq org-use-property-inheritance t)
-
- ;; ------------------ Org TODO Next/Previous Set Keybindings -----------------
-
- (add-hook 'org-agenda-mode-hook (lambda ()
- (local-set-key (kbd "s-<right>") #'org-agenda-todo-nextset)
- (local-set-key (kbd "s-<left>") #'org-agenda-todo-previousset)))
-
- ;; ------------------------------ Org Super Agenda -----------------------------
-
- (use-package org-super-agenda
- :config (org-super-agenda-mode))
-
-;;;; ORG AGENDA VIEW DEFINITIONS
- (defun cj/agenda-today-view()
- "This agenda from all tasks that are scheduled or have a deadline."
- (setq org-super-agenda-groups
- '((:log t) ; Automatically named "Log"
- (:name "SCHEDULED AND DUE"
- :time-grid t
- :deadline past
- :deadline today
- :scheduled past
- :scheduled today)
- (:habit t)
- (:name "DUE SOON"
- :deadline future)
- (:name "LESS IMPORTANT"
- :scheduled future
- :order 100)
- (:discard (:anything t)))))
-
- (defun cj/agenda-all-view()
- "This agenda is built from all tasks."
- (setq org-super-agenda-groups
- '(
- (:name "Ready To Go"
- :todo "STAGED"
- :todo "READY"
- :order 5)
- (:name "Due Today"
- :deadline past
- :deadline today
- :order 2)
- (:name "Empty Projects"
- :todo "PROJECT"
- :order 85)
- (:name "Delegated"
- :todo "DELEGATED"
- :order 50)
- (:name "Scheduled Later"
- :scheduled future
- :order 75)
- (:name "Scheduled Today"
- :scheduled today
- :scheduled past
- :order 4)
- (:name "In Progress"
- :todo "DOING"
- :order 7)
- (:name "High Priority"
- :priority "A"
- :order 10)
- (:name "Waiting"
- :todo "WAITING"
- :order 60)
- (:name "Upcoming"
- :deadline future
- :order 30)
- (:name "Next Priority"
- :priority "B"
- :order 70)
- (:name "Everything Else"
- :anything t
- :order 90))))
-
- ;; ------------------------------ Add Agenda Time ------------------------------
-
- (defun cj/add-agenda-time (s)
- "Add an event with time S to appear underneath the line-at-point.
-This allows a line to show in an agenda without being scheduled or a deadline."
- (interactive "sTime: ")
- (defvar cj/timeformat "%Y-%m-%d %a")
- (org-end-of-line)
- (save-excursion
- (open-line 1)
- (forward-line 1)
- (insert (concat "<" (format-time-string cj/timeformat (current-time)) " " s ">" ))))
-
- (global-set-key (kbd "M-t") #'cj/add-agenda-time)
-
- ;; ---------------------------- Org Agenda Settings ----------------------------
-
+(use-package org-agenda
+ :ensure nil ;; built-in
+ :after (org org-roam)
+ :config
(setq org-agenda-prefix-format '((agenda . " %i %-25:c%?-12t% s")
(timeline . " % s")
- (todo . " %i %-25:c")
- (tags . " %i %-12:c")
- (search . " %i %-12:c")))
+ (todo . " %i %-25:c")
+ (tags . " %i %-12:c")
+ (search . " %i %-12:c")))
(setq org-agenda-dim-blocked-tasks 'invisible)
(setq org-agenda-skip-scheduled-if-done nil)
- (setq org-agenda-skip-include-deadlines t)
(setq org-agenda-remove-tags t)
(setq org-agenda-compact-blocks t)
- ;; ------------------------ Add Files To Org Agenda List -----------------------
- ;; finds files named 'todo.org' (case insensitive) and adds them to
- ;; org-agenda-files list.
+ ;; display the agenda from the bottom
+ (add-to-list 'display-buffer-alist
+ '("\\*Org Agenda\\*"
+ (display-buffer-reuse-mode-window display-buffer-below-selected)
+ (dedicated . t)
+ (window-height . fit-window-to-buffer)))
- (defun cj/add-files-to-org-agenda-files (directory)
- "Recursively searches for files named 'todo.org',
- Searches in DIRECTORY and adds them to org-project-files."
- (interactive "D")
- (setq org-agenda-files
- (append (directory-files-recursively directory
- "^[Tt][Oo][Dd][Oo]\\.[Oo][Rr][Gg]$" t)
- org-agenda-files)))
+ ;; reset s-left/right each time org-agenda is enabled
+ (add-hook 'org-agenda-mode-hook (lambda ()
+ (local-set-key (kbd "s-<right>") #'org-agenda-todo-nextset)
+ (local-set-key (kbd "s-<left>")
+ #'org-agenda-todo-previousset)))
+ ;; build org-agenda-list for the first time after emacs init completes.
+ (add-hook 'emacs-startup-hook #'cj/build-org-agenda-list))
- ;; NOTE: the following functions require org-roam functionality
- (with-eval-after-load 'org-roam-config
- ;; ---------------------------- Rebuild Org Agenda ---------------------------
+;; ------------------------ Add Files To Org Agenda List -----------------------
+;; finds files named 'todo.org' (case insensitive) and adds them to
+;; org-agenda-files list.
- (defun cj/build-org-agenda-list ()
- "Rebuilds the org agenda list.
-Begins with the inbox-file and schedule-file, then searches for org-roam
-Projects and adds all todo.org files from code and project directories."
- (interactive)
- ;; reset org-agenda-files to inbox-file
- (setq org-agenda-files (list inbox-file schedule-file))
- (let ((new-files
- (append
- (cj/org-roam-list-notes-by-tag "Project"))))
- (dolist (file new-files)
- (unless (member file org-agenda-files)
- (setq org-agenda-files (cons file org-agenda-files)))))
+(defun cj/add-files-to-org-agenda-files-list (directory)
+ "Search for files named \\='todo.org\\=' add them to org-project-files.
+DIRECTORY is a string of the path to begin the search."
+ (interactive "D")
+ (setq org-agenda-files
+ (append (directory-files-recursively directory
+ "^[Tt][Oo][Dd][Oo]\\.[Oo][Rr][Gg]$" t)
+ org-agenda-files)))
- (cj/add-files-to-org-agenda-files projects-dir)
- (cj/add-files-to-org-agenda-files code-dir))
+;; ---------------------------- Rebuild Org Agenda ---------------------------
+;; builds the org agenda list from all agenda targets.
+;; agenda targets is the schedule, project todos, inbox, and org roam projects.
- ;; build org-agenda-list for the first time once emacs init is complete.
- (add-hook 'emacs-startup-hook 'cj/build-org-agenda-list)
-
- ;; ------------------------ Org Agenda Display Functions -----------------------
-
- (defun cj/agenda-all-agenda-files-day ()
- "Display an \'org-agenda\' schedule with tasks covering today.
+(defun cj/build-org-agenda-list ()
+ "Rebuilds the org agenda list.
+Begins with the inbox-file and schedule-file, then searches for org-roam
+Projects and adds all todo.org files from code and project directories."
+ (interactive)
+ ;; reset org-agenda-files to inbox-file
+ (setq org-agenda-files (list inbox-file schedule-file))
+ (let ((new-files
+ (append
+ (cj/org-roam-list-notes-by-tag "Project"))))
+ (dolist (file new-files)
+ (unless (member file org-agenda-files)
+ (setq org-agenda-files (cons file org-agenda-files)))))
+
+ (cj/add-files-to-org-agenda-files-list projects-dir)
+ (cj/add-files-to-org-agenda-files-list code-dir))
+
+;; ------------------------------ Agenda List All ------------------------------
+;; an agenda listing tasks from all available agenda targets.
+
+(defun cj/todo-list-all-agenda-files ()
+ "Displays an \\='org-agenda\\=' todo list.
The contents of the agenda will be built from org-project-files and org-roam
files that have project in their filetag."
- (interactive)
- (cj/build-org-agenda-list)
- (setq org-agenda-span 'day)
- (cj/agenda-today-view)
- (org-agenda "a" "a"))
- (global-set-key (kbd "<f8>") #'cj/agenda-all-agenda-files-day)
+ (interactive)
+ (cj/build-org-agenda-list)
+ (org-agenda "a" "t"))
+(global-set-key (kbd "C-<f8>") #'cj/todo-list-all-agenda-files)
+
+;; ------------------------- Agenda List Current Buffer ------------------------
+;; an agenda listing tasks from just the current buffer.
+
+(defun cj/todo-list-from-this-buffer ()
+ "Displays an \\='org-agenda\\=' todo list built from the current buffer.
+If the current buffer isn't an org buffer, inform the user."
+ (interactive)
+ (if (eq major-mode 'org-mode)
+ (let ((org-agenda-files (list buffer-file-name)))
+ (org-agenda "a" "t"))
+ (message (concat "Your org agenda request based on '" (buffer-name (current-buffer))
+ "' failed because it's not an org buffer."))))
+(global-set-key (kbd "M-<f8>") #'cj/todo-list-from-this-buffer)
+
+;; -------------------------------- Main Agenda --------------------------------
+;; my custom agenda command from all available agenda targets. adapted from:
+;; https://blog.aaronbieber.com/2016/09/24/an-agenda-for-life-with-org-mode.html
+
+(defvar cj/main-agenda-hipri-title "\nHIGH PRIORITY UNRESOLVED TASKS\n"
+ "String to announce the high priority section of the main agenda.")
+
+(defvar cj/main-agenda-schedule-title "\nSCHEDULE\n"
+ "String to announce the schedule section of the main agenda.")
+
+(defvar cj/main-agenda-tasks-title "\nPRIORITY B AND C\n"
+ "String to announce the schedule section of the main agenda.")
+
+(defun cj/org-skip-subtree-if-habit ()
+ "Skip an agenda entry if it has a STYLE property equal to \"habit\"."
+ (let ((subtree-end (save-excursion (org-end-of-subtree t))))
+ (if (string= (org-entry-get nil "STYLE") "habit")
+ subtree-end
+ nil)))
+
+(defun cj/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 cj/org-skip-subtree-if-keyword (keywords)
+ "Skip an agenda subtree if it has a TODO keyword in KEYWORDS.
+KEYWORDS must be a list of strings."
+ (let ((subtree-end (save-excursion (org-end-of-subtree t))))
+ (if (member (org-get-todo-state) keywords)
+ subtree-end
+ nil)))
+
+(setq org-agenda-custom-commands
+ '(("d" "Daily Agenda with Tasks"
+ ((tags "PRIORITY=\"A\""
+ ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
+ (org-agenda-overriding-header cj/main-agenda-hipri-title)))
+ (agenda "" ((org-agenda-ndays 1)
+ (org-agenda-overriding-header cj/main-agenda-schedule-title)))
+ (alltodo ""
+ ((org-agenda-skip-function '(or (cj/org-skip-subtree-if-habit)
+ (cj/org-skip-subtree-if-priority ?A)
+ (cj/org-skip-subtree-if-priority ?D)
+ (cj/org-skip-subtree-if-keyword '("PROJECT"))
+ (org-agenda-skip-if nil '(scheduled deadline))))
+ (org-agenda-overriding-header cj/main-agenda-tasks-title))))
+ ((org-agenda-compact-blocks nil)))))
+
+
+ (defun cj/main-agenda-display ()
+ "Display the main \'org-agenda\' display.
+This uses all org-agenda targes and presents three sections:
+- all unfinished priority A tasks
+- the weekly schedule, including the habit consistency graph
+- all priority B and C tasks"
+ (interactive)
+ (cj/build-org-agenda-list)
+ (org-agenda "a" "d"))
+(global-set-key (kbd "<f8>") #'cj/main-agenda-display)
+;; ------------------------- Add Timestamp To Org Entry ------------------------
+;; simply adds a timestamp to put the org entry on an agenda
- (defun cj/agenda-all-agenda-files-week ()
- "Display an 'org-agenda' schedule with tasks covering this week.
-The contents of the agenda will be built from org-project-files and org-roam
-files that have project in their filetag."
- (interactive)
- (cj/build-org-agenda-list)
- (setq org-agenda-span 'week)
- (cj/agenda-today-view)
- (org-agenda "a" "a"))
- (global-set-key (kbd "s-<f8>") #'cj/agenda-all-agenda-files-week)
-
- (defun cj/todo-list-all-agenda-files ()
- "Displays an 'org-agenda' todo list.
-The contents of the agenda will be built from org-project-files and org-roam
-files that have project in their filetag."
- (interactive)
- (cj/build-org-agenda-list)
- (cj/agenda-all-view)
- (org-agenda "a" "t"))
- (global-set-key (kbd "C-<f8>") #'cj/todo-list-all-agenda-files)
-
- (defun cj/todo-list-from-this-buffer ()
- "Displays an 'org-agenda' todo list built from the current buffer.
- If the current buffer isn't an org buffer, inform the user."
- (interactive)
- (if (eq major-mode 'org-mode)
- (let ((org-agenda-files (list buffer-file-name)))
- (cj/agenda-all-view)
- (org-agenda "a" "t"))
- (message (concat "Your org agenda request based on '" (buffer-name (current-buffer))
- "' failed because it's not an org buffer."))))
- (global-set-key (kbd "M-<f8>") #'cj/todo-list-from-this-buffer)
-
- ;; --------------------------- Notifications / Alerts --------------------------
- ;; send libnotify notifications about agenda items
-
- (use-package alert
- :defer .5
- :config
- (setq alert-fade-time 10) ;; secs to vanish alert
- (setq alert-default-style 'libnotify)) ;; work with dunst
-
- (use-package org-alert
- :defer .5
- :bind
- ("C-c A" . org-alert-check)
- :config
- (setq alert-default-style 'libnotify) ;; work with dunst
- (setq org-alert-interval 300) ;; seconds checks agenda is checked (300 = 5 mins)
- (setq org-alert-notify-cutoff 5) ;; minutes before a deadline to send alert
- (setq org-alert-notify-after-event-cutoff 10) ;; mins post deadline to stop alerts
- (setq org-alert-notification-title "Reminder")
- (org-alert-enable))
-
-
- ) ;; end with-eval-after-load 'org-roam-config
- ) ;; end with-eval-after-load 'org-roam
+(defun cj/add-timestamp-to-org-entry (s)
+ "Add an event with time S to appear underneath the line-at-point.
+This allows a line to show in an agenda without being scheduled or a deadline."
+ (interactive "sTime: ")
+ (defvar cj/timeformat "%Y-%m-%d %a")
+ (org-end-of-line)
+ (save-excursion
+ (open-line 1)
+ (forward-line 1)
+ (insert (concat "<" (format-time-string cj/timeformat (current-time)) " " s ">" ))))
+(global-set-key (kbd "M-t") #'cj/add-timestamp-to-org-entry)
+
+;; --------------------------- Notifications / Alerts --------------------------
+;; send libnotify notifications about agenda items
+
+(use-package alert
+ :defer .5
+ :after org-agenda
+ :config
+ (setq alert-fade-time 10) ;; secs to vanish alert
+ (setq alert-default-style 'libnotify)) ;; work with dunst
+
+(use-package org-alert
+ :defer .5
+ :after alert
+ :bind
+ ("C-c A" . org-alert-check)
+ :config
+ (setq alert-default-style 'libnotify) ;; work with dunst
+ (setq org-alert-interval 180) ;; seconds between agenda checks (180 = 3 mins)
+ (setq org-alert-notify-cutoff 5) ;; minutes before a deadline to send alert
+ (setq org-alert-notify-after-event-cutoff 10) ;; mins post deadline to stop alerts
+ (setq org-alert-notification-title "Reminder")
+ (org-alert-enable))
(provide 'org-agenda-config)
;;; org-agenda-config.el ends here
diff --git a/modules/org-capture-config.el b/modules/org-capture-config.el
index 8feab2bf..4fa7af41 100644
--- a/modules/org-capture-config.el
+++ b/modules/org-capture-config.el
@@ -78,31 +78,57 @@ Intended to be called within an org capture template."
;; ORG-CAPTURE TEMPLATES
(setq org-protocol-default-template-key "L")
(setq org-capture-templates
- '(
+ '(("t" "Task" entry (file+headline inbox-file "Inbox")
+ "* TODO %?" :prepend t)
+
("e" "Event" entry (file+headline schedule-file "Scheduled Events")
"* %?\nWHEN: %^t" :prepend t)
("E" "Epub Text" entry (file+headline inbox-file "Inbox")
- "* %?\n#+BEGIN_QUOTE\n %i\n#+END_QUOTE\nSource: [[%:link][%(buffer-name (org-capture-get :original-buffer))]]\nCaptured On: %U" :prepend t)
+ "* %?
+#+BEGIN_QUOTE\n %i\n#+END_QUOTE
+Source: [[%:link][%(buffer-name (org-capture-get :original-buffer))]]
+Captured On: %U" :prepend t)
("P" "PDF Text" entry (file+headline inbox-file "Inbox")
- "* %?\n#+BEGIN_QUOTE\n %(org-capture-pdf-active-region)\n#+END_QUOTE\nSource:[[%L][%(buffer-name (org-capture-get :original-buffer))]]\nCaptured On: %U" :prepend t)
+ "* %?
+#+BEGIN_QUOTE\n%(org-capture-pdf-active-region)\n#+END_QUOTE
+Source:[[%L][%(buffer-name (org-capture-get :original-buffer))]]
+Captured On: %U" :prepend t)
("p" "Link with Selection" entry (file+headline inbox-file "Inbox")
- "* TODO %?\n#+BEGIN_QUOTE\n%i\n#+END_QUOTE\n[[%:link][%:description]]\nCaptured On: %U" :prepend t)
+ "* %?%:description
+#+BEGIN_QUOTE\n%i\n#+END_QUOTE
+[[%:link][%:description]]
+Captured On: %U\n" :prepend t)
("L" "Link" entry (file+headline inbox-file "Inbox")
- "* TODO %?\n[[%:link][%:description]]\nCaptured On: %U" :prepend t)
+ "* %?%:description
+[[%:link][%:description]]\nCaptured On: %U" :prepend t :immediate-finish t)
("m" "Mu4e Email" entry (file+headline inbox-file "Inbox")
- "* TODO %?%(if (string= \"%i\" \"\") \"\" \"\n#+BEGIN_QUOTE\n%i\n#+END_QUOTE\")\n[[%:link][%:description]]\nCaptured On: %U"
+ "* TODO %?
+%(if (string= \"%i\" \"\") \"\" \"\n#+BEGIN_QUOTE\n%i\n#+END_QUOTE\")
+[[%:link][%:description]]
+Captured On: %U"
:prepend t)
- ("w" "Web Page Clipper" plain
- (function cj/org-webpage-clipper)
+ ("g" "Grocery List Item" item
+ (file+headline inbox-file "Grocery List") "%?")
+
+ ("s" "Shopping List Entry" entry
+ (file+headline inbox-file "Shopping List") "* %?")
+
+ ("w" "Web Page Clipper" plain
+ (function cj/org-webpage-clipper)
"* %a\nArticle Link: %L\nCaptured On: %U\n\n" :immediate-finish t)))
) ;; end with-eval-after-load 'org
+;; ---------------------------- Simple Task Capture ----------------------------
+;; the simplest way to capture a task. Also a simple way to write this function.
+
+(define-key global-map (kbd "C-S-t") (kbd "C-c c t"))
+
(provide 'org-capture-config)
;;; org-capture-config.el ends here.
diff --git a/modules/org-config.el b/modules/org-config.el
index 0094cc9d..f084a8c0 100644
--- a/modules/org-config.el
+++ b/modules/org-config.el
@@ -18,25 +18,88 @@
;;; Code:
-;;;; --------------------------- Constants ---------------------------
+;; --------------------------------- Constants ---------------------------------
;; note: some constants used here are defined in init.el
(defvar org-archive-location (concat sync-dir "/archives/archive.org::datetree/")) ;; location of archive file
(defvar org-project-files (list schedule-file))
-;; ---------------------------- APT Sorting Function ---------------------------
+;; ---------------------------- Org General Settings ---------------------------
-(defun cj/org-reorder-list-apt ()
- "Sort the org header by three criteria: alpha, pri, then todo."
- (interactive)
- (save-excursion
- (ignore-errors
- (progn
- (org-sort-entries t ?a)
- (org-sort-entries t ?p)
- (org-sort-entries t ?t)
- (org-cycle)
- (org-cycle)))))
+(defun cj/org-general-settings ()
+ "All general \='org-mode\=' settings are grouped and set in this function."
+
+ ;; Unbind org-cycle-agenda-files keys for use elsewhere
+ (unbind-key "C-'" org-mode-map)
+ (unbind-key "C-," org-mode-map)
+
+ ;; ORG-MODULES
+ ;; enable recognition of org-protocol:// as a parameter
+ ;; add org-habits
+ (require 'org-protocol)
+ (setq org-modules '(org-protocol ol-eww ol-w3m ol-info org-habit))
+
+ ;; GENERAL
+ (setq org-startup-folded t) ;; all org files should start in the folded state
+ (setq org-cycle-open-archived-trees t) ;; re-enable opening headings with archive tags with TAB
+ (setq org-outline-path-complete-in-steps nil)
+ (setq org-return-follows-link t) ;; hit return to follow an org-link
+ (setq org-list-allow-alphabetical t) ;; allow alpha ordered lists (i.e., a), A), a., etc.)
+
+ ;; INDENTATION
+ (setq org-startup-indented t) ;; load org files indented
+ (setq org-adapt-indentation t) ;; adapt indentation to outline node level
+ (setq org-indent-indentation-per-level 2) ;; indent two character-widths per level
+
+ ;; INLINE IMAGES
+ (setq org-startup-with-inline-images t) ;; preview images by default
+ (setq org-image-actual-width '(500)) ;; keep image sizes in check
+
+ (setq org-bookmark-names-plist nil) ;; don't set org-capture bookmarks
+
+ ;; force pdfs exported from org to open in emacs
+ (add-to-list 'org-file-apps '("\\.pdf\\'" . emacs)))
+
+;; ----------------------------- Org TODO Settings ---------------------------
+
+(defun cj/org-todo-settings ()
+ "All org-todo related settings are grouped and set in this function."
+
+ ;; logging task creation, task start, and task resolved states
+ (setq org-todo-keywords '((sequence "TODO(t!)" "PROJECT(p)" "DOING(i!)"
+ "WAITING(w)" "VERIFY(v)" "STALLED(s)"
+ "DELEGATED(x)" "|"
+ "FAILED(f!)" "DONE(d!)" "CANCELLED(c!)")))
+
+ (setq org-todo-keyword-faces
+ '(("TODO" . "green")
+ ("PROJECT" . "blue")
+ ("DOING" . "yellow")
+ ("WAITING" . "white")
+ ("VERIFY" . "orange")
+ ("STALLED" . "light blue")
+ ("DELEGATED" . "green")
+ ("FAILED" . "red")
+ ("DONE" . "dark grey")
+ ("CANCELLED" . "dark grey")))
+
+ (setq org-highest-priority ?A)
+ (setq org-lowest-priority ?D)
+ (setq org-default-priority ?D)
+ (setq org-priority-faces '((?A . (:foreground "Cyan" :weight bold))
+ (?B . (:foreground "Yellow"))
+ (?C . (:foreground "Green"))
+ (?D . (:foreground "Grey"))))
+
+ (setq org-enforce-todo-dependencies t)
+ (setq org-enforce-todo-checkbox-dependencies t)
+ (setq org-deadline-warning-days 7) ;; warn me w/in a week of deadlines
+ (setq org-treat-insert-todo-heading-as-state-change t) ;; log task creation
+ (setq org-log-into-drawer t) ;; log into the drawer
+ (setq org-habit-graph-column 75) ;; allow space for task name
+
+ ;; inherit parents properties (sadly not schedules or deadlines)
+ (setq org-use-property-inheritance t))
;; ---------------------------------- Org Mode ---------------------------------
@@ -57,7 +120,6 @@
("C-\\" . org-match-sparse-tree)
("C-c t" . org-set-tags-command)
("C-c l" . org-store-link)
- ("C-c r" . cj/org-reorder-list-apt)
("C-c C-l" . org-insert-link)
("s-<up>" . org-priority-up)
("s-<down>" . org-priority-down)
@@ -112,40 +174,38 @@
(org-mode . (lambda () (interactive) (company-mode -1))) ;; no company-mode in org
:config
- ;; Unbind org-cycle-agenda-files keys for use elsewhere
- (unbind-key "C-'" org-mode-map)
- (unbind-key "C-," org-mode-map)
+ (cj/org-general-settings)
+ (cj/org-todo-settings))
- ;; ORG-PROTOCOL
- ;; enable recognition of org-protocol:// as a parameter
- (require 'org-protocol)
- (setq org-modules '(org-protocol ol-eww ol-w3m ol-info))
+;; ------------------------------- Org-Checklist -------------------------------
+;; needed for org-habits to reset checklists once task is complete
+;; this was a part of org-contrib which was deprecated
- ;; GENERAL
- (setq org-startup-folded t) ;; all org files should start in the folded state
- (setq org-cycle-open-archived-trees t) ;; re-enable opening headings with archive tags with TAB
- (setq org-outline-path-complete-in-steps nil)
- (setq org-return-follows-link t) ;; hit return to follow an org-link
- (setq org-list-allow-alphabetical t) ;; allow alpha ordered lists (i.e., a), A), a., etc.)
+(use-package org-checklist
+ :ensure nil ;; in custom folder
+ :after org
+ :load-path "custom/org-checklist.el")
- ;; INDENTATION
- (setq org-startup-indented t) ;; load org files indented
- (setq org-adapt-indentation t) ;; adapt indentation to outline node level
- (setq org-indent-indentation-per-level 2) ;; indent two character-widths per level
+;; -------------------------- Org Link To Current File -------------------------
+;; get a link to the file the current buffer is associated with.
- ;; INLINE IMAGES
- (setq org-startup-with-inline-images t) ;; preview images by default
- (setq org-image-actual-width '(500)) ;; keep image sizes in check
-
- (setq org-bookmark-names-plist nil) ;; don't set org-capture bookmarks
-
- ;; force pdfs exported from org to open in emacs
- (add-to-list 'org-file-apps '("\\.pdf\\'" . emacs)))
+(defun cj/org-link-to-current-buffer-file ()
+ "Create an Org mode link to the current file and copy it to the clipboard.
+The link is formatted as [[file:<file-path>][<file-name>]],
+where <file-path> is the full path to the current file and <file-name>
+is the name of the current file without any directory information.
-;; https://www.reddit.com/r/orgmode/comments/n56fcv/important_the_contrib_directory_now_lives_outside/
-;; (use-package org-contrib
-;; :after org)
+If the current buffer is not associated with a file, the function will throw an
+error."
+ (interactive)
+ (if (buffer-file-name)
+ (let* ((filename (buffer-file-name))
+ (description (file-name-nondirectory filename))
+ (link (format "[[file:%s][%s]]" filename description)))
+ (kill-new link)
+ (message "Copied Org link to current file to clipboard: %s" link))
+ (user-error "Buffer isn't associated with a file, so no link sent to clipboard")))
(provide 'org-config)
;;; org-config.el ends here
diff --git a/modules/org-roam-config.el b/modules/org-roam-config.el
index c9a5bad1..d6c437b2 100644
--- a/modules/org-roam-config.el
+++ b/modules/org-roam-config.el
@@ -6,42 +6,48 @@
;;; Code:
-
;; ---------------------------------- Org Roam ---------------------------------
(use-package org-roam
:after org
:defer .5
:custom
- (org-roam-directory "~/sync/org/roam/")
+ (org-roam-directory roam-dir)
(org-roam-dailies-directory "journal/")
(org-roam-completion-everywhere t)
(org-roam-dailies-capture-templates
'(("d" "default" entry "* %<%I:%M:%S %p %Z> %?"
- :if-new (file+head "%<%Y-%m-%d>.org" "#+FILETAGS: Journal\n#+TITLE: %<%Y-%m-%d>"))))
+ :if-new (file+head "%<%Y-%m-%d>.org" "#+FILETAGS: Journal
+#+TITLE: %<%Y-%m-%d>"))))
(org-roam-capture-templates
- '(("d" "default" plain
- "%?"
+ '(("d" "default" plain "%?"
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}\n")
:unnarrowed t)
- ("v" "v2mom" plain (file "~/sync/org/roam/templates/v2mom.org")
+ ("v" "v2mom" plain
+ (function (lambda () (concat roam-dir "templates/v2mom.org")))
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}\n")
:unnarrowed t)
- ("r" "recipe" plain (file "~/sync/org/roam/templates/recipe.org")
- :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}\n#+CATEGORY: ${title}\n#+FILETAGS: Recipe")
+ ("r" "recipe" plain
+ (function (lambda () (concat roam-dir "templates/recipe.org")))
+ :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}
+ #+CATEGORY: ${title}\n#+FILETAGS: Recipe")
:unnarrowed t)
- ("p" "project" plain (file "~/sync/org/roam/templates/project.org")
- :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}\n#+CATEGORY: ${title}\n#+FILETAGS: Project")
+ ("p" "project" plain
+ (function (lambda () (concat roam-dir "templates/project.org")))
+ :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}
+ #+CATEGORY: ${title}\n#+FILETAGS: Project")
:unnarrowed t)
- ("t" "topic" plain (file "~/sync/org/roam/templates/topic.org")
- :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}\n#+CATEGORY: ${title}\n#+FILETAGS: Topic")
+ ("t" "topic" plain
+ (function (lambda () (concat roam-dir "templates/topic.org")))
+ :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}
+ #+CATEGORY: ${title}\n#+FILETAGS: Topic")
:unnarrowed t)))
:bind (("C-c n ?" . org-roam-hydra/body)
("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find)
- ("C-c n p" . cj/org-roam-find-project)
- ("C-c n r" . cj/org-roam-find-recipe)
- ("C-c n t" . cj/org-roam-find-topic)
+ ("C-c n p" . cj/org-roam-find-node-project)
+ ("C-c n r" . cj/org-roam-find-node-recipe)
+ ("C-c n t" . cj/org-roam-find-node-topic)
("C-c n i" . org-roam-node-insert)
:map org-mode-map
("C-M-i" . completion-at-point)
@@ -59,9 +65,9 @@
;; move closed tasks to today's journal when marked done
(add-to-list 'org-after-todo-state-change-hook
- (lambda ()
- (when (equal org-state "DONE")
- (cj/org-roam-copy-todo-to-today))))
+ (lambda ()
+ (when (equal org-state "DONE")
+ (cj/org-roam-copy-todo-to-today))))
(require 'org-roam-dailies) ;; Ensures the keymap is available
(org-roam-db-autosync-mode))
@@ -70,34 +76,40 @@
(defun cj/org-roam-node-insert-immediate (arg &rest args)
"Create new node and insert its link immediately.
-The prefix ARG .
-ARGS represents the node name to link."
+This is mainly a wrapper around org-roam-node-insert to achieve immediate finish
+to the capture. The prefix ARG and ARGS are the filter function and the rest of
+the arguments that org-roam-node-insert expects."
(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)))
+ (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") 'cj/org-roam-node-insert-immediate)
;; ------------------------- Tag Listing And Filtering -------------------------
(defun cj/org-roam-filter-by-tag (tag-name)
(lambda (node)
- (member tag-name (org-roam-node-tags node))))
+ (member tag-name (org-roam-node-tags node))))
(defun cj/org-roam-list-notes-by-tag (tag-name)
(mapcar #'org-roam-node-file
- (seq-filter
- (cj/org-roam-filter-by-tag tag-name)
- (org-roam-node-list))))
+ (seq-filter
+ (cj/org-roam-filter-by-tag tag-name)
+ (org-roam-node-list))))
;; -------------------------- Org Roam Find Functions --------------------------
(defun cj/org-roam-find-node (tag template-key template-file)
- "List all node of type \='TAG\=' in completing read for selection or creation."
+ "List all nodes of type \='TAG\=' in completing read for selection or creation.
+Interactively find or create an Org-roam node with a given \='TAG\='. Newly
+created nodes are added to the agenda and follow a template defined by
+\='TEMPLATE-KEY\=' and \='TEMPLATE-FILE\='."
+
(interactive)
;; Add the project file to the agenda after capture is finished
- (add-hook 'org-capture-after-finalize-hook #'cj/org-roam-add-node-to-agenda-files-finalize-hook)
+ (add-hook 'org-capture-after-finalize-hook
+ #'cj/org-roam-add-node-to-agenda-files-finalize-hook)
;; Select a project file to open, creating it if necessary
(org-roam-node-find
@@ -107,86 +119,86 @@ ARGS represents the node name to link."
nil
:templates
`((,template-key ,tag plain (file ,template-file)
- :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" ,(concat "#+TITLE: ${title}\n#+CATEGORY: ${title}\n#+FILETAGS: " tag))
- :unnarrowed t))))
+ :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org"
+ ,(concat "#+TITLE: ${title}
+#+CATEGORY: ${title}\n#+FILETAGS: " tag))
+ :unnarrowed t))))
-(defun cj/org-roam-find-topic ()
- "List all node of type \=`topic\=` in completing read for selection or creation."
+(defun cj/org-roam-find-node-topic ()
+ "List nodes of type \=`topic\=` in completing read for selection or creation."
(interactive)
- (cj/org-roam-find-node "Topic" "t" "~/sync/org/roam/templates/topic.org"))
+ (cj/org-roam-find-node "Topic" "t" (concat roam-dir "templates/topic.org")))
-(defun cj/org-roam-find-recipe ()
- "List all node of type \=`recipe\=` in completing read for selection or creation."
+(defun cj/org-roam-find-node-recipe ()
+ "List nodes of type \=`recipe\=` in completing read for selection or creation."
(interactive)
- (cj/org-roam-find-node "Recipe" "r" "~/sync/org/roam/templates/recipe.org"))
+ (cj/org-roam-find-node "Recipe" "r" (concat roam-dir "templates/recipe.org")))
+
+(defun cj/org-roam-find-node-project ()
+ "List nodes of type \='project\=' in completing read for selection or creation."
-(defun cj/org-roam-find-project ()
- "List all node of type \='project\=' in completing read for selection or creation."
(interactive)
- (cj/org-roam-find-node "Project" "p" "~/sync/org/roam/templates/project.org"))
+ (cj/org-roam-find-node "Project" "p" (concat roam-dir "templates/project.org")))
;; ---------------------- Org Capture After Finalize Hook ----------------------
(defun cj/org-roam-add-node-to-agenda-files-finalize-hook ()
"Add the captured project file to \='org-agenda-files\='."
;; Remove the hook since it was added temporarily
- (remove-hook 'org-capture-after-finalize-hook #'cj/org-roam-add-node-to-agenda-files-finalize-hook)
+ (remove-hook 'org-capture-after-finalize-hook
+ #'cj/org-roam-add-node-to-agenda-files-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)))))
-
-;; ------------------------------- Capture Inbox -------------------------------
-
-(defun cj/org-roam-capture-inbox ()
- (interactive)
- (org-roam-capture- :node (org-roam-node-create)
- :templates '(("i" "inbox" plain "** %?"
- :if-new (file+head+olp "~/sync/org/roam/inbox.org"
- "#+TITLE: Inbox\n#+CATEGORY: Inbox\n#+FILETAGS: Project"
- ("Inbox"))))))
-(global-set-key (kbd "C-t") #'cj/org-roam-capture-inbox)
+ (with-current-buffer (org-capture-get :buffer)
+ (add-to-list 'org-agenda-files (buffer-file-name)))))
;; -------------------------------- Capture Task -------------------------------
-(defun cj/org-roam-capture-task ()
+(defun cj/org-roam-capture-task-into-project ()
+ "Create a new project and add a task immediately to it."
(interactive)
;; Add the project file to the agenda after capture is finished
- (add-hook 'org-capture-after-finalize-hook #'cj/org-roam-add-node-to-agenda-files-finalize-hook)
+ (add-hook 'org-capture-after-finalize-hook
+ #'cj/org-roam-add-node-to-agenda-files-finalize-hook)
;; Capture the new task, creating the project file if necessary
- (org-roam-capture- :node (org-roam-node-read
- nil
- (cj/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"
- ("${title}"))))))
-(global-set-key (kbd "C-c n t") #'cj/org-roam-capture-task)
+ (org-roam-capture-
+ :node (org-roam-node-read
+ nil
+ (cj/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}
+#+CATEGORY: ${title}
+#+FILETAGS: Project"
+ ("${title}"))))))
+(global-set-key (kbd "C-c n t") #'cj/org-roam-capture-task-into-project)
;; ------------------------ Org Roam Copy Done To Daily ------------------------
(defun cj/org-roam-copy-todo-to-today ()
+ "Copy completed tasks to today's daily org-roam node."
(interactive)
(let ((org-refile-keep t) ;; Set this to nil to delete the original!
- (org-roam-dailies-capture-templates
- '(("t" "tasks" entry "%?"
- :if-new (file+head+olp "%<%Y-%m-%d>.org" "#+FILETAGS: Journal\n#+TITLE: %<%Y-%m-%d>\n" ("Completed 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)))
-
- ;; Only refile if the target file is different than the current file
- (unless (equal (file-truename today-file)
- (file-truename (buffer-file-name)))
- (org-refile nil nil (list "Completed Tasks" today-file nil pos)))))
-
-
+ (org-roam-dailies-capture-templates
+ '(("t" "tasks" entry "%?"
+ :if-new (file+head+olp "%<%Y-%m-%d>.org"
+ "#+FILETAGS: Journal
+#+TITLE: %<%Y-%m-%d>\n" ("Completed 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)))
+
+ ;; Only refile if the target file is different than the current file
+ (unless (equal (file-truename today-file)
+ (file-truename (buffer-file-name)))
+ (org-refile nil nil (list "Completed Tasks" today-file nil pos)))))
(provide 'org-roam-config)
;;; org-roam-config.el ends here.
diff --git a/modules/prog-general.el b/modules/prog-general.el
index b6b58494..2338564f 100644
--- a/modules/prog-general.el
+++ b/modules/prog-general.el
@@ -141,6 +141,28 @@ If none exists, it opens magit-status."
:bind
("C-c s i" . ivy-yasnippet))
+;; ----------------------- Export Org To Markdown On Save ----------------------
+;; if the file has the proper header, saving an org file will also export to
+;; markdown with a timestamp. The header is this:
+;; # -*- org-auto-export-to-md: t; -*-
+;; #+DATE:
+;; and is available as the org-export-md snippet
+
+(defvar org-auto-export-to-md nil)
+
+(defun cj/export-org-to-md-on-save ()
+ "Export the current org file to Markdown format on save."
+ (when (and (eq major-mode 'org-mode)
+ org-auto-export-to-md)
+ (save-excursion
+ (goto-char (point-min))
+ (search-forward "#+DATE:")
+ (kill-line)
+ (insert (format-time-string " %Y-%m-%d %H:%M"))
+ (org-md-export-to-markdown))))
+
+(add-hook 'after-save-hook 'cj/export-org-to-md-on-save)
+
;; --------------------- Display Color On Color Declaration --------------------
;; display the actual color as highlight to color hex code
diff --git a/modules/prog-lisp.el b/modules/prog-lisp.el
index 618108bd..59eb122b 100644
--- a/modules/prog-lisp.el
+++ b/modules/prog-lisp.el
@@ -31,15 +31,17 @@
;; $ rlwrap sbcl
;;; Code:
+(require 'ert)
;; -------------------------------- Elisp Setup --------------------------------
;; run this on editing an elisp file
(defun cj/elisp-setup ()
"My default code preferences for emacs-lisp."
- (setq-default tab-width 4) ;; set the tab width to 4 spaces
- (setq-default indent-tabs-mode -1) ;; disable tab characters
- (setq-default fill-column 80))
+ (setq-default tab-width 4) ;; set the tab width to 4 spaces
+ (setq-default indent-tabs-mode -1) ;; disable tab characters
+ (setq-default fill-column 80) ;; default column for gnu projects
+ (display-fill-column-indicator-mode)) ;; show where the 80th column is
(add-hook 'emacs-lisp-mode-hook 'cj/elisp-setup)
;; ------------------------------ Emacs Lisp REPL ------------------------------
@@ -85,7 +87,7 @@
(defun cj/eval-and-run-all-tests-in-buffer ()
- "Delete loaded tests, evaluate current buffer. and run all loaded ERT tests."
+ "Delete any loaded tests, evaluate current buffer, and run loaded ERT tests."
(interactive)
(ert-delete-all-tests)
(eval-buffer)
diff --git a/modules/show-kill-ring.el b/modules/show-kill-ring.el
index a1f3a637..dbe7c934 100644
--- a/modules/show-kill-ring.el
+++ b/modules/show-kill-ring.el
@@ -63,12 +63,11 @@ This makes it easy to figure out which prefix to pass to yank."
;; show it
(goto-char (point-min))
(setq buffer-read-only t)
- (set-buffer-modified-p nil)
-
- ;; it's better to leave the point in it's buffer
- ;; so user can C-u (Item#) C-y in place.
- ;; (pop-to-buffer buf)
- ))
+ (set-buffer-modified-p nil)
+ ;; display-buffer rather than pop-to-buffer
+ ;; easier for user to C-u (item#) C-y
+ ;; while the point is where they want to yank
+ (display-buffer buf)))
(defun show-kill-insert-item (item)
"Insert an ITEM from the kill ring into the current buffer.
diff --git a/modules/system-utils.el b/modules/system-utils.el
index 0592f928..0ec287b9 100644
--- a/modules/system-utils.el
+++ b/modules/system-utils.el
@@ -25,7 +25,10 @@
;; 'cj/buffer-bury-alive-list' via 'C-u C-x k'
;; BUFFER BURY ALIVE LIST
-(defvar cj/buffer-bury-alive-list '("*dashboard*" "*scratch*" "*Messages*")
+(defvar cj/buffer-bury-alive-list '("*dashboard*"
+ "*scratch*"
+ "*Messages*"
+ "*ChatGPT*")
"Buffers that shouldn't be killed, but buried instead.")
;; KILL BUFFER AND WINDOW
diff --git a/modules/test-code.el b/modules/test-code.el
index 6c4fadcd..d9759e6e 100644
--- a/modules/test-code.el
+++ b/modules/test-code.el
@@ -34,13 +34,13 @@
(use-package easy-hugo
:defer .5
:init
- (setq easy-hugo-basedir "~/code/cjennings.net/")
+ (setq easy-hugo-basedir "~/code/cjennings-net/")
(setq easy-hugo-url "https://cjennings.net")
(setq easy-hugo-sshdomain "cjennings.net")
(setq easy-hugo-root "/var/www/cjennings/")
(setq easy-hugo-previewtime "300")
(setq easy-hugo-postdir "content")
- (setq easy-hugo-server-flags "-D")
+ (setq easy-hugo-server-flags "-D --noHTTPCache --disableFastRender")
(setq easy-hugo-default-ext ".md")
:bind ("C-c H" . easy-hugo)
:config
@@ -113,6 +113,7 @@ otherwise use the default location in `cj/recording-location'."
(use-package wttrin
:defer .5
:load-path ("~/code/emacs-wttrin")
+ :ensure nil ;; local package
:preface
;; dependency for wttrin
(use-package xterm-color
diff --git a/modules/ui-theme.el b/modules/ui-theme.el
index 64fa739b..8d83ac50 100644
--- a/modules/ui-theme.el
+++ b/modules/ui-theme.el
@@ -45,13 +45,15 @@ Unloads any other applied themes before applying the chosen theme."
;; persistence utility functions used by switch themes.
(defvar theme-file (concat sync-dir "emacs-theme.persist")
- "The location of the file to persist the theme name.")
+ "The location of the file to persist the theme name.
+If you want your theme change to persist across instances, put this in a
+directory that is sync'd across machines with this configuration.")
-(defvar fallback-theme-name "wombat"
+(defvar fallback-theme-name "modus-vivendi"
"The name of the theme to fallback on.
This is used then there's no file, or the theme name doesn't match
-any of the installed themes. If theme name is 'nil', there will be
-no theme.")
+any of the installed themes. This should be a built-in theme. If theme name is
+'nil', there will be no theme.")
(defun cj/read-file-contents (filename)
"Read FILENAME and return its content as a string.
@@ -97,14 +99,14 @@ loading the file name, the fallback-theme-name is applied and saved."
;; if theme-name is nil, unload all themes and load fallback theme
(if (or (string= theme-name "nil") (not theme-name))
(progn
- (mapcar #'disable-theme custom-enabled-themes)
- (cj/load-fallback-theme "Theme file not found or theme name in it is nil."))
+ (mapcar #'disable-theme custom-enabled-themes)
+ (cj/load-fallback-theme "Theme file not found or theme name in it is nil."))
;; apply theme name or if error, load fallback theme
(condition-case err
(load-theme (intern theme-name) t)
(error
- (cj/load-fallback-theme (concat "Error loading " theme-name
- ".")))))))
+ (cj/load-fallback-theme (concat "Error loading " theme-name
+ ".")))))))
(cj/load-theme-from-file)
diff --git a/modules/vc-config.el b/modules/vc-config.el
index a9b72507..769825a8 100644
--- a/modules/vc-config.el
+++ b/modules/vc-config.el
@@ -28,7 +28,14 @@
(setf vc-handled-backends nil) ;; magit is the only vc interface I use
(setq magit-bury-buffer-function 'magit-restore-window-configuration)
(setq git-commit-major-mode 'org-mode) ;; edit commit messages in org-mode
- (setq magit-display-buffer-function 'magit-display-buffer-fullframe-status-topleft-v1))
+ (setq magit-display-buffer-function
+ 'magit-display-buffer-fullframe-status-topleft-v1)
+
+ ;; CLONING
+ (setq magit-clone-default-directory code-dir) ;; cloned repositories go here by default
+ (setq magit-clone-set-remote-head t) ;; do as git does for remote heads
+ (setq magit-clone-set-remote.pushDefault 'ask) ;; ask if origin is default
+ ) ;; end use-package magit
;; --------------------------------- Git Gutter --------------------------------
;; mark changed lines since last commit in the margin