This is a bit of fumbling to try and get this all to work on a new computer from zero with minimal manual intervention.
(package-initialize)
(when (not package-archive-contents)
(package-refresh-contents))
(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)
(unless (package-installed-p 'use-package)
(package-install 'use-package))
(eval-when-compile
(require 'use-package))
Make use package always install if package is not installed.
(setq use-package-always-ensure t)
Ubuntu specific (hopefully this doesn’t break mac!) - this forces org to update to a later version.
(use-package org :ensure org-contrib :pin org)
This brings back the old “<s” shortcut for source blocks. Unfortunately it has different casing than before, but that’s not worth the time to fix (probably easy though).
(require 'org-tempo)
Because I am a vim user at heart.
Remove evil C-i binding so tab works.
(setq evil-want-C-i-jump nil)
See Evil jumplist remapping for where the rebind happens.
Set up org bindings first. Honestly not sure if this needs to come before use evil, but not worth figuring out.
(use-package evil-org
:ensure t
:after org
:hook (org-mode . (lambda () evil-org-mode))
:config
(require 'evil-org-agenda)
(evil-org-agenda-set-keys))
(use-package evil)
(evil-mode 1)
Change cursor to a bar in insert mode.
(use-package evil-terminal-cursor-changer)
(unless (display-graphic-p)
(require 'evil-terminal-cursor-changer)
(evil-terminal-cursor-changer-activate) ; or (etcc-on)
)
(setq evil-default-cursor (quote (t "#750000"))
evil-visual-state-cursor '("#880000" box)
evil-normal-state-cursor '("#750000" box)
evil-insert-state-cursor '("#e2e222" bar)
)
(use-package evil-surround
:ensure t
:config
(global-evil-surround-mode 1))
(use-package evil-easymotion)
(evilem-default-keybindings "SPC")
(use-package find-lisp)
Doesn’t quite work yet - Maybe I’ll get it going some day.
;; (use-package smartparens)
;; (use-package evil-smartparens)
;; (add-hook 'smartparens-enabled-hook #'evil-smartparens-mode)
Definitely pronounced “muh git”, much like “muh queen”. Certainly not “mahjit”, despite what the top hat and wand would make you think.
(use-package magit)
Get keybindings for evil in magit mode. Not sure what else evil-collection has, but some day I want to move this elsewhere if it’s spanning across other modes.
(use-package evil-collection)
(evil-collection-init 'magit)
To work with github
;;(use-package forge
;;:after magit)
I could have sworn I had this installed at one point, but oh well!
(use-package undo-tree)
(global-undo-tree-mode)
(global-set-key (kbd "C-x C-u") 'undo-tree-visualize)
(define-key evil-ex-map "xu" 'undo-tree-visualize)
Force undo tree files into local emacs d.
(setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo")))
All the other deps with the funked up deps
(use-package f)
(use-package s)
(use-package dash)
(use-package helm-org-rifle)
Much of this I just followed this guide while trying to configure Roam Smart parents
(use-package smartparens)
(smartparens-global-mode t)
Company
(use-package company)
(add-hook 'after-init-hook 'global-company-mode)
(setq company-minimum-prefix-length 2)
(setq company-idle-delay 0.25)
(add-to-list 'company-backends 'company-capf)
Completion config
(setq completion-ignore-case t)
(use-package helm
:ensure t)
(setq helm-split-window-in-side-p t
helm-move-to-line-cycle-in-source t)
(helm-mode 1)
Doesn’t quite work yet - I’m trying to get it so that I can fuzzy match in helm-apropos, but despite what the internet says it is not working.
;; (use-package helm-fuzzier)
;; (helm-fuzzier-mode 1)
Not using k8s a ton day to day, but a magit-like k8s buffer seems great. Going to mess around with it.
(use-package kubernetes)
(use-package kubernetes-evil
:ensure t
:after kubernetes)
(fset 'k8s 'kubernetes-overview)
Variables - org agenda files, which will some day pull dates, but are also used for how things refile. I exclude archive.org from this list because it’s huge.
(defun es/fourteen-days-ago-month ()
"Lookback fourteen days ago, and format that month as YYYY-MM."
(format-time-string "%Y-%m" (time-add (current-time) (seconds-to-time -1209600)))
;; debug - make this look back more to see if anything is straggling
;; (format-time-string "%Y-%m" (time-add (current-time) (seconds-to-time -2409600)))
)
(defun es/current-month ()
"Get current month as YYYY-MM."
(format-time-string "%Y-%m" (current-time))
)
(defun es/set-org-agenda-files () (interactive)
(if es/no-work-agenda
(es/set-no-work-org-agenda-files)
(es/set-work-org-agenda-files)
)
)
(defun es/set-work-org-agenda-files () (interactive)
"Define my org agenda files"
(custom-set-variables
'(org-agenda-files
(append
(cl-remove-if (lambda (k) (string-match-p "archive.org" k))
(find-lisp-find-files "~/Dropbox/org/projects/" "\.org$"))
(cl-remove-if (lambda (k) (string-match-p "_done.org" k))
(find-lisp-find-files "~/org/projects/" "\.org$"))
(cl-remove-if (lambda (k) (not (or
(string-match-p (es/current-month) k)
(string-match-p (es/fourteen-days-ago-month) k))))
(find-lisp-find-files "~/org/roam/daily" "\.org$"))
(cl-remove-if (lambda (k) (not (string-match-p "inbox.org" k)))
(find-lisp-find-files "~/Dropbox/org" "\.org$"))
(cl-remove-if (lambda (k) (not (or
(string-match-p (es/current-month) k)
(string-match-p (es/fourteen-days-ago-month) k))))
(find-lisp-find-files "~/Dropbox/org/roam/daily/" "\.org$"))
)
)))
(defun es/set-nw-agenda () (interactive)
(setq es/no-work-agenda t)
)
(defun es/set-yw-agenda () (interactive)
(setq es/no-work-agenda nil)
)
(defun es/set-no-work-org-agenda-files () (interactive)
"Define just personal agenda files"
(custom-set-variables
'(org-agenda-files
(append
(cl-remove-if (lambda (k) (string-match-p "archive.org" k))
(find-lisp-find-files "~/Dropbox/org/projects/" "\.org$"))
(cl-remove-if (lambda (k) (not (string-match-p "inbox.org" k)))
(find-lisp-find-files "~/Dropbox/org" "\.org$"))
(cl-remove-if (lambda (k) (not (or
(string-match-p (es/current-month) k)
(string-match-p (es/fourteen-days-ago-month) k))))
(find-lisp-find-files "~/Dropbox/org/roam/daily/" "\.org$"))
)
)))
(es/set-yw-agenda)
Start with bullets folded and indented by default.
(setq org-startup-indented t)
(setq org-startup-folded t)
No clue what custom-set-faces is to be honest.
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)
;; Package-Requires: ((dash "2.13.0"))
;; (add-to-list 'load-path "~/.emacs.d/vendor/emacs-powerline")
;; (require 'powerline)
;; (require 'cl)
Refile config. I found this on reddit, but I think this says “take the stuff from org-agenda-files and go one N levels deep in the trees to find targets”. It works.
(setq org-refile-targets '((nil :maxlevel . 1)
(org-agenda-files :maxlevel . 3)
("~/Dropbox/org/projects/stuff.org" :maxlevel . 1)
("~/Dropbox/org/projects/financeMath.org" :maxlevel . 2)
("~/Dropbox/org/projects/tList.org" :maxlevel . 1)
("~/code/dotfiles/fish/fishProfile.org" :maxlevel . 3)
("~/code/dotfiles/bashProfile.org" :maxlevel . 3)))
(setq org-refile-use-outline-path 'file)
(setq org-refile-allow-creating-parent-nodes 'confirm)
Adding sh (bash) to babel languages so I can tangle my bash profile.
(org-babel-do-load-languages 'org-babel-load-languages
'(
(shell . t)
)
)
(setq org-babel-default-header-args:bash '((:tangle . "yes")))
Ongoing thing to figure out what states I want. log-done enables timestamp and prompts for a note. Archive location is what you’d expect.
More details Here
(setq org-todo-keywords
'((sequence "TODO(t)" "SOMEDAY(s)" "WAITING(w)" "IN-PROGRESS(i)" "BLOCKED(l)" "|" "DONE(d)" "EXPORTED(e)" "OBSOLOTE(b)" "DELEGATED(g)")))
(setq org-log-done 'time)
;;(setq org-log-done 'note)
(setq org-archive-location "~/Dropbox/org/projects/archive.org::")
Custom priorities
(setq org-lowest-priority 74)
Make checkbox/todo tracking recursive so I see everything under the subtree
(setq org-hierarchical-todo-statistics t)
Column view in org-agenda
(setq org-columns-default-format-for-agenda "%80ITEM(Task) %4PRIORITY(Priority) %10TODO(Todo Status) %17Effort(Estimated Effort){:} %CLOCKSUM(Time Spent)")
Define a custom tiebreaker for priority - I basically want A on par with within 1 day, B on par with within 2 days, etc.
(setq org-agenda-cmp-user-defined (lambda (a b) (message (org-get-priority a))))
Only one change from the default strategy, which is to use effort-up. The ordering on agenda is now “high priority first, low effort first, respect order of org-agenda-files”. I think the fact that all my things in “recurring.org” are habits sort of circuvents “habit-down”. But I don’t mind for now.
(setq org-agenda-sorting-strategy
'((agenda user-defined-up todo-state-down habit-down time-up priority-down effort-up category-keep)
(todo priority-down category-keep)
(tags priority-down category-keep)
(search category-keep)))
Org agenda todo - filter out things with dates so I schedule any dangling todos. Apparently I need all of these set - I tend to just slap dates on stuff so it’ll show on the agenda, which is good enough for me.
(setq org-agenda-todo-ignore-scheduled "all")
(setq org-agenda-todo-ignore-deadlines "all")
(setq org-agenda-todo-ignore-timestamp "all")
(setq org-agenda-todo-ignore-with-date "all")
(setq org-agenda-tags-todo-honor-ignore-options t)
Just a command to bring up agenda view
(define-key global-map "\C-ca" 'org-agenda)
(use-package org-super-agenda)
(setq org-super-agenda-keep-order t)
(org-super-agenda-mode 1)
(setq org-super-agenda-groups
'(;; Each group has an implicit boolean OR operator between its selectors.
(:name "Inbox"
:tag "inbox"
)
(:name "Habits Overdue"
:and(:file-path "recurring.org" :deadline past :not(:tag "eodroutine"))
:and(:file-path "recurring.org" :scheduled past :not(:tag "eodroutine"))
)
(:name "Habits Today"
:and(:file-path "recurring.org" :deadline today :not(:tag "eodroutine"))
:and(:file-path "recurring.org" :scheduled today :not(:tag "eodroutine"))
)
(:name "Personal - IN-PROGRESS"
;; Single arguments given alone
:and (:todo ("IN-PROGRESS") :file-path "Dropbox"))
(:name "Important - Personal"
;; Single arguments given alone
:and (:priority "A" :todo ("TODO" "IN-PROGRESS" "SOMEDAY") :file-path "Dropbox"))
(:name "Work - IN-PROGRESS"
;; Single arguments given alone
:and (:todo ("IN-PROGRESS") :file-path "Drive")
:and (:todo ("IN-PROGRESS") :file-path "work.org"))
(:name "Work Stuck"
;; Single arguments given alone
:and (:priority "A"
:todo ("WAITING" "BLOCKED") :file-path "Drive")
:and (:priority "A"
:todo ("WAITING" "BLOCKED") :file-path "work.org"))
(:name "Important - Work"
;; Single arguments given alone
:and (:priority "A"
:todo ("TODO" "SOMEDAY") :file-path "Drive")
:and (:priority "A"
:todo ("TODO") :file-path "work.org"))
(:name "Other personal"
:and (:todo ("TODO" "SOMEDAY") :file-path "Dropbox" :not(:tag "eodroutine")))
(:name "Other work"
:and(:file-path "work.org" :todo ("TODO"))
:and(:file-path "Drive" :todo ("TODO")))
;; Set order of multiple groups at once
(:and(:priority<= "B"
;; Show this section after "Today" and "Important", because
;; their order is unspecified, defaulting to 0. Sections
;; are displayed lowest-number-first.
:order 0
:todo ("TODO" "IN-PROGRESS" "SOMEDAY")))
;; After the last group, the agenda will display items that didn't
;; match any of these groups, with the default order position of 99
(:name "Blocked"
:todo ("BLOCKED"))
(:name "Future Habits"
:and(:file-path "recurring.org" :deadline future))
(:name "Waiting"
:todo ("WAITING"))
(:name "EOD Routine"
:and(:todo "TODO" :file-path "recurring.org" :scheduled today :tag "eodroutine")
:and(:todo "TODO" :file-path "recurring.org" :scheduled past :tag "eodroutine")
)
(:name "Done"
:and(
:todo ("DONE" "OBSOLETE" "DELEGATED" "EXPORTED")
)
)))
(setq org-super-agenda-header-map (make-sparse-keymap))
(defun org-agenda-list-day () (interactive)
"Wrapper for org-agenda-list that just lists a single day"
(es/set-org-agenda-files)
(org-agenda-list 1)
)
(define-key evil-ex-map "a" 'org-agenda-list-day)
(define-key evil-ex-map "nw" 'es/set-nw-agenda)
(define-key evil-ex-map "yw" 'es/set-yw-agenda)
Binds :st
to “insert at end of line, append [/], C-cC-c it” for quick subtask adding.
(fset 'es/append-subtask-tracker
(kmacro-lambda-form [?A ? ?\[ ?/ ?\] escape ?\C-c ?\C-c] 0 "%d"))
(define-key evil-ex-map "st" 'es/append-subtask-tracker)
Enable log mode on start up to see what was completed when
(setq org-agenda-start-with-log-mode "state")
(load-theme 'manoj-dark)
(setq org-ellipsis "⤵")
(use-package org-bullets
:ensure t
:init
(add-hook 'org-mode-hook (lambda ()
(org-bullets-mode 1))))
Line numbering - absolute and relative.
(global-display-line-numbers-mode)
(setq display-line-numbers-type 'relative)
This makes emacs figure out the max line numbers beforehand - for longer files with thousands of lines, there is a little bump that happens when line numbers are displayed - this fixes that.
(setq display-line-numbers-width-start t)
WIP - Hide emphasis markers to make things a bit prettier.
bold italic underline literal
code
strikethrough
This first one is to get a different one for org-refile. I want it as C-r C-f (rf -> refile)
First thing to do is to set “C-r” as a possible prefix.
(define-prefix-command 'ring-map)
(global-set-key (kbd "C-r") 'ring-map)
Next thing to do is to remove “C-r” from the evil map (apparently it’s redo, which I never use).
Then we do the actual “C-r C-f” bind.
(define-key evil-normal-state-map (kbd "C-r") nil)
(global-set-key (kbd "C-r C-f") 'org-refile)
(define-key evil-ex-map "rf" 'org-refile)
Another one - archive. I’m gonna do “C-r C-a” for “refile - archive”, and because I have “C-r” as a prefix now.
(global-set-key (kbd "C-r C-a") 'org-archive-subtree)
(define-key evil-ex-map "ra" 'org-archive-subtree)
“C-r” is bound to something else, which I don’t use, and I’d rather be able to refile in insert mode as well.
(define-key evil-insert-state-map (kbd "C-r") nil)
;; (define-key evil-insert-state-map (kbd "C-r C-f"))
A lot of the below is from when I relied on C-[key] commands a la emacs style. Recently I’m moving to :[key][key] a la vim style since it’s easier for typing. As such, a lot of the below might be obsolete, but hey, I’m too lazy to go reconcile it. Plus, some of the spots where vim command mode doesn’t work (magit, agenda buffers) will still need C-w C-w.
(define-key evil-ex-map "ww" 'evil-window-next)
(define-key evil-ex-map "WW" 'evil-window-prev)
I use C-w C-w to switch windows a lot, but it messes me up when it deletes a word in insert mode.
(define-key evil-insert-state-map (kbd "C-w") nil)
(define-key evil-insert-state-map (kbd "C-w C-w") 'evil-window-next)
(define-key evil-insert-state-map (kbd "C-w w") 'evil-window-next)
I never really use the most recently used functionality, and would rather have C-w C-p and C-w p just do previous window, since that makes sense to me.
(define-key evil-motion-state-map (kbd "C-w C-p") 'evil-window-prev)
(define-key evil-insert-state-map (kbd "C-w C-p") 'evil-window-prev)
(define-key evil-insert-state-map (kbd "C-w p") 'evil-window-prev)
(define-key evil-motion-state-map (kbd "C-w p") 'evil-window-prev)
;; (define-key magit-status-mode-map (kbd "C-w") nil)
;; (define-key magit-status-mode-map (kbd "C-w C-w") 'evil-window-next)
;; (define-key magit-status-mode-map (kbd "C-w w") 'evil-window-next)
;; (define-key magit-status-mode-map (kbd "C-w C-p") 'evil-window-prev)
;; (define-key magit-status-mode-map (kbd "C-w C-p") 'evil-window-prev)
;; (define-key magit-status-mode-map (kbd "C-w p") 'evil-window-prev)
;; (define-key magit-status-mode-map (kbd "C-w p") 'evil-window-prev)
(setq w-keymap (make-sparse-keymap))
(define-prefix-command 'w-keymap)
(global-set-key (kbd "C-w") 'w-keymap)
(define-key magit-status-mode-map (kbd "C-w") nil)
(define-key magit-diff-mode-map (kbd "C-w") nil)
(global-set-key (kbd "C-w C-w") 'evil-window-next)
Make it so I can quickly reload emacs config.
(defun quick-refresh-dot-emacs ()
"Quickly reload emacs config"
(interactive)
(load-file user-init-file)
)
(global-set-key (kbd "C-r C-e") 'quick-refresh-dot-emacs)
(define-key evil-ex-map "re" 'quick-refresh-dot-emacs)
(define-key evil-ex-map "rir" 'helm-org-rifle-agenda-files)
(define-key evil-ex-map "ria" 'helm-org-rifle-occur-org-directory)
I’ll admit, there’s a header further up for this, but for some reason defining this that far up breaks, and I don’t really want
to figure out why org-agenda-mode-map
isn’t initiatlized up here
(define-key org-agenda-mode-map (kbd "C-w C-w") 'evil-window-next)
I am evil, so :
is special. It sets tags in agenda, which I basically never want to do.
(define-key org-agenda-mode-map (kbd ":") nil)
Evil shortcuts - helm menus, org capture. Basically replace any common C-[something] C-[something] I use with :[something][something]
A bunch of this is effectively recreating helm-config
- the file generated
from a shell script bundled with helm. It’s easier to roll these in my config so
I don’t have to boot from a clean slate, run some random sh, then boot again.
(define-key evil-ex-map "b" 'helm-buffers-list)
(define-key evil-ex-map "mx" 'helm-M-x)
(define-key evil-ex-map "dd" 'helm-apropos)
(define-key evil-ex-map "e" 'helm-find-files)
(define-key evil-ex-map "t" 'org-todo)
(define-key evil-ex-map "co" 'org-open-at-point)
(define-key evil-ex-map "dk" 'describe-key)
(define-key evil-ex-map "dp" 'describe-package)
(define-key evil-ex-map "oc" 'org-capture)
(define-key evil-ex-map "mg" 'magit)
(define-key evil-ex-map "k8s" 'k8s)
(define-key evil-ex-map "cs" 'org-schedule)
(define-key evil-ex-map "c!" 'org-time-stamp-inactive)
(define-key evil-ex-map "ce" 'org-export-dispatch)
(define-key evil-ex-map "kb" 'kill-buffer)
(define-key evil-ex-map "cl" 'org-insert-link)
(define-key evil-ex-map "osl" 'org-store-link)
(define-key evil-ex-map "cni" 'org-roam-node-insert)
(define-key evil-ex-map "xe" 'eval-last-sexp)
(defun es/save-all ()
"Thin wrapper around saving all buffers"
(interactive)
(save-some-buffers t))
(define-key evil-ex-map "sa" 'es/save-all)
Normal map for opening links - remap “go” to do it.
Inspired by vim’s gf
and gx
but go
is easier to type.
(define-key evil-normal-state-map "go" 'org-open-at-point)
(evil-define-key 'motion org-agenda-mode-map (kbd "go") 'org-open-at-point)
Quick binding for C-cC-c using evil command mode.
(fset 'do-the-thing
(kmacro-lambda-form [?\C-c ?\C-c] 0 "%d"))
(define-key evil-ex-map "dtt" 'do-the-thing)
(define-key evil-ex-map "cc" 'do-the-thing)
Unset shift+right for evil insert, because sometimes it overrides org. I never use it anyway.
(define-key evil-insert-state-map (kbd "S-<right>") nil)
Sticks a priority A todo for today afte the current org node. https://emacs.stackexchange.com/questions/19210/how-to-insert-a-new-same-level-headline-after-current-one
(defalias 'dotoday
(kmacro "C-<return> S-<right> C-c C-s <return> S-<up> S-<up> A"))
(define-key evil-ex-map "dtd" 'dotoday)
Do today, but with priority b
(defalias 'dotodayb
(kmacro "C-<return> S-<right> C-c C-s <return> S-<up> A"))
(define-key evil-ex-map "dtb" 'dotodayb)
Do tomorrow
(defalias 'dotmrw
(kmacro "C-<return> S-<right> C-c C-s S-<right> <return> S-<up> S-<up> A"))
(define-key evil-ex-map "dtm" 'dotmrw)
Insert a do today header, but indented one level from the current header.
(defalias 'doindenttoday
(kmacro "o M-<return> M-<right> S-<right> S-<up> S-<up> C-c C-s <return>"))
(define-key evil-ex-map "dit" 'doindenttoday)
Do to inbox - experimenting with an inbox view in org-agenda.
(fset 'do-inbox
(kmacro-lambda-form [?\C-u ?\C-u ?\C-c ?\C-x ?M ?\C-c ?\C-c ?i ?n ?b ?o ?x ?\C-m ?\C-c ?\C-s ?\C-m ?a ?\C-\[ ?x ?e ?n ?d ?- ?k ?b ?\C-i] 0 "%d"))
(define-key evil-ex-map "dti" 'do-inbox)
Let’s me break up an org source block so I can document in between more easily
(fset 'split-src-block
(kmacro-lambda-form [?i ?# ?+ ?b ?e ?g ?i ?n ?_ ?s ?e ?r ?c ?\C-? ?\C-? ?\C-? ?r ?c ? ?e ?m ?a ?c ?s ?- ?l ?i ?s ?t ?p ?\C-? ?\C-? ?p escape ?O ?# ?+ ?e ?n ?d ?_ ?s ?r ?c escape ?j ?I ?\C-\[ ?O ?C ?\C-? escape] 0 "%d"))
(define-key evil-ex-map "srcsplit" 'split-src-block)
Shortcut to make a link called “thread”. Useful for when I want to stamp a link from a slack thread thread
(fset 'thread
(kmacro-lambda-form [?: ?c ?l ?\C-m ?t ?h ?r ?e ?a ?d ?\C-m] 0 "%d"))
(define-key evil-ex-map "ctl" 'thread)
(fset 'pr-link
(kmacro-lambda-form [?: ?c ?l ?\C-m ?p ?r ?\C-m] 0 "%d"))
(define-key evil-ex-map "cpl" 'pr-link)
(fset 'link-link
(kmacro-lambda-form [?: ?c ?l ?\C-m ?l ?i ?n ?k ?\C-m] 0 "%d"))
(define-key evil-ex-map "ckl" 'link-link)
ex map shortcut to recover a file
(define-key evil-ex-map "rtf" 'recover-this-file)
Rebind normal C-i to C-j
(define-key evil-normal-state-map (kbd "C-j") 'evil-jump-forward)
Rebind normal C-o to C-k
(define-key evil-normal-state-map (kbd "C-k") 'evil-jump-backward)
A bunch of “do this motion, then center the screen” type changes. There’s probably some better way to curry these but I’m not good enough at elisp.
(defun es/evil-then-center (lambda)
"Wrapper for any motion to motion, then center the screen"
(funcall lambda)
(evil-scroll-line-to-center nil)
)
(defun es/search-center ()
"wrapper to center after search"
(interactive)
(es/evil-then-center 'evil-search-next)
)
(define-key evil-motion-state-map (kbd "n") 'es/search-center)
(defun es/search-rev-center ()
"wrapper to center after reverse search"
(interactive)
(es/evil-then-center 'evil-search-previous)
)
(define-key evil-motion-state-map (kbd "N") 'es/search-rev-center)
(defun es/search-word-center ()
"wrapper to center after word search"
(interactive)
(es/evil-then-center 'evil-search-word-forward)
)
(define-key evil-motion-state-map (kbd "*") 'es/search-word-center)
(defun es/search-word-rev-center ()
"wrapper to center after reverse word search"
(interactive)
(es/evil-then-center 'evil-search-word-backward)
)
(define-key evil-motion-state-map (kbd "#") 'es/search-word-rev-center)
Yank doesn’t quite do the trick with things, so make a custom one. https://emacs.stackexchange.com/questions/10900/copy-text-from-emacs-to-os-x-clipboard
Also add pp
to do visual paste, since pc
overrides it.
(fset 'pbcopy
(kmacro-lambda-form [?\C-\[ ?| ?p ?b ?c ?o ?p ?y ?\C-m] 0 "%d"))
(define-key evil-visual-state-map "pc" 'pbcopy)
(define-key evil-visual-state-map "pp" 'evil-paste-after)
(define-key evil-visual-state-map "cl" 'org-insert-link)
(define-key evil-visual-state-map "cc" 'evil-change)
Trying to see what this does on startup so I can optimize my init/dotfiles.
;;(setq message-log-max t)
(defadvice org-agenda (around split-vertically activate)
(let ((split-width-threshold 300)) ; or whatever width makes sense for you
ad-do-it))
(add-hook 'text-mode-hook 'visual-line-mode)
Inbox directory
(setq org-default-notes-file "~/Dropbox/org/inbox.org")
Stick backup files elsewhere. They screw up IFTTT’s dropbox integration for some reason.
(setq backup-directory-alist `(("." . "./.emacsSaves")))
Start server
(load "server")
(unless (server-running-p) (server-start))
Capture templates
(setq org-capture-templates
'(("p" "Personal" entry (file "~/Dropbox/org/inbox.org")
"* TODO %?\n")
("w" "Work" entry (file "~/Dropbox/org/projects/workInbox.org")
"* TODO %?\n")
("t" "Things on my mind" entry (file "~/Dropbox/org/projects/tList.org")
"* TODO %?\n" )
("s" "Stuff" entry (file "~/Dropbox/org/projects/stuff.org")
"* TODO %?\n")))
(use-package powerline-evil
:config
(powerline-evil-center-color-theme))
This is a hack because I probably have a bad config on my ubuntu machine. For some reason, string-empty-p
isn’t defined at runtime, but when I describe-function
it, it shows up.
This breaks org-agenda. Requring subr-x
at startup fixes this.
(require 'subr-x)
Ubuntu specific (hopefully this doesn’t break mac!) - this forces org to update to a later version.
(use-package org :ensure org-contrib :pin org)
More hacks to force dependencies into place, hopefully.
(require 'org-macs)
The default styles are gross. I use google docs all day erry day. This is an ODT file that has the headers for google docs.
This seems to barf on multiline source blocks, but I don’t use that for notes much, so that’s ok (typically the last line of a source block is unstyled).
(setq org-odt-styles-file (concat (getenv "PATH_TO_DOTFILES_REPO") "/gdocStyles.odt"))
Table of contents is ugly, and google doc styles do it for you anyway (in google docs)
(setq org-export-with-toc nil)
So this is an attempt to make people in a meeting todos, and then use todos to quickly flag who is speaking as I’m taking notes. You can only do todo states on headers by default, so I’m using inlinetask to try and use todo states elsewhere.
Update: Doesn’t quite work the way I want, it renders kinda ugly in a huge block. If I’m indented far enough (5?) the todo states seem to work. Keeping because this is needed for the meeting minutes stuff below.
Update: four *s seems to work to not use a header, which will work for me.
(require 'org-inlinetask)
This seems interesting. Try it out. Update - as of [2021-08-28 Sat]ish, I basically use roam for notes now, and having roam nodes for people makes it easy to add attendees. This was an interesting experiment, but I’m mostly not using it at this point.
(require 'org)
(require 'dash)
(defun org-actionitems-extract-entry ()
(-let* ((entries (org-entry-properties))
((&alist "ITEM" "TODO" "DEADLINE") entries))
(list ITEM TODO DEADLINE)))
(defun org-dblock-write:actionitems (params)
(let ((match (or (plist-get params :match) "/+TODO")))
(insert-before-markers "| What | Who | When |\n")
(insert-before-markers "|-\n")
(let* ((tasks (org-map-entries 'org-actionitems-extract-entry match))
(rows (-map (lambda (task)
(->> task
(-map (lambda (item) (or item "")))
(apply 'format "| %s | %s | %s |")))
tasks))
(table (string-join rows "\n")))
(insert-before-markers table))
(org-table-align)))
https://github.com/arnm/ob-mermaid Install this in “~/” or else!
(use-package ob-mermaid)
(setq ob-mermaid-cli-path "~/node_modules/.bin/mmdc")
This is what this ends up looking like. Keeping it here as an example - this is just the thing that the mermaid live editor ships with.
graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
Use sensible defaults from the git submodule.
(load-file (concat (getenv "PATH_TO_DOTFILES_REPO") "/sensible-defaults.el/sensible-defaults.el"))
(sensible-defaults/use-all-settings)
(sensible-defaults/use-all-keybindings)
Trim whitespace
(add-hook 'write-file-hooks 'delete-trailing-whitespace)
Don’t prompt for exit - this must be after sensible defaults, as it overwrites it.
(setq confirm-kill-emacs nil)
(setq org-outline-path-complete-in-steps nil)
(setq helm-completion-style 'helm-flex)
(add-to-list 'completion-styles 'helm-flex)
(setq helm-apropos-fuzzy-match t)
(setq helm-locate-fuzzy-match t)
(setq helm-mode-fuzzy-match t)
Override M-x
(global-set-key (kbd "M-x") 'helm-M-x)
(setq find-file-visit-truename t)
Probably need to change the viewer per OS.
(setq org-roam-graph-executable "neato")
(setq org-roam-db-location "~/org/roam/org-roam.db")
(setq org-roam-graph-viewer "/usr/bin/open")
(use-package org-roam
:ensure t
:init
(setq org-roam-v2-ack t)
:custom
(org-roam-directory (file-truename "~/org/roam"))
(org-roam-completion-everywhere t)
: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)
("C-c n d" . org-roam-dailies-capture-today)
:map org-mode-map
("C-M-i" . completion-at-point))
:config
(org-roam-setup)
;; If using org-roam-protocol
(require 'org-roam-protocol))
Roam ex map bindings
(define-key evil-ex-map "ni" 'org-roam-node-insert)
(define-key evil-ex-map "nf" 'org-roam-node-find)
(define-key evil-ex-map "nb" 'org-roam-buffer-toggle)
Capture templates for roam
(setq org-roam-capture-templates
'(
("n" "normal" plain "%?"
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org"
"#+title: ${title}")
:unnarrowed t)
("f" "fun" plain "%?"
:if-new (file+head "fun/%<%Y%m%d%H%M%S>-${slug}.org"
"#+title: ${title}\n#+filetags: fun\n")
:unnarrowed t)
("w" "work" plain "%?"
:if-new (file+head "work/%<%Y%m%d%H%M%S>-${slug}.org"
"#+title: ${title}")
:unnarrowed t)
))
(setq org-roam-node-display-template "${title:30}")
Synchronize cache on startup
(org-roam-db-sync)
Dailies go here
(setq org-roam-dailies-directory "daily/")
Workflow to link things from agenda to daily note to more intentionally curate todo list. Taken from this post.
This doesn’t quite seem to work yet - I suspect it doesn’t play nice with super agenda
(setq org-agenda-custom-commands
'(("d" "Daily schedule"
((agenda ""
((org-agenda-span 'day)
(org-agenda-use-time-grid nil)
(org-agenda-skip-function '(org-agenda-skip-entry-if 'scheduled 'deadline))))))))
(defun as/get-daily-agenda (&optional date)
"Return the agenda for the day as a string."
(interactive)
(let ((file (make-temp-file "daily-agenda" nil ".txt")))
(org-agenda nil "d" nil)
(when date (org-agenda-goto-date date))
(org-agenda-write file nil nil "*Org Agenda*")
(kill-buffer)
(with-temp-buffer
(insert-file-contents file)
(goto-char (point-min))
(kill-line 2)
(while (re-search-forward "^ " nil t)
(replace-match "- " nil nil))
(buffer-string))))
This is the bit referenced above that inserts the target header as a link into the org roam note. Pretty handy!
(defun es/org-roam-header (title)
"Formats a roam title with the suffix"
(concat "#+title: %<%Y-%m-%d (%A)> - " title "\n#+startup: showall\n"
"* Do Today\n* Journal\n")
)
; (setq org-roam-head
; (concat "#+title: %<%Y-%m-%d (%A)>\n#+startup: showall\n"
; "* Do Today\n* Journal\n"))
(setq personal-header (es/org-roam-header "Personal"))
(setq work-header (es/org-roam-header "Work"))
(setq personal-dir "~/Dropbox/org/roam/daily/")
(setq work-dir "~/org/roam/daily/")
(setq org-daily-filename "%<%Y-%m-%d>.org")
(setq personal-file (concat personal-dir org-daily-filename))
(setq work-file (concat work-dir org-daily-filename))
(setq org-roam-dailies-capture-templates
`(("j" "journal" entry
"* %<%H:%M> %?"
:if-new (file+head+olp ,personal-file ,personal-header ("Journal")))
("t" "do today - work" entry
"** TODO [#A] %a\nSCHEDULED: <%<%Y-%m-%d>>"
:if-new (file+head+olp ,work-file ,work-header ("Do Today"))
:immediate-finish t)
("p" "do today - personal" entry
"** TODO [#A] %a\nSCHEDULED: <%<%Y-%m-%d>>"
:if-new (file+head+olp ,personal-file ,personal-header ("Do Today"))
:immediate-finish t)
))
Make a shortcut in org agenda to cap something.
(evil-define-key 'motion org-agenda-mode-map (kbd "c") 'org-roam-dailies-capture-today)
Quick jump to work or personal daily node.
(defun es/open-roam-daily-today (target)
"Thin wrapper around org-roam-dailies-goto-today that also saves the file."
(org-roam-dailies-goto-today target)
(save-buffer)
)
(defun es/open-daily-work-buffer ()
""
(interactive)
(es/open-roam-daily-today "t")
(es/set-org-agenda-files)
)
(defun es/open-daily-personal-buffer ()
""
(interactive)
(es/open-roam-daily-today "p")
(es/set-org-agenda-files)
)
(define-key evil-ex-map "rd" 'es/open-daily-work-buffer)
(define-key evil-ex-map "rp" 'es/open-daily-personal-buffer)
(use-package websocket)
(use-package simple-httpd)
(use-package org-roam-ui)
(define-key evil-ex-map "oru" 'org-roam-ui-open)
(use-package fish-mode)
(use-package graphql-mode)
(use-package go-mode)
(use-package protobuf-mode)
Probably do something like this
Starting to play with this and see how it works.
(use-package tree-sitter)
(use-package tree-sitter-langs)
This is an attempt to hit the notion api in order to dump tasks out of org into notion.
My anticipated workflow is, while grooming my inbox, instead of refiling an item, I export it to Notion via POST.
Then I mark the item EXPORTED (custom TODO state) and archive it.
This is also the first elisp I’m writing on my own, so it’s a learning experience.
Thus far I’ve managed to extract the todo state and map it to the todo status I use in notion.
Next, I need to format a payload with local secrets (api key) and hit the api. It looks like the preferred way to do this in emacs is request.el.
(require 'org-element)
;; make a function that gets the org heading components as an alist mapped to the things in notion
;; make a function that json encodes that
;; make a function to call the api
(defun org-todo-to-notion-todo (org-todo)
"map org todo status to notion status - you should change this to fit whatever todo statuses you have"
(plist-get '(TODO "To Do" IN-PROGRESSS "Doing" DONE "Done") (intern org-todo)))
(defun org-heading-to-notion-json ()
"Encode current heading as json"
(let* ((ohc (org-heading-components))
(todo-state (nth 2 ohc))
(notion-todo-state (org-todo-to-notion-todo todo-state)))
(message notion-todo-state)))
Font size default
(set-face-attribute 'default nil :height 140)