;;;; $DOOMDIR/config.el -*- lexical-binding: t; -*-
;;; $DOOMDIR/config.el -*- lexical-binding: t; -*-
;;;
;;;
;;; BEGIN_code
;;;
;;;
;; Add handlers SELinux files
(add-to-list 'auto-mode-alist '("\\.te\\'" . m4-mode))
;; make a shell script executable automatically on save
(add-hook 'after-save-hook
'executable-make-buffer-file-executable-if-script-p)
(setq c-default-style "linux") ;; set style to "linux"
;; Clone git repos or jump to the project in the code path
;; https://github.com/NinjaTrappeur/my-repo-pins
(use-package! my-repo-pins
:after-call my-repo-pins
:defer t
:init
(setq my-repo-pins-code-root "~/projects/code"))
(setq copilot-indent-offset-warning-disable t)
(use-package! copilot
:hook (prog-mode . copilot-mode)
:bind (:map copilot-completion-map
("<tab>" . 'copilot-accept-completion)
("TAB" . 'copilot-accept-completion)
("C-TAB" . 'copilot-accept-completion-by-word)
("C-<tab>" . 'copilot-accept-completion-by-word)))
(after! lsp-clangd
(setq lsp-clients-clangd-args
'("-j=3"
"--background-index"
"--clang-tidy"
"--completion-style=detailed"
"--header-insertion=never"
"--header-insertion-decorators=0"))
(set-lsp-priority! 'clangd 2))
;; use just mode for setting tasks to run at the cmdline
(use-package! justl
:config
(map! :n "e" 'justl-exec-recipe))
(after! nix-mode
(setq lsp-nix-nixd-server-path "nixd"
lsp-nix-nixd-formatting-command [ "nixfmt" ]
lsp-nix-nixd-nixpkgs-expr "import (builtins.getFlake \"/home/brian/.dotfiles\").inputs.nixpkgs { }"
lsp-nix-nixd-nixos-options-expr "(builtins.getFlake \"/home/brian/.dotfiles\").nixosConfigurations.arcadia.options"))
;; lsp-nix-nixd-home-manager-options-expr "(builtins.getFlake \"/home/nb/nixos\").homeConfigurations.\"brian@arcadia\".options"))
;;;
;;;
;;; END_code
;;;
;;;
;;;
;;;
;;; BEGIN_General
;;;
;;;
;; Some functionality uses this to identify you, e.g. GPG configuration, email
;; clients, file templates and snippets.
(setq user-full-name "Brian McGillion"
user-mail-address "[email protected]")
;; TODO WTF is happening here ?? enable word-wrap (almost) everywhere
;;(+global-word-wrap-mode +1)
;; TODO re-enable??
;; this is anoying when format-on-save is enabled
;; but still a nice to have feature (though there are many times
;; files have not been saved)
;; Autosave files when switching buffers
;; (use-package! super-save
;; :config
;; (message "Super save enabled")
;; (setq auto-save-default nil)
;; (setq super-save-exclude '(".gpg" ".age"))
;; (super-save-mode +1))
(use-package! crux
:defer t)
(use-package! imenu-anywhere
:defer t)
;; Who remembers all the commands :)
(setq which-key-idle-delay 0.5)
;; Use a custom dictionary on linux
(if IS-MAC (setq ispell-dictionary "en_GB"))
;; (setq ispell-dictionary "en-custom"))
(set-language-environment-charset "UTF-8")
;; Use the Languagetool only in server mode
(setq langtool-http-server-host "localhost"
langtool-http-server-port 8081
langtool-default-language nil)
;; If a file changes on disk update the buffer to match
(global-auto-revert-mode t)
;; hopefully projectile auto finds the projects
;; M-x projectile-discover-projects-in-directory
;; M-x projectile-discover-projects-in-search-path
(setq projectile-project-search-path '(("~/.dotfiles" . 1)("~/projects" . 5)("~/.config" . 2)("~/Documents/org" . 2)))
;; TODO set this back to t
(setq projectile-auto-discover nil)
(after! license-snippets
(license-snippets-init))
;; TODO change this in dotfiles
(setq auth-sources '("~/.netrc"))
;;;
;;;
;;; END_General
;;;
;;;
;;;
;;;
;;; BEGIN_Interface_Tweaks
;;;
;;;
;; When starting a new frame make it maximized
(add-to-list 'initial-frame-alist '(fullscreen . fullboth))
(push '(fullscreen . fullboth) default-frame-alist)
;; Set your own banner to replace the default doom one "convert image.png
;; -resize 600 -quality 75 OUTPUT.png" try resize 400 for smaller resolutions
;; e.g. 1080p
(setq fancy-splash-image (concat doom-private-dir "banner/trancendent-gnu.png"))
;; Doom exposes five (optional) variables for controlling fonts in Doom. Here
;; are the three important ones:
;;
;; + `doom-font'
;; + `doom-variable-pitch-font'
;; + `doom-big-font' -- used for `doom-big-font-mode'; use this for
;; presentations or streaming.
;;
;; They all accept either a font-spec, font string ("Input Mono-12"), or xlfd
;; font string. You generally only need these two:
;;(setq doom-font (font-spec :family "monospace" :size 14))
(setq doom-font (font-spec :family "Fira Code" :size 13)
doom-variable-pitch-font (font-spec :family "Overpass")
doom-big-font (font-spec :family "Fira Code" :size 19))
;; There are two ways to load a theme. Both assume the theme is installed and
;; available. You can either set `doom-theme' or manually load a theme with the
;; `load-theme' function. This is the default:
(setq doom-theme 'doom-dracula)
;; This determines the style of line numbers in effect. If set to `nil', line
;; numbers are disabled. For relative line numbers, set this to `relative'.
(setq display-line-numbers-type t)
;; Blinking cursors are annoying
(blink-cursor-mode -1)
(setq +doom-dashboard-menu-sections
'(("Open org-agenda"
:icon (nerd-icons-octicon "nf-oct-calendar" :face 'doom-dashboard-menu-title)
:action bmg/switch-to-agenda)
("Recently opened files"
:icon (nerd-icons-faicon "nf-fa-file_text" :face 'doom-dashboard-menu-title)
:action recentf-open-files)
("Reload last session"
:icon (nerd-icons-octicon "nf-oct-history" :face 'doom-dashboard-menu-title)
:when (cond ((modulep! :ui workspaces)
(file-exists-p (expand-file-name persp-auto-save-fname persp-save-dir)))
((require 'desktop nil t)
(file-exists-p (desktop-full-file-name))))
:action doom/quickload-session)
("Open project"
:icon (nerd-icons-octicon "nf-oct-briefcase" :face 'doom-dashboard-menu-title)
:action projectile-switch-project)
("Open private configuration"
:icon (nerd-icons-octicon "nf-oct-tools" :face 'doom-dashboard-menu-title)
:when (file-directory-p doom-private-dir)
:action doom/open-private-config)
("Open documentation"
:icon (nerd-icons-octicon "nf-oct-book" :face 'doom-dashboard-menu-title)
:action doom/help)
;; ("Passwords"
;; :icon (icons-octicon "lock" :face 'font-lock-keyword-face)
;; :action pass)
;; ("RSS"
;; :icon (icons-octicon "rss" :face 'font-lock-keyword-face)
;; :action =rss)
))
(after! consult
(consult-customize
+default/search-project +default/search-other-project
+default/search-project-for-symbol-at-point
+default/search-cwd +default/search-other-cwd
+default/search-notes-for-symbol-at-point
+default/search-emacsd
:preview-key (list "C-SPC" :debounce 0.1 'any)))
;;;
;;;
;;; END_Interface_Tweaks
;;;
;;;
;;;
;;;
;;; BEGIN_Map
;;;
;;;
(map!
(;;:org-roam
:leader
(:prefix-map ("z" . "org-roam")
"c" #'org-roam-capture
"D" #'org-roam-demote-entire-buffer
"f" #'org-roam-node-find
"F" #'org-roam-ref-find
"g" #'org-roam-graph
"i" #'org-roam-node-insert
"I" #'org-id-get-create
"t" #'org-roam-buffer-toggle
"T" #'org-roam-buffer-display-dedicated
"r" #'org-roam-refile
"R" #'org-roam-link-replace-all
(:prefix ("d" . "by date")
:desc "Goto previous note" "b" #'org-roam-dailies-goto-previous-note
:desc "Goto date" "d" #'org-roam-dailies-goto-date
:desc "Capture date" "D" #'org-roam-dailies-capture-date
:desc "Goto next note" "f" #'org-roam-dailies-goto-next-note
:desc "Goto tomorrow" "m" #'org-roam-dailies-goto-tomorrow
:desc "Capture tomorrow" "M" #'org-roam-dailies-capture-tomorrow
:desc "Capture today" "n" #'org-roam-dailies-capture-today
:desc "Goto today" "t" #'org-roam-dailies-goto-today
:desc "Capture today" "T" #'org-roam-dailies-capture-today
:desc "Goto yesterday" "y" #'org-roam-dailies-goto-yesterday
:desc "Capture yesterday" "Y" #'org-roam-dailies-capture-yesterday
:desc "Find directory" "-" #'org-roam-dailies-find-directory)
(:prefix ("n" . "node properties")
"a" #'org-roam-alias-add
"A" #'org-roam-alias-remove
"t" #'org-roam-tag-add
"T" #'org-roam-tag-remove
"r" #'org-roam-ref-add
"R" #'org-roam-ref-remove)))
(;;: org-agenda
(:leader
;;; <leader> n --- notes
(:prefix-map ("n" . "notes")
:desc "Org agenda" "a" #'bmg/switch-to-agenda))
(:map org-agenda-mode-map
"i" #'org-agenda-clock-in
;;"r" #'bmg/org-process-inbox
"R" #'org-agenda-refile
"c" #'bmg/org-inbox-capture))
(;;: open submenu
(:leader
;;; <leader> o --- open
(:prefix-map ("o" . "open")
:desc "Url" "u" #'browse-url
:desc "Web" "w" #'browse-url)))
(;;: crux and stuff
(:leader
;;; <leader> b --- prelude
(:prefix-map ("b" . "prelude")
:desc "crux-cleanup-buffer-or-region" "c" #'crux-cleanup-buffer-or-region
:desc "crux-duplicate-current-line-or-region" "d" #'crux-duplicate-current-line-or-region
:desc "crux-delete-file-and-buffer" "D" #'crux-delete-file-and-buffer
:desc "crux-kill-other-buffers" "k" #'crux-kill-other-buffers
:desc "crux-open-with" "o" #'crux-open-with
:desc "crux-rename-buffer-and-file" "r" #'crux-rename-buffer-and-file
:desc "crux-transpose-windows" "s" #'crux-transpose-windows
:desc "crux-view-url" "u" #'crux-view-url
:desc "crux-indent-defun" "TAB" #'crux-indent-defun)))
) ;; END MAP
(map! :map dirvish-mode-map
;; left click for expand/collapse dir or open file
"<mouse-1>" #'dirvish-subtree-toggle-or-open
;; middle click for opening file / entering dir in other window
"<mouse-2>" #'dired-mouse-find-file-other-window
;; right click for opening file / entering dir
"<mouse-3>" #'dired-mouse-find-file
"?" #'dirvish-dispatch
"q" #'dirvish-quit
"b" #'dirvish-quick-access
"f" #'dirvish-file-info-menu
"p" #'dirvish-yank
"S" #'dirvish-quicksort
"F" #'dirvish-layout-toggle
"z" #'dirvish-history-jump
"TAB" #'dirvish-subtree-toggle
"M-b" #'dirvish-history-go-backward
"M-f" #'dirvish-history-go-forward
"M-n" #'dirvish-narrow
"M-m" #'dirvish-mark-menu
"M-s" #'dirvish-setup-menu
"M-e" #'dirvish-emerge-menu
(:prefix ("y" . "yank")
"l" #'dirvish-copy-file-true-path
"n" #'dirvish-copy-file-name
"p" #'dirvish-copy-file-path
"r" #'dirvish-copy-remote-path
"y" #'dired-do-copy)
(:prefix ("s" . "symlinks")
"s" #'dirvish-symlink
"S" #'dirvish-relative-symlink
"h" #'dirvish-hardlink))
;
;;;
;;;
;;; END_MAP
;;;
;;;
;;;
;;;
;;; BEGIN_ORG
;;;
;;;
;; If you use `org' and don't want your org files in the default location below,
;; change `org-directory'. It must be set before org loads!
(setq! org-directory "~/Documents/org/"
org-ellipsis " ▾ "
org-startup-folded t
org-src-fontify-natively t
org-hide-emphasis-markers t)
(defvar my-roam-dir (concat org-directory "roam/"))
(setq! org-noter-notes-search-path my-roam-dir)
(setq! citar-bibliography (concat org-directory "emacs_lit.bib")
citar-library-paths '("~/Documents/Papers/")
citar-notes-paths my-roam-dir)
;; TODO turn on autosync
;;(org-roam-db-autosync-mode)
(setq org-roam-directory (file-truename my-roam-dir)
org-id-link-to-org-use-id t
org-roam-extract-new-file-path "${slug}.org"
)
;; TODO Why can I not use add-to-list for this
(setq org-roam-capture-templates
'(("d" "default" plain
"%?"
:if-new (file+head "${slug}.org"
"#+title: ${title}\n#+created: %u\n#+last_modified: %U\n\n - related :: ")
:unnarrowed t)))
;; TODO is this still supported
(setq org-roam-capture-ref-templates
'(("r" "ref" plain
"%?"
:if-new (file+head "${slug}.org"
"#+title: ${title}\n#+roam_key: ${ref}\n#+created: %u\n#+last_modified: %U\n\n - related :: ")
:unnarrowed t)))
(use-package! websocket
:after org-roam)
(use-package! org-roam-ui
:after org-roam
:commands (org-roam-ui-mode))
(use-package! org-appear ; better markup edit
:hook (org-mode . org-appear-mode))
;;;
;;;
;;; END_ORG
;;;
;;;
;;;
;;;
;;; BEGIN_ORG_CAPTURE
;;;
;;;
(setq org-default-notes-file (expand-file-name (format "inbox-%s.org" (system-name)) my-roam-dir))
(setq +org-capture-todo-file org-default-notes-file
+org-capture-notes-file org-default-notes-file
+org-capture-projects-file org-default-notes-file)
(setq org-log-done 'time
org-log-into-drawer t
org-log-state-notes-insert-after-drawers nil)
;; (after! org
;; (add-to-list 'org-capture-templates
;; '(("r" "Review Templates for use with GTD")
;; ("rm" "Review Morning" entry
;; (file+headline org-archive-location "Review")
;; (file "~/Documents/org/morning_template.org"))
;; ("re" "Review Evening" entry
;; (file+headline org-archive-location "Review")
;; (file "~/Documents/org/evening_template.org"))
;; ("rw" "Review Weekly" entry
;; (file+headline org-archive-location "Review")
;; (file "~/Documents/org/weekly_template.org")))))
;;;
;;;
;;; END_ORG_Capture
;;;
;;;
;;;
;;;
;;; BEGIN_ORG_GTD
;;;
;;;
;;(setq bmg/org-agenda-directory (concat org-directory "/gtd/"))
(setq org-archive-location (concat org-directory "/archive.org_archive::datetree/"))
(after! org
;; The 'bmg-org-roam-agenda' tag is used to tell vulpea that there is a todo item in this file
(add-to-list 'org-tags-exclude-from-inheritance "bmg-org-roam-agenda"))
(setq org-tag-alist '((:startgroup . nil)
("@Project" . ?p)
("@Reading" . ?r)
("@Someday" . ?s)
("@Training" . ?t)
("uni" . ?u)
("@Research" . ?R)
("Emacs" . ?e)
("@Issue" . ?i)
("Important" . ?I)
(:endgroup . nil)
(:startgroup . nil)
("PERSONAL" . ?P)
(:endgroup . nil)))
(use-package! vulpea
:after (org-agenda org-roam)
:commands (bmg/vulpea-agenda-files-update bmg/vulpea-project-update-tag)
:init
(add-hook 'find-file-hook #'bmg/vulpea-project-update-tag)
(add-hook 'before-save-hook #'bmg/vulpea-project-update-tag)
(advice-add 'org-agenda :before #'bmg/vulpea-agenda-files-update)
:hook ((org-roam-db-autosync-mode . vulpea-db-autosync-enable))
:config
(defun bmg/vulpea-project-p ()
"Return non-nil if current buffer has any todo entry.
TODO entries marked as done are ignored, meaning the this
function returns nil if current buffer contains only completed
tasks."
(seq-find ; (3)
(lambda (type)
(eq type 'todo))
(org-element-map ; (2)
(org-element-parse-buffer 'headline) ; (1)
'headline
(lambda (h)
(org-element-property :todo-type h)))))
(defun bmg/vulpea-project-update-tag ()
"Update PROJECT tag in the current buffer."
(when (and (not (active-minibuffer-window))
(bmg/vulpea-buffer-p))
(save-excursion
(goto-char (point-min))
(let* ((tags (vulpea-buffer-tags-get))
(original-tags tags))
(if (bmg/vulpea-project-p)
(setq tags (cons "bmg-org-roam-agenda" tags))
(setq tags (remove "bmg-org-roam-agenda" tags)))
;; cleanup duplicates
(setq tags (seq-uniq tags))
;; update tags if changed
(when (or (seq-difference tags original-tags)
(seq-difference original-tags tags))
(apply #'vulpea-buffer-tags-set tags))))))
(defun bmg/vulpea-buffer-p ()
"Return non-nil if the currently visited buffer is a note."
(and buffer-file-name
(string-prefix-p
(expand-file-name (file-name-as-directory org-roam-directory))
(file-name-directory buffer-file-name))))
(defun bmg/vulpea-project-files ()
"Return a list of note files containing 'project' tag." ;
(seq-uniq
(seq-map
#'car
(org-roam-db-query
[:select [nodes:file]
:from tags
:left-join nodes
:on (= tags:node-id nodes:id)
:where (like tag (quote "%\"bmg-org-roam-agenda\"%"))]))))
(defun bmg/vulpea-agenda-files-update (&rest _)
"Update the value of `org-agenda-files'."
(setq org-agenda-files (bmg/vulpea-project-files)))
(defun bmg/vulpea-agenda-category (&optional len)
"Get category of item at point for agenda.
Category is defined by one of the following items:
- CATEGORY property
- TITLE keyword
- TITLE property
- filename without directory and extension
When LEN is a number, resulting string is padded right with
spaces and then truncated with ... on the right if result is
longer than LEN.
Usage example:
(setq org-agenda-prefix-format
'((agenda . \" %(vulpea-agenda-category) %?-12t %12s\")))
Refer to `org-agenda-prefix-format' for more information."
(let* ((file-name (when buffer-file-name
(file-name-sans-extension
(file-name-nondirectory buffer-file-name))))
(title (vulpea-buffer-prop-get "title"))
(category (org-get-category))
(result
(or (if (and
title
(string-equal category file-name))
title
category)
"")))
(if (numberp len)
(s-truncate len (s-pad-right len " " result))
result))))
(use-package! org-super-agenda
:after org-agenda
:init
(setq org-agenda-prefix-format
'((agenda . " %i %(bmg/vulpea-agenda-category 12)%?-12t% s")
(todo . " %i %(bmg/vulpea-agenda-category 12) ")
(tags . " %i %(bmg/vulpea-agenda-category 12) ")
(search . " %i %(bmg/vaulpea-agenda-category 12) ")))
(setq org-agenda-time-grid '((daily today require-timed)
(800 1200 1600 2000)
"......"
"----------------")
org-agenda-skip-scheduled-if-done t
org-agenda-skip-deadline-if-done t
org-agenda-include-deadlines t
org-agenda-include-diary nil
org-agenda-block-separator nil
org-agenda-compact-blocks t
org-agenda-start-with-log-mode t
org-agenda-start-day nil) ;; i.e. today
;;TODO fix the sections so that the match the todo-list (lang/org/config.el)
(setq org-agenda-custom-commands
'(("o" "Overview"
((agenda "" ((org-agenda-span 'week)
(org-agenda-start-on-weekday 0) ;; Sunday
(org-super-agenda-groups
'((:name "Today"
:time-grid t
:date today
:todo "TODAY"
:scheduled today
:order 1)))))
(alltodo "" ((org-agenda-overriding-header "")
(org-super-agenda-groups
'((:name "To Refile"
:tag ("REFILE" "IDEA" "DONE" "KILL")
:order 1)
(:name "Next to do"
:todo "NEXT"
:tag "NEXT"
:order 3)
(:name "Ongoing"
:todo "STRT"
:order 3)
(:name "Recurring"
:todo "LOOP"
:order 4)
(:name "Personal"
:tag "PERSONAL"
:order 12)
(:name "Important"
:tag "Important"
:priority "A"
:order 6)
(:name "Due Today"
:deadline today
:order 2)
(:name "Due Soon"
:deadline future
:order 8)
(:name "Overdue"
:deadline past
:face error
:order 7)
(:name "Issues"
:tag "@Issue"
:order 12)
(:name "Emacs"
:tag "Emacs"
:order 13)
(:name "Projects"
:todo "PROJ"
:tag "@Project"
:order 14)
(:name "Research"
:tag "@Research"
:order 15)
(:name "To read"
:tag "@Reading"
:order 30)
(:name "Waiting"
:todo "HOLD"
:todo "WAIT"
:order 20)
(:name "University"
:tag "uni"
:order 32)
(:name "Someday"
:priority<= "C"
:tag "@Someday"
:todo "SOMEDAY"
:order 90)
(:discard (:tag ("Chore" "Routine" "Daily")))))))))))
:config
(org-super-agenda-mode))
;; Moved outside the use-package! agenda so it shows on the home screen
(defun bmg/switch-to-agenda ()
(interactive)
(org-agenda nil "o"))
;;;
;;;
;;; END_ORG_GTD
;;;
;;;