395 lines
14 KiB
Org Mode
395 lines
14 KiB
Org Mode
* Emacs litterate config file
|
|
I am using straight as the backend for use package and have thusly set it in
|
|
[./early-init.el]
|
|
** Overrides
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(setq custom-file (locate-user-emacs-file "custom-vars.el"))
|
|
(load custom-file 'noerror 'nomessage)
|
|
(setq global-auto-revert-non-file-buffers 't)
|
|
(setq evil-want-keybinding nil)
|
|
#+end_src
|
|
** Evil Mode
|
|
*** Undo-Tree
|
|
evil mode requires undo-tree so I have it set to compress the undo files
|
|
and enable undo-tree mode globally
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(use-package undo-tree :config
|
|
(global-undo-tree-mode)
|
|
(setq undo-tree-auto-save-history t)
|
|
(defadvice undo-tree-make-history-save-filename
|
|
(after undo-tree activate)
|
|
(setq ad-return-value (concat ad-return-value ".gz"))))
|
|
#+end_src
|
|
|
|
*** goto-chg
|
|
It also requires goto-chg
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(use-package goto-chg)
|
|
#+end_src
|
|
*** Evil Mode
|
|
Now I hook in Evil mode
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(use-package evil :config
|
|
(evil-mode 1)
|
|
(setq evil-search-module 'evil-search)
|
|
(setq evil-shift-width 2)
|
|
(setq evil-split-window-below 't)
|
|
(setq evil-vsplit-window-right 't)
|
|
(setq show-paren-mode 't)
|
|
(setq evil-undo-system 'undo-tree))
|
|
(evil-set-leader '(normal visual motion) (kbd "SPC"))
|
|
(evil-define-key 'normal 'global
|
|
(kbd "<leader>f f") 'file-file
|
|
(kbd "<leader>f s") 'save-buffer
|
|
(kbd "<leader>f r") 'recentf-open-files
|
|
(kbd "<leader>e e") 'eval-buffer)
|
|
#+end_src
|
|
*** Evil Collection
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(use-package evil-collection :after evil
|
|
:ensure t
|
|
:config
|
|
(evil-collection-init))
|
|
(use-package evil-org :after org
|
|
:ensure t
|
|
:hook (org-mode . (lambda () evil-org-mode))
|
|
:config
|
|
(require 'evil-org-agenda)
|
|
(evil-org-agenda-set-keys)
|
|
(setf evil-org-key-theme '(navigation insert textobjects additional))
|
|
(setf org-special-ctrl-a/e t))
|
|
#+end_src
|
|
|
|
** UI
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(use-package treemacs :config
|
|
(evil-define-key 'normal 'global (kbd "<leader> f e") 'treemacs))
|
|
#+end_src
|
|
Enable which key mode
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(which-key-mode)
|
|
#+end_src
|
|
** Theming
|
|
*** Fonts / icons
|
|
Icons must be installed 'all-the-icons-install
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(use-package all-the-icons
|
|
:if (display-graphic-p))
|
|
(use-package nerd-icons
|
|
:if (display-graphic-p))
|
|
(use-package rainbow-delimiters :hook (prog-mode . rainbow-delimiters-mode))
|
|
#+end_src
|
|
*** UI System
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(require 'recentf)
|
|
(recentf-mode 1)
|
|
(setq history-length 50)
|
|
(savehist-mode 1)
|
|
(setq recentf-max-menu-items 25)
|
|
(save-place-mode 1)
|
|
(menu-bar-mode 1)
|
|
(tool-bar-mode 1)
|
|
(scroll-bar-mode -1)
|
|
(global-display-line-numbers-mode 1)
|
|
(hl-line-mode 1)
|
|
(blink-cursor-mode 1)
|
|
#+end_src
|
|
*** Color Scheme -> load-theme here
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(use-package doom-themes
|
|
:ensure t
|
|
:config
|
|
;; Global settings (defaults)
|
|
(setq doom-themes-enable-bold t ; if nil, bold is universally disabled
|
|
doom-themes-enable-italic t) ; if nil, italics is universally disabled
|
|
(load-theme 'doom-tokyo-night t)
|
|
(doom-themes-visual-bell-config)
|
|
(doom-themes-neotree-config)
|
|
(setq doom-themes-treemacs-theme "doom-tokyo-night") ; use "doom-colors" for less minimal icon theme
|
|
(doom-themes-treemacs-config)
|
|
;; Corrects (and improves) org-mode's native fontification.
|
|
(doom-themes-org-config))
|
|
#+end_src
|
|
** Utilities
|
|
*** Lsp's
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(use-package lsp-mode
|
|
:init
|
|
(setq lsp-keymap-prefix "C-c l")
|
|
:hook(
|
|
(python-mode . lsp)
|
|
(js-mode . lsp)
|
|
(typescript . lsp)
|
|
(rust-mode . lsp)
|
|
(lsp-mode . lsp-enable-which-key-integration)
|
|
(zig-mode . lsp)
|
|
(nim-mode . lsp)
|
|
)
|
|
:commands lsp)
|
|
|
|
;; Tree-sitter grammars are provided by NixOS packages instead of runtime compilation
|
|
#+end_src
|
|
*** Completion
|
|
**** counsel
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(use-package counsel :config (counsel-mode))
|
|
(use-package swiper)
|
|
(use-package ivy :config
|
|
(ivy-mode)
|
|
(setq ivy-use-virtual-buffers 't)
|
|
(setq enable-recursive-minibuffers 't)
|
|
(global-set-key "\C-s" 'swiper-isearch)
|
|
(global-set-key (kbd "C-c C-r") 'ivy-resume)
|
|
(global-set-key (kbd "M-x") 'counsel-M-x)
|
|
(global-set-key (kbd "C-x C-f") 'counsel-find-file)
|
|
(global-set-key (kbd "<f1> f") 'counsel-describe-function)
|
|
(global-set-key (kbd "<f1> v") 'counsel-describe-variable)
|
|
(global-set-key (kbd "<f1> o") 'counsel-describe-symbol)
|
|
(global-set-key (kbd "<f1> l") 'counsel-find-library)
|
|
(global-set-key (kbd "<f1> i") 'counsel-info-lookup-symbol)
|
|
(global-set-key (kbd "<f1> u") 'counsel-unicode-char)
|
|
(global-set-key (kbd "C-c g") 'counsel-git)
|
|
(global-set-key (kbd "C-c j") 'counsel-git-grep)
|
|
(global-set-key (kbd "C-c k") 'counsel-ag)
|
|
(global-set-key (kbd "C-x l") 'counsel-locate)
|
|
(global-set-key (kbd "C-S-o") 'counsel-rhythmbox)
|
|
(define-key minibuffer-local-map (kbd "C-r") 'counsel-minibuffer-history))
|
|
(use-package all-the-icons-ivy-rich
|
|
:ensure t
|
|
:init (all-the-icons-ivy-rich-mode 1))
|
|
|
|
(use-package ivy-rich
|
|
:ensure t
|
|
:init (ivy-rich-mode 1))
|
|
#+end_src
|
|
**** helpful
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(use-package helpful
|
|
:config
|
|
(global-set-key (kbd "C-h f") #'helpful-callable)
|
|
(global-set-key (kbd "C-h v") #'helpful-variable)
|
|
(global-set-key (kbd "C-h k") #'helpful-key)
|
|
(global-set-key (kbd "C-h x") #'helpful-command)
|
|
(global-set-key (kbd "C-c C-S-d") #'helpful-at-point))
|
|
#+end_src
|
|
** Org Mode
|
|
*** Org Roam
|
|
Presents a good example of use-package's capabilities.
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(use-package org-roam :ensure t :after org :custom (org-roam-directory "~/org/roam") :bind
|
|
(("C-c n l" . org-roam-buffer-toggle)
|
|
("C-c n f" . org-roam-node-find)
|
|
("C-c n i" . org-roam-node-insert)
|
|
:map org-mode-map
|
|
("C-M-i" . completion-at-point))
|
|
:init (setq org-roam-v2-ack t)
|
|
:config
|
|
(org-roam-setup))
|
|
(setq org-roam-node-display-template
|
|
(concat "${title:*} "
|
|
(propertize "${tags:10}" 'face 'org-tag)))
|
|
(setq org-roam-database-connector 'sqlite-builtin)
|
|
#+end_src
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(setq org-roam-capture-templates
|
|
'(("d" "default" plain
|
|
"%?"
|
|
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
|
|
:unnarrowed t)
|
|
("l" "programming language" plain
|
|
"* Characteristics\n\n- Family: %?\n- Inspired by: \n\n*Reference:\n\n"
|
|
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
|
|
:unnarrowed t)
|
|
("b" "book notes" plain
|
|
"\n* Source\n\nAuthor: %^{Author}\nTitle: ${title}\nYear: %^{Year}\n\n* Summary\n\n%?"
|
|
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
|
|
:unnarrowed t)
|
|
("p" "project" plain "* Goals\n\n%?\n\n* Tasks\n\n** TODO Add initial tasks\n\n* Dates\n\n"
|
|
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+filetags: Project")
|
|
:unnarrowed t)))
|
|
#+end_src
|
|
**** Capture Templates
|
|
#+begin_src emacs-lisp :tangle yes
|
|
#+end_src
|
|
*** Org Agenda
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(setq org-columns-default-format "%50ITEM(Task) %10CLOCKSUM %16TIMESTAMP_IA")
|
|
#+end_src
|
|
*** Capture Templates
|
|
**** Agenda Related
|
|
:PROPERTIES:
|
|
:ID: e81c993e-995d-492f-af46-73928c0a4fbd
|
|
:END:
|
|
[https://d12frosted.io/posts/2020-06-23-task-management-with-roam-vol1.html]
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(setq org-capture-templates
|
|
'(("t" "todo" entry (file org-default-notes-file)
|
|
"* TODO %?\n%u\n%a\n" :clock-in t :clock-resume t)
|
|
("m" "Meeting" entry (file org-default-notes-file)
|
|
"* MEETING with %? :MEETING:\n%t" :clock-in t :clock-resume t)
|
|
("d" "Diary" entry (file+datetree "~/org/diary.org")
|
|
"* %?\n%U\n" :clock-in t :clock-resume t)
|
|
("i" "Idea" entry (file org-default-notes-file)
|
|
"* %? :IDEA: \n%t" :clock-in t :clock-resume t)
|
|
("n" "Next Task" entry (file+headline org-default-notes-file "Tasks")
|
|
"** NEXT %? \nDEADLINE: %t") ))
|
|
#+end_src
|
|
#+begin_src emacs-lisp :tangle yes
|
|
(setq org-agenda-prefix-format
|
|
'((agenda . " %i %-12(vulpea-agenda-category)%?-12t% s")
|
|
(todo . " %i %-12(vulpea-agenda-category) ")
|
|
(tags . " %i %-12(vulpea-agenda-category) ")
|
|
(search . " %i %-12(vulpea-agenda-category) ")))
|
|
|
|
(defun vulpea-agenda-category ()
|
|
"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
|
|
|
|
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)))
|
|
(or (if (and
|
|
title
|
|
(string-equal category file-name))
|
|
title
|
|
category)
|
|
"")))
|
|
(defun vulpea-buffer-prop-get (name)
|
|
"Get a buffer property called NAME as a string."
|
|
(org-with-point-at 1
|
|
(when (re-search-forward (concat "^#\\+" name ": \\(.*\\)")
|
|
(point-max) t)
|
|
(buffer-substring-no-properties
|
|
(match-beginning 1)
|
|
(match-end 1)))))
|
|
(setq org-agenda-prefix-format
|
|
'((agenda . " %i %(vulpea-agenda-category 12)%?-12t% s")
|
|
(todo . " %i %(vulpea-agenda-category 12) ")
|
|
(tags . " %i %(vulpea-agenda-category 12) ")
|
|
(search . " %i %(vulpea-agenda-category 12) ")))
|
|
|
|
(defun 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)))
|
|
(defun vulpea-ensure-filetag ()
|
|
"Add respective file tag if it's missing in the current note."
|
|
(interactive)
|
|
(let ((tags (vulpea-buffer-tags-get))
|
|
(tag (vulpea--title-as-tag)))
|
|
(when (and (seq-contains-p tags "people")
|
|
(not (seq-contains-p tags tag)))
|
|
(vulpea-buffer-tags-add tag))))
|
|
|
|
(defun vulpea--title-as-tag ()
|
|
"Return title of the current note as tag."
|
|
(vulpea--title-to-tag (vulpea-buffer-title-get)))
|
|
|
|
(defun vulpea--title-to-tag (title)
|
|
"Convert TITLE to tag."
|
|
(concat "@" (s-replace " " "" title)))
|
|
(defun vulpea-tags-add ()
|
|
"Add a tag to current note."
|
|
(interactive)
|
|
;; since https://github.com/org-roam/org-roam/pull/1515
|
|
;; `org-roam-tag-add' returns added tag, we could avoid reading tags
|
|
;; in `vulpea-ensure-filetag', but this way it can be used in
|
|
;; different contexts while having simple implementation.
|
|
(when (call-interactively #'org-roam-tag-add)
|
|
(vulpea-ensure-filetag)))
|
|
|
|
(defun org-roam-node-insert-wrapper (fn)
|
|
"Insert a link to the note using FN.
|
|
|
|
If inserted node has PEOPLE tag on it, tag the current outline
|
|
accordingly."
|
|
(interactive)
|
|
(when-let*
|
|
((node (funcall fn))
|
|
(title (org-roam-node-title node))
|
|
(tags (org-roam-node-tags node)))
|
|
(when (seq-contains-p tags "people")
|
|
(save-excursion
|
|
(ignore-errors
|
|
(org-back-to-heading)
|
|
(org-set-tags
|
|
(seq-uniq
|
|
(cons
|
|
(vulpea--title-to-tag title)
|
|
(org-get-tags nil t)))))))))
|
|
|
|
(advice-add
|
|
#'org-roam-node-insert
|
|
:around
|
|
#'org-roam-node-insert-wrapper)
|
|
|
|
(defun my-vulpea-insert-handle (note)
|
|
"Hook to be called on NOTE after `vulpea-insert'."
|
|
(when-let* ((title (vulpea-note-title note))
|
|
(tags (vulpea-note-tags note)))
|
|
(when (seq-contains-p tags "people")
|
|
(save-excursion
|
|
(ignore-errors
|
|
(org-back-to-heading)
|
|
(when (eq 'todo (org-element-property
|
|
:todo-type
|
|
(org-element-at-point)))
|
|
(org-set-tags
|
|
(seq-uniq
|
|
(cons
|
|
(vulpea--title-to-tag title)
|
|
(org-get-tags nil t))))))))))
|
|
|
|
(defun vulpea--title-to-tag (title)
|
|
"Convert TITLE to tag."
|
|
(concat "@" (s-replace " " "" title)))
|
|
|
|
(add-hook 'vulpea-insert-handle-functions
|
|
#'my-vulpea-insert-handle)
|
|
#+end_src
|