diff --git a/.gitignore b/.gitignore index d4470f3..0c131b8 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,4 @@ url/ bookmarks # Custom file -custom.el - -# Flycheck -flycheck_* \ No newline at end of file +custom.el \ No newline at end of file diff --git a/init.el b/init.el index d86cad3..8b5e6f0 100644 --- a/init.el +++ b/init.el @@ -63,11 +63,6 @@ (load (concat user-emacs-directory "shared-packages.el")) ;; UI and display related packages (load (concat user-emacs-directory "ui.el")) - -;; Use a custom file instead of putting customisations in init.el -(setq custom-file (concat user-emacs-directory "custom.el")) -(when (file-exists-p custom-file) (load custom-file)) - ;; Writing behavior and packages (load (concat user-emacs-directory "writing.el")) ;; Navigation behavior and packages @@ -80,3 +75,7 @@ (load-directory (concat user-emacs-directory "workflows")) ;; Custom screens (load-directory (concat user-emacs-directory "screens")) + +;; Use a custom file instead of putting customisations in init.el +(setq custom-file (concat user-emacs-directory "custom.el")) +(when (file-exists-p custom-file) (load custom-file)) diff --git a/navigation.el b/navigation.el index df39764..cf587d1 100644 --- a/navigation.el +++ b/navigation.el @@ -36,20 +36,6 @@ :config (ultra-scroll-mode 1)) -;; Disable mouse input -(defcustom theurgy-mouse-disabled t - "Disable mouse input." - :type 'boolean - :group 'theurgy) - -(when theurgy-mouse-disabled - (dolist (k '([mouse-1] [down-mouse-1] [drag-mouse-1] [double-mouse-1] [triple-mouse-1] - [mouse-2] [down-mouse-2] [drag-mouse-2] [double-mouse-2] [triple-mouse-2] - [mouse-3] [down-mouse-3] [drag-mouse-3] [double-mouse-3] [triple-mouse-3] - [mouse-4] [down-mouse-4] [drag-mouse-4] [double-mouse-4] [triple-mouse-4] - [mouse-5] [down-mouse-5] [drag-mouse-5] [double-mouse-5] [triple-mouse-5])) - (global-unset-key k))) - ;; Keyboard Scrolling (global-set-key (kbd "C-") '(lambda () (interactive) (scroll-up-line))) (global-set-key (kbd "C-") '(lambda () (interactive) (scroll-down-line))) diff --git a/screens/dashboard.el b/screens/dashboard.el index ab4341f..9cc57f2 100644 --- a/screens/dashboard.el +++ b/screens/dashboard.el @@ -115,8 +115,8 @@ (grid-get-box `(:content ,(concat (enlight-menu '(("Projects" - ("Switch To" theurgy-open-project "p") - ("Project List" theurgy-edit-projects-list "l"))))) + ("Open" open-project "o") + ("Project List" open-inbox "p"))))) :align center :width 20)) (grid-get-box `(:content ,(concat diff --git a/userland/projects.el b/userland/projects.el deleted file mode 100644 index 08ba049..0000000 --- a/userland/projects.el +++ /dev/null @@ -1,61 +0,0 @@ -;;; projects.el --- Project management configuration with whaler -*- lexical-binding: t -*- - -;; 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 . - - -;;; Commentary: - -;; commentary - -;;; Code: - -(require 'subr-x) - -(defcustom theurgy-project-default-file-alist '(("~/.emacs.d" . "init.el")) - "This alist specifies which file (relative to the project root) to open in the main frame by default when opening a project." - :group 'theurgy - :group 'theurgy-projects - :group 'whaler) - -(use-package whaler - :ensure t - :config - (whaler-populate-projects-directories) - ) - -(defun get-project-default-file (dir) - "Get the project default file for `DIR', regardless of whether either path is absolute or relative." - (let ((absolute-project-dir (expand-file-name (string-remove-suffix "/" dir))) - (absolute-project-default-file-alist (mapcar (lambda (x) `(,(string-remove-suffix "/" (expand-file-name (car x))) . ,(cdr x))) - theurgy-project-default-file-alist))) - (or (file-name-concat dir (cdr (assoc absolute-project-dir absolute-project-default-file-alist))) dir))) - -(defun theurgy-open-project () - "Select a project and update neotree to use it as root." - (interactive) - (whaler :action (lambda (dir) - (find-file (get-project-default-file dir)) - (tab-rename (file-name-nondirectory (string-remove-suffix "/" dir))) - (neotree-dir dir)))) - -(defun theurgy-edit-projects-list () - "Open list of projects in customize." - (interactive) - (customize-group 'whaler)) - -(provide 'projects) - -;;; projects.el ends here diff --git a/userland/terminal.el b/userland/terminal.el index d99ed8f..d47dc0c 100644 --- a/userland/terminal.el +++ b/userland/terminal.el @@ -33,22 +33,12 @@ 'shell)) (defun theurgy-bottom-shell () - "Put a shell in the bottom of the frame." (interactive) (let ((win (car (window-at-side-list nil 'bottom)))) (if (and win (equal 'bottom (window-parameter win 'window-side))) (delete-window win) (funcall (theurgy-shell))))) -(defun theurgy-main-shell () - "Put a shell in a main window." - (interactive) - (if (get-buffer "*Shell Session*") - (switch-to-buffer "*Shell Session*") - (funcall (theurgy-shell) "*Shell Session*"))) - -(define-key global-map (kbd "C-") 'theurgy-main-shell) - (global-set-key (kbd "M-RET") 'theurgy-bottom-shell) (define-key vterm-mode-map (kbd "M-RET") 'theurgy-bottom-shell) diff --git a/workflows/flycheck_org-custom.el b/workflows/flycheck_org-custom.el new file mode 100644 index 0000000..c4d5434 --- /dev/null +++ b/workflows/flycheck_org-custom.el @@ -0,0 +1,698 @@ +;;; org-custom.el --- Org-mode configuration -*- lexical-binding: t -*- + +;; 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 . + + +;;; Commentary: + +;; commentary + +;;; Code: + +(require 'org) +(require 'org-agenda) +(require 'org-attach) +(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) + +(defcustom theurgy-org-directory "~/.org/" + "The directory for all theurgy org-mode files." + :type 'string + :group 'theurgy + :group 'theurgy-org) + +;; Change a bunch of default org-mode variables. +(setq org-log-done nil ;; 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(t)" "WIP(w)" "DELEGATED(p)" "WAITING(?)" "|" "CANCELLED(x)" "DONE(d)")) ;; Some extra keywords in addition to TODO and DONE + org-use-fast-todo-selection t ;; Always use fast selection + org-refile-targets '((org-agenda-files :maxlevel . 2)) ;; Allow any agenda files to be refile targets. + + org-agenda-files (append (apply 'append (mapcar + (lambda (dir) + (directory-files-recursively dir org-agenda-file-regexp)) + `(,(concat theurgy-org-directory "tasks")))) + `(,(concat theurgy-org-directory "inbox.org"))) ;; Agenda files location - gathered recursively + org-cite-global-bibliography `(,(concat theurgy-org-directory "global.bib")) ;; Global bibliography location + + org-startup-indented t ;; Start indented - this fixed org-indent mode + + org-attach-id-dir (concat theurgy-org-directory "lore/assets") + + org-M-RET-may-split-line '((item . nil)) ;; https://irreal.org/blog/?p=6297 + ) + +;; 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]")) + +(use-package org-appear :ensure t + :init + (setq org-appear-delay 0.2) + :hook + org-mode) + +;; Side tree +(use-package org-side-tree + :hook ((org-modern-mode . org-side-tree))) + +;; Advice to display org-side-tree where we want it +(defun theurgy-org-side-tree () + "Create or pop to Org-Side-Tree buffer." + (interactive) + (when (org-side-tree-buffer-p) + (error "Don't tree a tree")) + (unless (or (derived-mode-p 'org-mode) + (derived-mode-p 'outline-mode) + outline-minor-mode) + (error "Not an outline buffer")) + (let* ((tree-name (if (default-value 'org-side-tree-persistent) + "*Org-Side-Tree*" + (format "%s" (buffer-name)))) + (tree-buffer (get-buffer tree-name)) + (heading (org-side-tree-heading-number)) + (dd default-directory) + (inv-spec buffer-invisibility-spec)) + (unless (buffer-live-p tree-buffer) + (save-restriction + (widen) + (jit-lock-mode 1) + (jit-lock-fontify-now)) + (setq tree-buffer (generate-new-buffer tree-name)) + (add-hook 'kill-buffer-hook #'org-side-tree-cleanup nil t) + (let* ((headings (org-side-tree-get-headings)) + (tree-head-line (or (cadar (org-collect-keywords + '("title"))) + "Org-Side-Tree")) + (tree-mode-line (format "Org-Side-Tree - %s" + (buffer-name)))) + (when (default-value 'org-side-tree-enable-folding) + (setq-local org-side-tree-enable-folding t)) + (with-current-buffer tree-buffer + (setq-local default-directory dd) + (org-side-tree-mode) + (setq tabulated-list-entries headings) + (tabulated-list-print t t) + (when (default-value 'org-side-tree-enable-folding) + (setq-local org-side-tree-enable-folding t) + ;; preserve org font-locking + (setq-local outline-minor-mode-highlight nil) + (outline-minor-mode 1)) + (setq buffer-invisibility-spec inv-spec) + (setq header-line-format tree-head-line) + (setq mode-line-format tree-mode-line)))) + (org-side-tree-set-timer) + (switch-to-buffer (buffer-name)) + (display-buffer-in-side-window + tree-buffer + `((side . ,org-side-tree-display-side) + (slot . 1) + (window-width . ,org-side-tree-width))) + (when (default-value 'org-side-tree-persistent) + (setq-local org-side-tree-persistent + (buffer-name)) + (org-side-tree-update)) + (when org-side-tree-select + (pop-to-buffer tree-buffer)) + (setq window-size-fixed (when org-side-tree-width 'width)) + (pulse-momentary-highlight-one-line) + (org-side-tree-go-to-heading heading))) + +(advice-add 'org-side-tree :override #'theur) + +;; Helper functions for the side tree +(defun theurgy-toggle-org-side-tree () + (interactive) + (if (get-buffer-window (concat "" (file-name-nondirectory (buffer-file-name)))) + (delete-window (get-buffer-window (concat "" (file-name-nondirectory (buffer-file-name))))) + (org-side-tree))) + +(add-to-list 'display-buffer-alist + '(".+\.org" + (display-buffer-in-side-window) + (side . left) + (slot . 1) + (window-height . 0.2))) + +(define-key org-mode-map (kbd "C-") #'theurgy-toggle-org-side-tree) + +;; https://chrismaiorana.com/summer-productivity-reset-emacs-functions/ +(defun csm/replace-punctuation-at-point () + "Replace punctuation at point (., !, ?) with the character typed by the user." + (interactive) + (let ((char (this-command-keys))) ;; Get the key pressed by the user + (if (and (member (char-after) '(?. ?! ?? ?,)) ;; Check if current char is ., !, or ? + (member (string-to-char char) '(?. ?! ??))) ;; Check if typed char is ., !, or ? + (progn + (delete-char 1) ;; Delete existing punctuation + (insert char)) ;; Insert new punctuation + (self-insert-command 1)))) ;; Default behavior: insert character + +;; Bind this function to punctuation keys +(define-key global-map "." 'csm/replace-punctuation-at-point) +(define-key global-map "," 'csm/replace-punctuation-at-point) +(define-key global-map "!" 'csm/replace-punctuation-at-point) +(define-key global-map "?" 'csm/replace-punctuation-at-point) + +;; Windmove bindings since org overwrites them otherwise +(define-key org-mode-map (kbd "C-c ") 'windmove-left) +(define-key org-mode-map (kbd "C-c ") 'windmove-right) +(define-key org-mode-map (kbd "C-c ") 'windmove-up) +(define-key org-mode-map (kbd "C-c ") 'windmove-down) + +;; Same with scrolling +(define-key org-mode-map (kbd "C-S-") '(lambda () (interactive) (scroll-up-line 10))) +(define-key org-mode-map (kbd "C-S-") '(lambda () (interactive) (scroll-down-line 10))) + +;; 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-") #'move-sentence-left) +(define-key org-mode-map (kbd "C-M-") #'move-sentence-right) +(define-key org-mode-map (kbd "C-M-") #'move-paragraph-up) +(define-key org-mode-map (kbd "C-M-") #'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)) + +;;; 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\n%?" + :empty-lines 1) + ("ip" "Project" entry + (function (lambda () (select-project "Ideas"))) + "* %^{TITLE} \n\n%?" + :empty-lines 1) + ("ic" "Career" entry + (function (lambda () (select-career-project "Ideas"))) + "* %^{TITLE} \n\n%?" + :empty-lines 1) + + ("t" "Task") + ("tt" "Generic") + ("ttt" "Raw" entry + (file "~/.org/inbox.org") + "* TODO [%^{priority|#A|#B|#C|#D}] %^{TITLE} :task:\n\n%?" + :empty-lines 1) + ("ttm" "Maintenance" entry + (function (lambda () (select-maintenance-area "TO-DO"))) + "* TODO [%^{priority|#A|#B|#C|#D}] %^{TITLE}\n\n%?" + :empty-lines 1) + ("ttp" "Project" entry + (function (lambda () (select-project "TO-DO"))) + "* TODO [%^{priority|#A|#B|#C|#D}] %^{TITLE}\n\n%?" + :empty-lines 1) + ("ttc" "Career" entry + (function (lambda () (select-career-project "TO-DO"))) + "* TODO [%^{priority|#A|#B|#C|#D}] %^{TITLE}\n\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\n%?" + :empty-lines 1) + ("nm" "Meeting") + ("nmm" "Raw" entry + (file "~/.org/inbox.org") + "* %^{TITLE} :meeting: \n\n%?" + :clock-in t + :clock-resume t) + ("nmc" "Career" entry + (function (lambda () (select-career-project "Calendar"))) + "* %^{TITLE} \n\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) + +(add-to-list 'display-buffer-alist + '("\\*Org Agenda\\*" + (display-buffer-in-side-window) + (side . right) + (slot . 3) + (window-width . 0.2))) + +(add-to-list 'display-buffer-alist + '("\\*capture\\*\\|CAPTURE-" + (display-buffer-in-side-window) + (side . right) + (slot . 2) + (window-width . 0.2))) + +;; 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-roam-dailies-directory (file-truename "~/.org/lore/refined/journal/")) + (org-roam-file-exclude-regexp "\\.git/.*\\|logseq/.*$") + (org-roam-completion-everywhere) + (org-roam-capture-templates + '(("r" "Raw") + ("rr" "Note" plain + "%?" + :target (file+head "raw/${slug}.org" "#+title: ${title}\n") + :unnarrowed t) + ("rq" "Question" plain + "%?" + :target (file+head "raw/${slug}.org" "#+title: ${title}\n#+filetags: :question:") + :unnarrowed t) + ("i" "Index" plain + "%?" + :target (file+head "raw/${slug}.org" "#+title: ${title} - Index\n#+filetags: :index:") + :unnarrowed t) + ("R" "Refined") + ("Rm" "Mini-essay" plain + "%?" + :target (file+head "refined/wiki/${slug}.org" "#+title: ${title}\n#+author: Jakub Nowak\n#+filetags: :mini-essay:") + :unnarrowed t) + ("Re" "Essay" plain + "%?" + :target (file+head "refined/wiki/${slug}.org" "#+title: ${title}\n#+author: Jakub Nowak\n#+filetags: :essay:") + :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 headline’s 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 don’t 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)))) + +(use-package logseq-org-roam + :straight (:host github + :repo "sbougerel/logseq-org-roam" + :files ("*.el"))) + +(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) + ("f" "Find" org-roam-node-find) ] + ["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)] + ["Org Roam UI" ("U" "Enable org-roam-ui-mode" org-roam-ui-mode)]) + +(define-key global-map (kbd "C-c o n") #'org-roam-menu) + +(use-package org-roam-ui + :straight + (:host github :repo "org-roam/org-roam-ui" :branch "main" :files ("*.el" "out")) + :after org-roam + ;; normally we'd recommend hooking orui after org-roam, but since org-roam does not have + ;; a hookable mode anymore, you're advised to pick something yourself + ;; if you don't care about startup time, use + :hook (after-init . org-roam-ui-mode) + :config + (setq org-roam-ui-sync-theme t + org-roam-ui-follow t + org-roam-ui-update-on-save t + org-roam-ui-open-on-start t)) + +;; 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) + +;;; Literate Programming +;; Racket +(use-package ob-racket + :after org + :config + (add-hook 'ob-racket-pre-runtime-library-load-hook + #'ob-racket-raco-make-runtime-library) + :straight (ob-racket + :type git :host github :repo "hasu/emacs-ob-racket" + :files ("*.el" "*.rkt"))) + +(org-babel-do-load-languages + 'org-babel-load-languages + '((emacs-lisp . t) + (racket . t) + )) + +;;; LaTeX configuration +(require 'ox-latex) + +(setq org-latex-pdf-process + '("pdflatex -interaction nonstopmode -output-directory %o %f" + "bibtex %b" + "pdflatex -interaction nonstopmode -output-directory %o %f" + "pdflatex -interaction nonstopmode -output-directory %o %f")) +(setq org-latex-with-hyperref nil) ;; stop org adding hypersetup{author..} to latex export +;; (setq org-latex-prefer-user-labels t) + +;; deleted unwanted file extensions after latexMK +(setq org-latex-logfiles-extensions + (quote ("lof" "lot" "tex~" "aux" "idx" "log" "out" "toc" "nav" "snm" "vrb" "dvi" "fdb_latexmk" "blg" "brf" "fls" "entoc" "ps" "spl" "bbl" "xmpi" "run.xml" "bcf" "acn" "acr" "alg" "glg" "gls" "ist"))) + +(unless (boundp 'org-latex-classes) + (setq org-latex-classes nil)) + +(provide 'org-custom) + +;;; org-custom.el ends here