Initial commit

This commit is contained in:
Jakub 2025-07-09 16:51:22 +08:00
commit f66338dcf2
2 changed files with 500 additions and 0 deletions

499
logos.el Normal file
View file

@ -0,0 +1,499 @@
;;; logos.el --- A workflow for org-mode -*- lexical-binding: t -*-
;; Author: Jakub
;; Maintainer: Jakub
;; Version: 1.0
;; Package-Requires: (straight)
;; Homepage: homepage
;; Keywords: org
;; This file is not part of GNU Emacs
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(require 'transient)
(require 'subr-x)
(defun org-mode-init ()
"This is called through `org-mode-hook', so that I don't need to `add-hook' 20 million times."
;; I want org to display pictures inline.
(org-display-inline-images)
;; I don't want monospace text by default.
(variable-pitch-mode)
)
(add-hook 'org-mode-hook #'org-mode-init)
;; Change a bunch of default org-mode variables.
(setq org-log-done 'time ;; I want to keep track of the time tasks are completed.
org-return-follows-link t ;; I want to be able to follow links easily.
org-hide-emphasis-markers t ;; This is a big one: hide markup syntax like ** and //.
org-pretty-entities t ;; These two variables together render latex entities as UTF8, which means that Greek letters, subscript, and superscript are all rendered correctly.
org-pretty-entities-include-sub-superscripts t
org-enforce-todo-dependencies t ;; Prevent changing a parent to DONE if the children aren't
org-enforce-todo-checkbox-dependencies t
org-agenda-skip-scheduled-if-done t ;; Don't show done stuff in the agenda view
org-agenda-skip-deadline-if-done t
org-agenda-skip-timestamp-if-done t
org-todo-keywords '((sequence "TODO" "WIP" "DELEGATED" "WAITING" "|" "CANCELLED" "DONE")) ;; Some extra keywords in addition to TODO and DONE
org-refile-targets '((org-agenda-files :maxlevel . 2)) ;; Allow any agenda files to be refile targets.z
org-agenda-files (apply 'append (mapcar
(lambda (dir)
(directory-files-recursively dir org-agenda-file-regexp))
'("~/.org/tasks"))) ;; Agenda files location - gathered recursively
org-cite-global-bibliography '("~/.org/global.bib") ;; Global bibliography location
org-startup-indented t ;; Start indented - this fixed org-indent mode
org-attach-id-dir "~/.org/lore/assets"
)
;; Org modern and other interface enhancements
(use-package org-modern
:hook ((org-mode . org-modern-mode)
(org-agenda-finalize . org-modern-agenda)))
(use-package org-modern-indent
:straight (org-modern-indent :type git :host github :repo "jdtsmith/org-modern-indent")
:hook ((org-mode . org-modern-indent-mode)))
(use-package wc-mode
:hook ((org-mode . wc-mode))
:config (setq wc-modeline-format "WC[%tw]"))
;; Sentence and word navigation and marking
(setq sentence-end-double-space nil) ;; Otherwise, M-e is broken in normal writing.
;;; Generally useful things
;; Mark word and sentence
(defun mark-whole-word ()
"Mark the whole word underneath the cursor."
(interactive)
(forward-word)
(set-mark-command nil)
(backward-word))
(defun mark-sentence ()
"Mark the entire sentence underneath the cursor."
(interactive)
(forward-sentence)
(set-mark-command nil)
(backward-sentence))
(define-key org-mode-map (kbd "C-@") #'mark-whole-word)
(define-key org-mode-map (kbd "M-@") #'mark-sentence)
(transient-define-prefix mark-menu-transient ()
"Transient menu for marking units of text."
["Mark" ("w" "Word" mark-whole-word)
("s" "Sentence" mark-sentence)
("p" "Paragraph" mark-paragraph)
("b" "Buffer" mark-whole-buffer)])
(define-key org-mode-map (kbd "C-c o SPC") #'mark-menu-transient)
;; Section navigation and reordering
(defun move-sentence-right (&optional arg)
"Move the whole sentence to the right of the next sentence, `ARG' times."
(interactive "^p")
(or arg (setq arg 1))
(while (> arg 0)
(forward-sentence)
(backward-sentence)
(left-char) ;; Capture previous space
(kill-sentence)
(forward-sentence)
(yank)
(backward-sentence)
(setq arg (1- arg))))
(defun move-sentence-left (&optional arg)
"Move the whole sentence to the left of the previous sentence, `ARG' times."
(interactive "^p")
(or arg (setq arg 1))
(while (> arg 0)
(forward-sentence)
(backward-sentence)
(left-char) ;; Capture previous space
(kill-sentence)
(backward-sentence)
(left-char) ;; Capture previous space
(yank)
(backward-sentence)
(setq arg (1- arg))))
(defun move-paragraph-up (&optional arg)
"Move the whole paragraph above the previous paragraph, `ARG' times."
(interactive "^p")
(or arg (setq arg 1))
(while (> arg 0)
(forward-paragraph)
(backward-paragraph)
(kill-paragraph nil)
(backward-paragraph)
(yank)
(backward-paragraph)
(setq arg (1- arg))))
(defun move-paragraph-down (&optional arg)
"Move the whole paragraph above the previous paragraph, `ARG' times."
(interactive "^p")
(or arg (setq arg 1))
(while (> arg 0)
(forward-paragraph)
(backward-paragraph)
(kill-paragraph nil)
(forward-paragraph)
(yank)
(backward-paragraph)
(setq arg (1- arg))))
(define-key org-mode-map (kbd "C-M-<left>") #'move-sentence-left)
(define-key org-mode-map (kbd "C-M-<right>") #'move-sentence-right)
(define-key org-mode-map (kbd "C-M-<up>") #'move-paragraph-up)
(define-key org-mode-map (kbd "C-M-<down>") #'move-paragraph-down)
(transient-define-prefix reorder-transient ()
"Transient menu for text re-ordering commands."
["Move sentence..." ("l" "Left" move-sentence-left)
("r" "Right" move-sentence-right)]
["Move paragraph..." ("u" "Up" move-paragraph-up)
("d" "Down" move-paragraph-down)])
(define-key org-mode-map (kbd "C-c o r") #'reorder-transient)
;; Focused rewriting
(defun break-out-sentence ()
"Breaks a sentence out into it's own buffer for editing."
(interactive)
(backward-sentence)
(kill-sentence)
(switch-to-buffer-other-window "*break-out*")
(erase-buffer)
(yank))
(defun break-out-choose-sentence ()
"Chooses a sentence from the break-out buffer."
(interactive)
(backward-sentence)
(kill-sentence)
(other-window -1)
(kill-buffer "*break-out*")
(yank))
(defun break-out-dwim ()
"Either break-out or choose sentency depending on buffer name."
(interactive)
(if (equal (buffer-name) "*break-out*")
(break-out-choose-sentence)
(break-out-sentence)))
(define-key org-mode-map (kbd "C-c o b") #'break-out-dwim)
;; Powerthesaurus
(use-package powerthesaurus
:bind ("C-x t" . powerthesaurus-transient))
;; Harper
(when (and (not (equal system-type 'windows-nt)) (locate-file "harper-ls" exec-path))
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'(org-mode . ("harper-ls" "--stdio"))))
(setq-default eglot-workspace-configuration
'(:harper-ls (:dialect "Australian")))
(add-hook 'org-mode-hook 'eglot-ensure))
;; Company
(defun org-mode-company-hook ()
"Set company backends for `org-mode' usage."
(setq-local company-backends
'((company-capf company-dabbrev company-files company-ispell))))
(add-hook 'org-mode-hook #'org-mode-company-hook)
;;; Exobrain
;;; Task management
;; Maintenance and project file creation shortcuts
(defun new-maintenance-file (maintenance-area)
"Create a new maintenance file for a given `MAINTENANCE-AREA'."
(interactive "sMaintenance area is: ")
(find-file (concat "~/.org/tasks/maintenance/" maintenance-area ".org"))
(insert "\n\n* Calendar\n\n* TO-DO\n\n* Routines\n\n* Archive\n")
(goto-char (point-min)))
(defun new-project-file (project-name acceptance-criteria)
"Create a new project file for a given `PROJECT-NAME', with some `ACCEPTANCE-CRITERIA'."
(find-file (concat "~/.org/tasks/projects/" project-name ".org"))
(insert (concat "\n\n* Acceptance Criteria\n\n" acceptance-criteria "\n\n* Ideas\n\n* TODO Work\n\n** Calendar\n\n** TO-DO\n\n** Routines\n\n** Archive\n"))
(goto-char (point-min)))
(defun new-generic-project (project-name acceptance-criteria)
"Interactive wrapper for `new-project-file', for generic projects."
(interactive "sProject name is: \nsAcceptance criteria is: ")
(new-project-file project-name acceptance-criteria))
(defun new-career-project (project-name acceptance-criteria)
"Interactive wrapper for `new-project-file', for career projects."
(interactive "sProject name is: \nsAcceptance criteria is: ")
(new-project-file (concat "career/" project-name) acceptance-criteria))
;; Captures
(defun select-task-area (location headline)
"Prompt for a file in ~/.org/tasks/maintenance/ to insert the capture."
(let* ((files (directory-files (concat "~/.org/tasks/" location) t "\\.org$"))
(choices (mapcar
(lambda (x) (string-remove-suffix ".org" x))
(mapcar #'file-name-nondirectory files)))
(selected (completing-read "Choose a file: " choices nil t)))
(set-buffer (org-capture-target-buffer (concat "~/.org/tasks/" location selected ".org")))
(org-capture-put-target-region-and-position)
(widen)
(goto-char (point-min))
(setq headline (org-capture-expand-headline headline))
(re-search-forward (format org-complex-heading-regexp-format
(regexp-quote headline))
nil t)
(forward-line 0)))
(defun select-maintenance-area (headline)
(select-task-area "maintenance/" headline))
(defun select-project (headline)
(select-task-area "projects/" headline))
(defun select-career-project (headline)
(select-task-area "projects/career/" headline))
(setq org-capture-templates
'(("i" "Idea")
("ii" "Generic" entry
(file "~/.org/inbox.org")
"* %^{TITLE} :idea: \n:Created: %T\n%?"
:empty-lines 1)
("ip" "Project" entry
(function (lambda () (select-project "Ideas")))
"* %^{TITLE} \n:Created: %T\n%?"
:empty-lines 1)
("ic" "Career" entry
(function (lambda () (select-career-project "Ideas")))
"* %^{TITLE} \n:Created: %T\n%?"
:empty-lines 1)
("t" "Task")
("tt" "Generic")
("ttt" "Raw" entry
(file "~/.org/inbox.org")
"* TODO [%^{priority|#A|#B|#C|#D}] %^{TITLE} :task:\n:Created: %T\n%?"
:empty-lines 1)
("ttm" "Maintenance" entry
(function (lambda () (select-maintenance-area "TO-DO")))
"* TODO [%^{priority|#A|#B|#C|#D}] %^{TITLE}\n:Created: %T\n%?"
:empty-lines 1)
("ttp" "Project" entry
(function (lambda () (select-project "TO-DO")))
"* TODO [%^{priority|#A|#B|#C|#D}] %^{TITLE}\n:Created: %T\n%?"
:empty-lines 1)
("ttc" "Career" entry
(function (lambda () (select-career-project "TO-DO")))
"* TODO [%^{priority|#A|#B|#C|#D}] %^{TITLE}\n:Created: %T\n%?"
:empty-lines 1)
("ts" "Scheduled")
("tss" "Raw" entry
(file "~/.org/inbox.org")
"* TODO [%^{priority|#A|#B|#C|#D}] %^{TITLE} :scheduled:\n:SCHEDULED: %^T\n%?"
:empty-lines 1
:time-prompt t)
("tsm" "Maintenance" entry
(function (lambda () (select-maintenance-area "Calendar")))
"* TODO [%^{priority|#A|#B|#C|#D}] %^{TITLE} \n:SCHEDULED: %^T\n%?"
:empty-lines 1
:time-prompt t)
("tsp" "Project" entry
(function (lambda () (select-project "Calendar")))
"* TODO [%^{priority|#A|#B|#C|#D}] %^{TITLE} \n:SCHEDULED: %^T\n%?"
:empty-lines 1
:time-prompt t)
("tsc" "Career" entry
(function (lambda () (select-career-project "Calendar")))
"* TODO [%^{priority|#A|#B|#C|#D}] %^{TITLE} \n:SCHEDULED: %^T\n%?"
:empty-lines 1
:time-prompt t)
("n" "Note")
("nn" "Raw" entry
(file "~/.org/inbox.org")
"* %^{TITLE} :note: \n:Created: %T\n%?"
:empty-lines 1)
("nm" "Meeting")
("nmm" "Raw" entry
(file "~/.org/inbox.org")
"* %^{TITLE} :meeting: \n:Created: %T\n%?"
:clock-in t
:clock-resume t)
("nmc" "Career" entry
(function (lambda () (select-career-project "Calendar")))
"* %^{TITLE} \n:Created: %T\n%?"
:empty-lines 1
:clock-in t
:clock-resume t)))
(defun open-inbox ()
"Opens `~/.org/inbox.org'"
(interactive)
(find-file "~/.org/inbox.org"))
(defun open-maintenance ()
"Opens `~/.org/tasks/maintenance/'"
(interactive)
(find-file "~/.org/tasks/maintenance/"))
(defun open-projects ()
"Opens `~/.org/tasks/projects/'"
(interactive)
(find-file "~/.org/tasks/projects/"))
(defun open-career ()
"Opens `~/.org/tasks/projects/career/'"
(interactive)
(find-file "~/.org/tasks/projects/career/"))
(transient-define-prefix task-management-menu ()
"Transient menu for task management shortcuts."
["Go To" ("i" "Inbox" open-inbox)
("m" "Maintenance Directory" open-maintenance)
("p" "Projects Directory" open-projects)
("c" "Career Directory" open-career)]
["Create New" ("M" "Maintenance File" new-maintenance-file)
("P" "Project" new-generic-project)
("C" "Career Project" new-career-project)])
(define-key global-map (kbd "C-c o t") #'task-management-menu)
(define-key global-map (kbd "C-c a") #'org-agenda)
(define-key global-map (kbd "C-c c") #'org-capture)
;; Org roam
(use-package org-roam
:straight nil
:ensure t
:init
(setq org-roam-v2-ack t)
:custom
(org-roam-directory (file-truename "~/.org/lore/"))
(org-dailies-directory (file-truename "~/.org/lore/refined/journal/"))
(org-roam-file-exclude-regexp "\\.git/.*\\|logseq/.*$")
(org-roam-completion-everywhere)
(org-roam-capture-templates
'(("c" "Raw" plain
"%?"
:target (file+head "raw/${slug}.org" "#+title: ${title}\n")
:unnarrowed t)
("r" "Refined")
("rm" "Mini-essay" plain
"%?"
:target (file+head "refined/wiki/${slug}.org" "#+title: ${title}\n#+author: Jakub Nowak")
:unnarrowed t)))
(org-roam-dailies-capture-templates
'(("d" "default" entry
"* %?"
:target (file+head "%<%Y-%m-%d>.org" ;; format matches Logseq
"#+title: %<%Y-%m-%d>\n"))))
:bind (("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find)
("C-c n g" . org-roam-graph)
("C-c n i" . org-roam-node-insert)
("C-c n c" . org-roam-capture)
:map org-roam-dailies-map
("Y" . org-roam-dailies-capture-yesterday)
("T" . org-roam-dailies-capture-tomorrow))
:bind-keymap ("C-c n d" . org-roam-dailies-map)
:config
(require 'org-roam-dailies) ;; Ensure the keymap is available
(org-roam-db-autosync-mode))
(defun org-roam-create-node-from-headline ()
"Create an Org-roam note from the current headline and jump to it.
Normally, insert the headlines title using the #title: file-level property
and delete the Org-mode headline. However, if the current headline has a
Org-mode properties drawer already, keep the headline and dont insert
#+title:'. Org-roam can extract the title from both kinds of notes, but using
#+title: is a bit cleaner for a short note, which Org-roam encourages."
(interactive)
(let ((title (nth 4 (org-heading-components)))
(has-properties (org-get-property-block)))
(org-cut-subtree)
(org-roam-find-file title nil nil 'no-confirm)
(org-paste-subtree)
(unless has-properties
(kill-line)
(while (outline-next-heading)
(org-promote)))
(goto-char (point-min))
(when has-properties
(kill-line)
(kill-line))))
(transient-define-prefix org-roam-menu ()
"Transient menu for task management shortcuts."
["Node" ("c" "Capture" org-roam-node-find)
("i" "Insert" org-roam-node-insert)
("r" "Refile" org-roam-create-node-from-headline)
("v" "Visit" org-roam-node-visit) ]
["Dailies" ("t" "Today" org-roam-dailies-capture-today)
("y" "Yesterday" org-roam-dailies-capture-yesterday)
("n" "Tomorrow" org-roam-dailies-capture-tomorrow)]
["Logseq" ("R" "Fix links" logseq-org-roam)])
(define-key global-map (kbd "C-c o n") #'org-roam-menu)
;; Bibliography stuff
(setq bibtex-dialect 'biblatex) ;; Use biblatex instead of bibtex.
(use-package biblio)
(defun bibtex-online-entry ()
(interactive)
(bibtex-entry "Online"))
(defun bibtex-misc-entry ()
(interactive)
(bibtex-entry "Misc"))
(defun bibtex-software-entry ()
(interactive)
(bibtex-entry "Software"))
(transient-define-prefix bibtex-transient-menu ()
"Transient menu for task management shortcuts."
["Biblio" ("d" "doi.org" doi-insert-bibtex)
("x" "arXiv" arxiv-lookup)]
["Templates" ("o" "Online Resource" bibtex-online-entry)
("m" "Misc" bibtex-misc-entry)
("s" "Software" bibtex-software-entry)])
(define-key bibtex-mode-map (kbd "C-c r") #'bibtex-transient-menu)
;;; logos.el ends here